[Engine] Updating fabric generator to support BL/WL shift registers. Still WIP
This commit is contained in:
parent
afd03d7eb7
commit
834bdd2b07
|
@ -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 */
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue