Refactoring Verilog generation intermediate level of pb_types and SRAM port generation
This commit is contained in:
parent
b3ca0d32a4
commit
d1948c82eb
|
@ -295,3 +295,104 @@ bool check_mem_config_bus(const e_sram_orgz& sram_orgz_type,
|
|||
/* Reach here, it means something goes wrong, return a false value */
|
||||
return false;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate a list of ports that are used for SRAM configuration to a module
|
||||
* The type and names of added ports strongly depend on the
|
||||
* organization of SRAMs.
|
||||
* 1. Standalone SRAMs:
|
||||
* two ports will be added, which are regular output and inverted output
|
||||
* 2. Scan-chain Flip-flops:
|
||||
* two ports will be added, which are the head of scan-chain
|
||||
* and the tail of scan-chain
|
||||
* IMPORTANT: the port size will be forced to 1 in this case
|
||||
* because the head and tail are both 1-bit ports!!!
|
||||
* 3. Memory decoders:
|
||||
* 2-4 ports will be added, depending on the ports available in the SRAM
|
||||
* Among these, two ports are mandatory: BL and WL
|
||||
* The other two ports are optional: BLB and WLB
|
||||
* Note that the constraints are correletated to the checking rules
|
||||
* in check_circuit_library()
|
||||
********************************************************************/
|
||||
std::vector<std::string> generate_sram_port_names(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_sram_orgz sram_orgz_type) {
|
||||
std::vector<std::string> sram_port_names;
|
||||
/* Prepare a list of port types to be added, the port type will be used to create port names */
|
||||
std::vector<e_spice_model_port_type> model_port_types;
|
||||
|
||||
switch (sram_orgz_type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_INPUT);
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_INPUT);
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK: {
|
||||
std::vector<e_spice_model_port_type> ports_to_search;
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_BL);
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_WL);
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_BLB);
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_WLB);
|
||||
/* Try to find a BL/WL/BLB/WLB port and update the port types/module port types to be added */
|
||||
for (const auto& port_to_search : ports_to_search) {
|
||||
std::vector<CircuitPortId> found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search);
|
||||
if (0 == found_port.size()) {
|
||||
continue;
|
||||
}
|
||||
model_port_types.push_back(port_to_search);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Add ports to the module manager */
|
||||
for (size_t iport = 0; iport < model_port_types.size(); ++iport) {
|
||||
/* Create a port */
|
||||
std::string port_name = generate_sram_port_name(sram_orgz_type, model_port_types[iport]);
|
||||
sram_port_names.push_back(port_name);
|
||||
}
|
||||
|
||||
return sram_port_names;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate a list of ports that are used for SRAM configuration to a module
|
||||
* 1. Standalone SRAMs:
|
||||
* use the suggested port_size
|
||||
* 2. Scan-chain Flip-flops:
|
||||
* IMPORTANT: the port size will be forced to 1 in this case
|
||||
* 3. Memory decoders:
|
||||
* use the suggested port_size
|
||||
********************************************************************/
|
||||
size_t generate_sram_port_size(const e_sram_orgz sram_orgz_type,
|
||||
const size_t& num_config_bits) {
|
||||
size_t sram_port_size = num_config_bits;
|
||||
|
||||
switch (sram_orgz_type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
/* CCFF head/tail are single-bit ports */
|
||||
sram_port_size = 1;
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return sram_port_size;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,4 +24,11 @@ bool check_mem_config_bus(const e_sram_orgz& sram_orgz_type,
|
|||
const BasicPort& config_bus,
|
||||
const size_t& local_expected_msb);
|
||||
|
||||
std::vector<std::string> generate_sram_port_names(const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_sram_orgz sram_orgz_type);
|
||||
|
||||
size_t generate_sram_port_size(const e_sram_orgz sram_orgz_type,
|
||||
const size_t& num_config_bits);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -442,9 +442,9 @@ void ModuleManager::add_child_module(const ModuleId& parent_module, const Module
|
|||
|
||||
/* Update fast look-up for nets */
|
||||
size_t instance_id = net_lookup_[parent_module][child_module].size();
|
||||
net_lookup_[parent_module][child_module].emplace_back();
|
||||
/* Find the ports for the child module and update the fast look-up */
|
||||
for (ModulePortId child_port : port_ids_[child_module]) {
|
||||
net_lookup_[parent_module][child_module].emplace_back();
|
||||
net_lookup_[parent_module][child_module][instance_id][child_port].resize(ports_[child_module][child_port].get_width(), ModuleNetId::INVALID());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,6 +133,7 @@ void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_
|
|||
module_manager.set_port_preproc_flag(module_id, port_id, preproc_flag);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Add a list of ports that are used for SRAM configuration to a module
|
||||
* in the module manager
|
||||
|
@ -157,60 +158,15 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager,
|
|||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_sram_orgz sram_orgz_type,
|
||||
const size_t& port_size) {
|
||||
/* Prepare a list of port types to be added, the port type will be used to create port names */
|
||||
std::vector<e_spice_model_port_type> model_port_types;
|
||||
/* Prepare a list of module port types to be added, the port type will be used to specify the port type in Verilog/SPICE module */
|
||||
std::vector<ModuleManager::e_module_port_type> module_port_types;
|
||||
/* Actual port size may be different from user specification. Think about CCFF */
|
||||
size_t sram_port_size = port_size;
|
||||
|
||||
switch (sram_orgz_type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_INPUT);
|
||||
module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||
module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
|
||||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_INPUT);
|
||||
module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
|
||||
model_port_types.push_back(SPICE_MODEL_PORT_OUTPUT);
|
||||
module_port_types.push_back(ModuleManager::MODULE_OUTPUT_PORT);
|
||||
/* CCFF head/tail are single-bit ports */
|
||||
sram_port_size = 1;
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK: {
|
||||
std::vector<e_spice_model_port_type> ports_to_search;
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_BL);
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_WL);
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_BLB);
|
||||
ports_to_search.push_back(SPICE_MODEL_PORT_WLB);
|
||||
/* Try to find a BL/WL/BLB/WLB port and update the port types/module port types to be added */
|
||||
for (const auto& port_to_search : ports_to_search) {
|
||||
std::vector<CircuitPortId> found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search);
|
||||
if (0 == found_port.size()) {
|
||||
continue;
|
||||
}
|
||||
model_port_types.push_back(port_to_search);
|
||||
module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
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);
|
||||
|
||||
/* Add ports to the module manager */
|
||||
for (size_t iport = 0; iport < model_port_types.size(); ++iport) {
|
||||
/* Create a port */
|
||||
std::string port_name = generate_sram_port_name(sram_orgz_type, model_port_types[iport]);
|
||||
BasicPort module_port(port_name, sram_port_size);
|
||||
for (const std::string& sram_port_name : sram_port_names) {
|
||||
/* Add generated ports to the ModuleManager */
|
||||
module_manager.add_port(module_id, module_port, module_port_types[iport]);
|
||||
BasicPort sram_port(sram_port_name, sram_port_size);
|
||||
module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,9 +178,9 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager,
|
|||
* This function will also check that each pb_type port is actually exist
|
||||
* in the linked circuit model
|
||||
*******************************************************************/
|
||||
void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
t_pb_type* cur_pb_type) {
|
||||
void add_primitive_pb_type_ports_to_module_manager(ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
t_pb_type* cur_pb_type) {
|
||||
|
||||
/* Find the inout ports required by the primitive pb_type, and add them to the module */
|
||||
std::vector<t_port*> pb_type_inout_ports = find_pb_type_ports_match_circuit_model_port_type(cur_pb_type, SPICE_MODEL_PORT_INOUT);
|
||||
|
@ -263,6 +219,32 @@ void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
|
|||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Add ports of a pb_type block to module manager
|
||||
* This function is designed for non-primitive pb_types, which are
|
||||
* NOT linked to any circuit model.
|
||||
* Actually, this makes things much simpler.
|
||||
* We just iterate over all the ports and add it to the module
|
||||
* with the naming convention
|
||||
*******************************************************************/
|
||||
void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
t_pb_type* cur_pb_type) {
|
||||
/* Create a type-to-type mapping between module ports and pb_type ports */
|
||||
std::map<PORTS, ModuleManager::e_module_port_type> port_type2type_map;
|
||||
port_type2type_map[IN_PORT] = ModuleManager::MODULE_INPUT_PORT;
|
||||
port_type2type_map[OUT_PORT] = ModuleManager::MODULE_OUTPUT_PORT;
|
||||
port_type2type_map[INOUT_PORT] = ModuleManager::MODULE_INOUT_PORT;
|
||||
|
||||
for (int port = 0; port < cur_pb_type->num_ports; ++port) {
|
||||
t_port* pb_type_port = &(cur_pb_type->ports[port]);
|
||||
BasicPort module_port(generate_pb_type_port_name(pb_type_port), pb_type_port->num_pins);
|
||||
module_manager.add_port(module_id, module_port, port_type2type_map[pb_type_port->type]);
|
||||
/* Set the port to be wire-connection */
|
||||
module_manager.set_port_is_wire(module_id, module_port.get_name(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Identify if a net is a local wire inside a module:
|
||||
* A net is a local wire if it connects between two instances,
|
||||
|
@ -832,6 +814,33 @@ void add_module_nets_memory_config_bus(ModuleManager& module_manager,
|
|||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Find the size of configuration ports for module
|
||||
*******************************************************************/
|
||||
size_t find_module_num_config_bits(const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_sram_orgz& sram_orgz_type) {
|
||||
std::vector<std::string> config_port_names = generate_sram_port_names(circuit_lib, sram_model, sram_orgz_type);
|
||||
size_t num_config_bits = 0; /* By default it has zero configuration bits*/
|
||||
|
||||
/* Try to find these ports in the module manager */
|
||||
for (const std::string& config_port_name : config_port_names) {
|
||||
ModulePortId module_port_id = module_manager.find_module_port(module_id, config_port_name);
|
||||
/* If the port does not exist, go to the next */
|
||||
if (false == module_manager.valid_module_port_id(module_id, module_port_id)) {
|
||||
continue;
|
||||
}
|
||||
/* The port exist, find the port size and update the num_config_bits if the size is larger */
|
||||
BasicPort module_port = module_manager.module_port(module_id, module_port_id);
|
||||
num_config_bits = std::max((int)num_config_bits, (int)module_port.get_width());
|
||||
}
|
||||
|
||||
return num_config_bits;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* TODO:
|
||||
* Add the port-to-port connection between a logic module
|
||||
|
|
|
@ -37,7 +37,11 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager,
|
|||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_sram_orgz sram_orgz_type,
|
||||
const size_t& port_size);
|
||||
const size_t& num_config_bits);
|
||||
|
||||
void add_primitive_pb_type_ports_to_module_manager(ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
t_pb_type* cur_pb_type);
|
||||
|
||||
void add_pb_type_ports_to_module_manager(ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
|
@ -72,4 +76,10 @@ void add_module_nets_memory_config_bus(ModuleManager& module_manager,
|
|||
const e_sram_orgz& sram_orgz_type,
|
||||
const e_spice_model_design_tech& mem_tech);
|
||||
|
||||
size_t find_module_num_config_bits(const ModuleManager& module_manager,
|
||||
const ModuleId& module_id,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const CircuitModelId& sram_model,
|
||||
const e_sram_orgz& sram_orgz_type);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -115,7 +115,7 @@ void print_verilog_primitive_block(std::fstream& fp,
|
|||
* Since we have linked pb_type ports to circuit models when setting up FPGA-X2P,
|
||||
* no ports of the circuit model will be missing here
|
||||
*/
|
||||
add_pb_type_ports_to_module_manager(module_manager, primitive_module, primitive_pb_graph_node->pb_type);
|
||||
add_primitive_pb_type_ports_to_module_manager(module_manager, primitive_module, primitive_pb_graph_node->pb_type);
|
||||
|
||||
/* Add configuration ports */
|
||||
/* Shared SRAM ports*/
|
||||
|
@ -273,43 +273,83 @@ void print_verilog_physical_blocks_rec(std::fstream& fp,
|
|||
ModuleId pb_module = module_manager.add_module(pb_module_name);
|
||||
VTR_ASSERT(ModuleId::INVALID() != pb_module);
|
||||
|
||||
/* TODO: Add ports to the Verilog module */
|
||||
/* Add ports to the Verilog module */
|
||||
add_pb_type_ports_to_module_manager(module_manager, pb_module, physical_pb_type);
|
||||
|
||||
/* TODO: Count I/O (INOUT) ports from the sub-modules under this Verilog module */
|
||||
/* TODO: Count shared SRAM ports from the sub-modules under this Verilog module */
|
||||
/* TODO: Count SRAM ports from the sub-modules under this Verilog module */
|
||||
/* TODO: Count formal verification ports from the sub-modules under this Verilog module */
|
||||
|
||||
/* Print Verilog module declaration */
|
||||
print_verilog_module_declaration(fp, module_manager, pb_module);
|
||||
|
||||
/* Comment lines */
|
||||
print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----"));
|
||||
|
||||
/* TODO: Print local wires (bus wires for memory configuration) */
|
||||
/*
|
||||
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info,
|
||||
stamped_sram_cnt,
|
||||
stamped_sram_cnt + num_conf_bits - 1);
|
||||
/* Vectors to record all the memory modules have been added
|
||||
* They are used to add module nets of configuration bus
|
||||
*/
|
||||
std::vector<ModuleId> memory_modules;
|
||||
std::vector<size_t> memory_instances;
|
||||
|
||||
/* TODO: this should be added to the cur_sram_orgz_info !!! */
|
||||
t_spice_model* mem_model = NULL;
|
||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model);
|
||||
CircuitModelId sram_model = circuit_lib.model(mem_model->name);
|
||||
VTR_ASSERT(CircuitModelId::INVALID() != sram_model);
|
||||
|
||||
/* TODO: Add all the child Verilog modules as instances */
|
||||
for (int ichild = 0; ichild < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ++ichild) {
|
||||
/* Get the name and module id for this child pb_type */
|
||||
std::string child_pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, &(physical_pb_type->modes[physical_mode_index].pb_type_children[ichild]));
|
||||
ModuleId child_pb_module = module_manager.find_module(child_pb_module_name);
|
||||
/* We must have one valid id! */
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(child_pb_module));
|
||||
|
||||
/* TODO: Instanciate all the child Verilog modules */
|
||||
for (int ipb = 0; ipb < physical_pb_type->modes[physical_mode_index].num_pb_type_children; ipb++) {
|
||||
/* Each child may exist multiple times in the hierarchy*/
|
||||
for (int jpb = 0; jpb < physical_pb_type->modes[physical_mode_index].pb_type_children[ipb].num_pb; jpb++) {
|
||||
for (int inst = 0; inst < physical_pb_type->modes[physical_mode_index].pb_type_children[ichild].num_pb; ++inst) {
|
||||
/* we should make sure this placement index == child_pb_type[jpb] */
|
||||
VTR_ASSERT(jpb == physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ipb][jpb].placement_index);
|
||||
VTR_ASSERT(inst == physical_pb_graph_node->child_pb_graph_nodes[physical_mode_index][ichild][inst].placement_index);
|
||||
|
||||
size_t child_instance_id = module_manager.num_instance(pb_module, child_pb_module);
|
||||
/* Add the memory module as a child of primitive module */
|
||||
module_manager.add_child_module(pb_module, child_pb_module);
|
||||
/* TODO: Identify if this sub module includes configuration bits,
|
||||
* we will update the memory module and instance list
|
||||
*/
|
||||
if (0 < find_module_num_config_bits(module_manager, child_pb_module,
|
||||
circuit_lib, sram_model,
|
||||
cur_sram_orgz_info->type)) {
|
||||
memory_modules.push_back(child_pb_module);
|
||||
memory_instances.push_back(child_instance_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO: Print programmable/non-programmable interconnections inside the Verilog module */
|
||||
|
||||
/* TODO: 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
|
||||
*/
|
||||
|
||||
/* TODO: Count I/O (INOUT) ports from the sub-modules under this Verilog module
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* TODO: Count shared SRAM ports from the sub-modules under this Verilog module
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* TODO: Count SRAM ports from the sub-modules under this Verilog module
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* TODO: Add modules and nets for programmable/non-programmable interconnections
|
||||
* inside the Verilog module */
|
||||
/*
|
||||
dump_verilog_pb_graph_interc(cur_sram_orgz_info, fp, subckt_name,
|
||||
cur_pb_graph_node, mode_index,
|
||||
is_explicit_mapping);
|
||||
*/
|
||||
|
||||
/* Print an end to the Verilog module */
|
||||
print_verilog_module_end(fp, module_manager.module_name(pb_module));
|
||||
|
||||
/* Comment lines */
|
||||
print_verilog_comment(fp, std::string("----- BEGIN Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----"));
|
||||
|
||||
/* Write the verilog module */
|
||||
write_verilog_module_to_file(fp, module_manager, pb_module, use_explicit_mapping);
|
||||
|
||||
print_verilog_comment(fp, std::string("----- END Physical programmable logic block Verilog module: " + std::string(physical_pb_type->name) + " -----"));
|
||||
|
||||
|
|
Loading…
Reference in New Issue