[Engine] Updating fabric generator to support BL/WL shift registers. Still WIP

This commit is contained in:
tangxifan 2021-09-28 17:29:03 -07:00
parent afd03d7eb7
commit 834bdd2b07
4 changed files with 331 additions and 3 deletions

View File

@ -13,10 +13,18 @@ namespace openfpga {
/* Top-level module name */
constexpr char* FPGA_TOP_MODULE_NAME = "fpga_top";
/* Configuration chain naming constant strings */
constexpr char* CONFIGURABLE_MEMORY_CHAIN_IN_NAME = "ccff_head";
constexpr char* CONFIGURABLE_MEMORY_CHAIN_OUT_NAME = "ccff_tail";
constexpr char* CONFIGURABLE_MEMORY_DATA_OUT_NAME = "mem_out";
constexpr char* CONFIGURABLE_MEMORY_INVERTED_DATA_OUT_NAME = "mem_outb";
constexpr char* BL_SHIFT_REGISTER_CHAIN_HEAD_NAME = "bl_sr_head";
constexpr char* BL_SHIFT_REGISTER_CHAIN_TAIL_NAME = "bl_sr_tail";
constexpr char* BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME = "bl_sr_bl_out";
constexpr char* WL_SHIFT_REGISTER_CHAIN_HEAD_NAME = "wl_sr_head";
constexpr char* WL_SHIFT_REGISTER_CHAIN_TAIL_NAME = "wl_sr_tail";
constexpr char* WL_SHIFT_REGISTER_CHAIN_WL_OUT_NAME = "wl_sr_wl_out";
constexpr char* WL_SHIFT_REGISTER_CHAIN_WLR_OUT_NAME = "wl_sr_wlr_out";
/* IO PORT */
/* Prefix of global input, output and inout ports of FPGA fabric */

View File

@ -30,6 +30,108 @@
/* begin namespace openfpga */
namespace openfpga {
/*********************************************************************
* BL shift register chain module organization
*
* +-------+ +-------+ +-------+
* chain --->| CCFF |--->| CCFF |--->... --->| CCFF |---->chain
* input&clock | [0] | | [1] | | [N-1] | output
* +-------+ +-------+ +-------+
* | | ... | config-memory output
* v v v
* +-----------------------------------------+
* | BLs of configurable modules |
*
********************************************************************/
static
void build_bl_shift_register_chain_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::string& module_name,
const CircuitModelId& sram_model,
const size_t& num_mems) {
/* Get the input ports from the SRAM */
std::vector<CircuitPortId> sram_input_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_INPUT, true);
VTR_ASSERT(1 == sram_input_ports.size());
/* Get the output ports from the SRAM */
std::vector<CircuitPortId> sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
VTR_ASSERT(1 == sram_output_ports.size());
/* Get the BL ports from the SRAM */
std::vector<CircuitPortId> sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true);
VTR_ASSERT(1 == sram_bl_ports.size());
/* Create a module and add to the module manager */
ModuleId mem_module = module_manager.add_module(module_name);
VTR_ASSERT(true == module_manager.valid_module_id(mem_module));
/* Label module usage */
module_manager.set_module_usage(mem_module, ModuleManager::MODULE_CONFIG);
/* Add an input port, which is the head of configuration chain in the module */
/* TODO: restriction!!!
* consider only the first input of the CCFF model as the D port,
* which will be connected to the head of the chain
*/
BasicPort chain_head_port(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME,
circuit_lib.port_size(sram_input_ports[0]));
module_manager.add_port(mem_module, chain_head_port, ModuleManager::MODULE_INPUT_PORT);
/* Add an output port, which is the tail of configuration chain in the module */
/* TODO: restriction!!!
* consider only the first output of the CCFF model as the Q port,
* which will be connected to the tail of the chain
*/
BasicPort chain_tail_port(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME,
circuit_lib.port_size(sram_output_ports[0]));
module_manager.add_port(mem_module, chain_tail_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Add the output ports to output BL signals */
BasicPort chain_bl_port(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME,
num_mems);
module_manager.add_port(mem_module, chain_bl_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Find the sram module in the module manager */
ModuleId sram_mem_module = module_manager.find_module(circuit_lib.model_name(sram_model));
/* Instanciate each submodule */
for (size_t i = 0; i < num_mems; ++i) {
size_t sram_mem_instance = module_manager.num_instance(mem_module, sram_mem_module);
module_manager.add_child_module(mem_module, sram_mem_module);
module_manager.add_configurable_child(mem_module, sram_mem_module, sram_mem_instance);
/* Build module nets to wire bl outputs of sram modules to BL outputs of memory module */
for (size_t iport = 0; iport < num_bl_ports; ++iport) {
CircuitPortId child_module_output_port = sram_bl_ports[iport];
std::string chain_output_port_name = std::string(BL_SHIFT_REGISTER_CHAIN_BL_OUT_NAME);
std::vector<ModuleNetId> output_nets = add_module_output_nets_to_chain_mem_modules(module_manager, mem_module,
chan_output_port_name, circuit_lib,
child_module_output_port,
sram_mem_module, i, sram_mem_instance);
}
}
/* Build module nets to wire the configuration chain */
add_module_nets_to_cmos_memory_config_chain_module(module_manager, mem_module,
circuit_lib, sram_input_ports[0], sram_output_ports[0]);
/* If there is a second input defined,
* add nets to short wire the 2nd inputs to the first inputs
*/
if (2 == sram_input_ports.size()) {
add_module_nets_to_cmos_memory_scan_chain_module(module_manager, mem_module,
circuit_lib, sram_input_ports[1], sram_output_ports[0]);
}
/* Add global ports to the pb_module:
* This is a much easier job after adding sub modules (instances),
* we just need to find all the global ports from the child modules and build a list of it
*/
add_module_global_ports_from_child_modules(module_manager, mem_module);
}
/*********************************************************************
* This function to add nets for quicklogic memory banks
* Each configuration region has independent memory bank circuitry
@ -640,6 +742,161 @@ void add_top_module_nets_cmos_ql_memory_bank_bl_flatten_config_bus(ModuleManager
}
}
/*********************************************************************
* This function to add nets for quicklogic memory banks using shift registers to manipulate BL/WLs
* Each configuration region has independent BL/WL shift register banks
* - Find the number of BLs and WLs required for each region
* - Find the number of BL and WL shift register chains required for each region
* - Create the module of shift register chain for each unique size
* - Create nets to connect from top-level module inputs to BL/WL shift register chains
* - Create nets to connect from BL/WL shift register chains to BL/WL of configurable children
*
* @note this function only adds the BL protocol
*
* Detailed schematic of each memory bank:
* @note The numbers are just made to show a simplified example, practical cases are more complicated!
*
* sr_clk sr_head sr_tail
* | | ^
* v v |
* +-------------------------------------------------+
* | Bit Line shift register chains |
* +-------------------------------------------------+
* | | |
* +---------+ BL[0:9] BL[10:17] BL[18:22]
* | | | | |
* | | | | |
* | Word |--WL[0:3]-->-----------+---------------+---- ... |------+-->
* | | | | | | | |
* | Line | | v | v | v
* | | | +-------+ | +-------+ | +------+
* | shift | +-->| SRAM | +-->| SRAM | +->| SRAM |
* | | | | [0:8] | | | [0:5] | ... | | [0:7]|
* | register| | +-------+ | +-------+ | +------+
* | | | | |
* | chains |--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_shift_register_config_bus(ModuleManager& module_manager,
const ModuleId& top_module,
const CircuitLibrary& circuit_lib,
const ConfigProtocol& config_protocol) {
CircuitModelId sram_model = config_protocol.memory_model();
CircuitModelId bl_memory_model = config_protocol.bl_memory_model();
/* Find out the unique shift register chain sizes */
std::vector<size_t> unique_sr_sizes;
for (const ConfigRegionId& config_region : module_manager.regions(top_module)) {
/* TODO: Need to find how to cut the BLs when there are multiple banks for shift registers in a region */
size_t num_bls = compute_memory_bank_regional_num_bls(module_manager, top_module,
config_region,
circuit_lib, sram_model);
unique_sr_sizes.push_back(num_bls);
}
/* TODO: Build submodules for shift register chains */
//for (const size_t& sr_size : unique_sr_sizes) {
// std::string sr_module_name = generate_bl_shift_register_module_name(bl_memory_model, sr_size);
// ModuleId sr_bank_module = build_bl_shift_register_chain_module(module_manager,
// circuit_lib,
// sr_module_name,
// bl_memory_model,
// sr_size);
//}
/* TODO: Instanciate the shift register chains in the top-level module */
//module_manager.add_child_module(top_module, sr_bank_module);
/* TODO: create connections between top-level module and the BL shift register banks */
/* 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
@ -778,7 +1035,7 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
break;
}
case BLWL_PROTOCOL_SHIFT_REGISTER: {
/* TODO */
add_top_module_nets_cmos_ql_memory_bank_bl_shift_register_config_bus(module_manager, top_module, circuit_lib, config_protocol);
break;
}
default: {
@ -872,7 +1129,14 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
break;
}
case BLWL_PROTOCOL_SHIFT_REGISTER: {
/* TODO */
/* Each region will have independent shift register banks */
for (const ConfigRegionId& config_region : module_manager.regions(module_id)) {
size_t num_heads = config_protocol.bl_num_banks();
BasicPort blsr_head_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads);
module_manager.add_port(module_id, blsr_head_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort blsr_tail_port(generate_regional_blwl_port_name(std::string(BL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads);
module_manager.add_port(module_id, blsr_tail_port, ModuleManager::MODULE_INPUT_PORT);
}
break;
}
default: {
@ -914,7 +1178,14 @@ void add_top_module_ql_memory_bank_sram_ports(ModuleManager& module_manager,
break;
}
case BLWL_PROTOCOL_SHIFT_REGISTER: {
/* TODO */
/* Each region will have independent shift register banks */
for (const ConfigRegionId& config_region : module_manager.regions(module_id)) {
size_t num_heads = config_protocol.wl_num_banks();
BasicPort wlsr_head_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_HEAD_NAME), config_region), num_heads);
module_manager.add_port(module_id, wlsr_head_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort wlsr_tail_port(generate_regional_blwl_port_name(std::string(WL_SHIFT_REGISTER_CHAIN_TAIL_NAME), config_region), num_heads);
module_manager.add_port(module_id, wlsr_tail_port, ModuleManager::MODULE_INPUT_PORT);
}
break;
}
default: {

View File

@ -84,6 +84,22 @@ size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager,
return num_blwls;
}
size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager,
const ModuleId& top_module,
const ConfigRegionId& config_region,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model) {
size_t num_bls = 0;
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];
num_bls += find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_BL);
}
return num_bls;
}
std::map<int, size_t> compute_memory_bank_regional_bitline_numbers_per_tile(const ModuleManager& module_manager,
const ModuleId& top_module,
const ConfigRegionId& config_region,
@ -100,6 +116,22 @@ std::map<int, size_t> compute_memory_bank_regional_bitline_numbers_per_tile(cons
return num_bls_per_tile;
}
size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager,
const ModuleId& top_module,
const ConfigRegionId& config_region,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model) {
size_t num_wls = 0;
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];
num_wls += find_module_ql_memory_bank_num_blwls(module_manager, child_module, circuit_lib, sram_model, CONFIG_MEM_QL_MEMORY_BANK, CIRCUIT_MODEL_PORT_WL);
}
return num_wls;
}
std::map<int, size_t> compute_memory_bank_regional_wordline_numbers_per_tile(const ModuleManager& module_manager,
const ModuleId& top_module,
const ConfigRegionId& config_region,

View File

@ -48,6 +48,14 @@ size_t find_module_ql_memory_bank_num_blwls(const ModuleManager& module_manager,
const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type,
const e_circuit_model_port_type& circuit_port_type);
/**
* @brief Precompute the total number of bit lines required by a specific configuration region
*/
size_t compute_memory_bank_regional_num_bls(const ModuleManager& module_manager,
const ModuleId& top_module,
const ConfigRegionId& config_region,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model);
/**
* @brief Precompute the number of bit lines required by each tile under a specific configuration region
@ -60,6 +68,15 @@ std::map<int, size_t> compute_memory_bank_regional_bitline_numbers_per_tile(cons
const ConfigRegionId& config_region,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model);
/**
* @brief Precompute the total number of word lines required by a specific configuration region
*/
size_t compute_memory_bank_regional_num_wls(const ModuleManager& module_manager,
const ModuleId& top_module,
const ConfigRegionId& config_region,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model);
/**
* @brief Precompute the number of word lines required by each tile under a specific configuration region
* @note