Merge remote-tracking branch 'origin/dev' into heterogeneous

This commit is contained in:
AurelienUoU 2019-09-25 16:50:53 -06:00
commit e5faeb1400
9 changed files with 333 additions and 27 deletions

View File

@ -8,6 +8,7 @@
#include "vtr_assert.h"
#include "sides.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_naming.h"
/************************************************
@ -228,7 +229,8 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type,
port_name += std::string("in_");
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid direction of chan_rr_node!\n",
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of chan_rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
@ -301,3 +303,95 @@ std::string generate_reserved_sram_port_name(const e_spice_model_port_type& port
}
return std::string("reserved_wl");
}
/*********************************************************************
* Generate the port name for a sram port, used for formal verification
* The port name is named after the cell name of SRAM in circuit library
* TODO:
* Use the new refactored data structure to replace the t_sram_orgz_info
*********************************************************************/
std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model) {
std::string port_name = circuit_lib.model_name(sram_model) + std::string("_out_fm");
return port_name;
}
/*********************************************************************
* Generate the port name for a regular sram port
* The port name is named after the cell name of SRAM in circuit library
* TODO:
* Use the new refactored data structure to replace the t_sram_orgz_info
*********************************************************************/
std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz& sram_orgz_type,
const e_spice_model_port_type& port_type) {
/* Get memory_model */
std::string port_name = circuit_lib.model_name(sram_model) + std::string("_");
switch (sram_orgz_type) {
case SPICE_SRAM_STANDALONE: {
/* Two types of ports are available:
* (1) Regular output of a SRAM, enabled by port type of INPUT
* (2) Inverted output of a SRAM, enabled by port type of OUTPUT
*/
if (SPICE_MODEL_PORT_INPUT == port_type) {
port_name += std::string("out");
} else {
VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
port_name += std::string("outb");
}
break;
}
case SPICE_SRAM_SCAN_CHAIN:
/* Two types of ports are available:
* (1) Head of a chain of Scan-chain Flip-Flops (SCFFs), enabled by port type of INPUT
* (2) Tail of a chian of Scan-chain Flip-flops (SCFFs), enabled by port type of OUTPUT
* +------+ +------+ +------+
* Head --->| SCFF |--->| SCFF |--->| SCFF |---> Tail
* +------+ +------+ +------+
*/
if (SPICE_MODEL_PORT_INPUT == port_type) {
port_name += std::string("scff_head");
} else {
VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
port_name += std::string("scff_tail");
}
break;
case SPICE_SRAM_MEMORY_BANK:
/* Four types of ports are available:
* (1) Bit Lines (BLs) of a SRAM cell, enabled by port type of BL
* (2) Word Lines (WLs) of a SRAM cell, enabled by port type of WL
* (3) Inverted Bit Lines (BLBs) of a SRAM cell, enabled by port type of BLB
* (4) Inverted Word Lines (WLBs) of a SRAM cell, enabled by port type of WLB
*
* BL BLB WL WLB BL BLB WL WLB BL BLB WL WLB
* [0] [0] [0] [0] [1] [1] [1] [1] [i] [i] [i] [i]
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
* | | | | | | | | | | | |
* +----------+ +----------+ +----------+
* | SRAM | | SRAM | ... | SRAM |
* +----------+ +----------+ +----------+
*/
if (SPICE_MODEL_PORT_BL == port_type) {
port_name += std::string("bl");
} else if (SPICE_MODEL_PORT_WL == port_type) {
port_name += std::string("wl");
} else if (SPICE_MODEL_PORT_BLB == port_type) {
port_name += std::string("blb");
} else {
VTR_ASSERT( SPICE_MODEL_PORT_WLB == port_type );
port_name += std::string("wlb");
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
__FILE__, __LINE__);
exit(1);
}
return port_name;
}

View File

@ -69,4 +69,12 @@ std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
std::string generate_reserved_sram_port_name(const e_spice_model_port_type& port_type);
std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model);
std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz& sram_orgz_type,
const e_spice_model_port_type& port_type);
#endif

View File

@ -106,6 +106,13 @@ bool ModuleManager::port_is_register(const ModuleId& module, const ModulePortId&
return port_is_register_[module][port];
}
/* Return the pre-processing flag of a port */
std::string ModuleManager::port_preproc_flag(const ModuleId& module, const ModulePortId& port) const {
/* validate both module id and port id*/
VTR_ASSERT(valid_module_port_id(module, port));
return port_preproc_flags_[module][port];
}
/******************************************************************************
* Public Mutators
******************************************************************************/
@ -131,6 +138,7 @@ ModuleId ModuleManager::add_module(const std::string& name) {
ports_.emplace_back();
port_types_.emplace_back();
port_is_register_.emplace_back();
port_preproc_flags_.emplace_back();
/* Register in the name-to-id map */
name_id_map_[name] = module;
@ -155,6 +163,7 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
ports_[module].push_back(port_info);
port_types_[module].push_back(port_type);
port_is_register_[module].push_back(false);
port_preproc_flags_[module].emplace_back(); /* Create an empty string for the pre-processing flags */
/* Update fast look-up for port */
port_lookup_[module][port_type].push_back(port);
@ -178,6 +187,13 @@ void ModuleManager::set_port_is_register(const ModuleId& module, const std::stri
port_is_register_[module][port] = is_register;
}
/* Set the preprocessing flag for a port */
void ModuleManager::set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag) {
/* Must find something, otherwise drop an error */
VTR_ASSERT(valid_module_port_id(module, port));
port_preproc_flags_[module][port] = preproc_flag;
}
/* Add a child module to a parent module */
void ModuleManager::add_child_module(const ModuleId& parent_module, const ModuleId& child_module) {
/* Validate the id of both parent and child modules */

View File

@ -48,6 +48,8 @@ class ModuleManager {
size_t num_instance(const ModuleId& parent_module, const ModuleId& child_module) const;
/* Find if a port is register */
bool port_is_register(const ModuleId& module, const ModulePortId& port) const;
/* Return the pre-processing flag of a port */
std::string port_preproc_flag(const ModuleId& module, const ModulePortId& port) const;
public: /* Public mutators */
/* Add a module */
ModuleId add_module(const std::string& name);
@ -58,6 +60,8 @@ class ModuleManager {
void set_module_name(const ModuleId& module, const std::string& name);
/* Set a port to be a register */
void set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register);
/* Set the preprocessing flag for a port */
void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag);
/* Add a child module to a parent module */
void add_child_module(const ModuleId& parent_module, const ModuleId& child_module);
private: /* Private validators/invalidators */
@ -76,6 +80,7 @@ class ModuleManager {
vtr::vector<ModuleId, vtr::vector<ModulePortId, BasicPort>> ports_; /* List of ports for each Module */
vtr::vector<ModuleId, vtr::vector<ModulePortId, enum e_module_port_type>> port_types_; /* Type of ports */
vtr::vector<ModuleId, vtr::vector<ModulePortId, bool>> port_is_register_; /* If the port is a register, use for Verilog port definition. If enabled: <port_type> reg <port_name> */
vtr::vector<ModuleId, vtr::vector<ModulePortId, std::string>> port_preproc_flags_; /* If a port is available only when a pre-processing flag is enabled. This is to record the pre-processing flags */
/* fast look-up for module */
std::map<std::string, ModuleId> name_id_map_;

View File

@ -107,3 +107,104 @@ void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager,
module_manager.add_port(module_id, wl_module_port, ModuleManager::MODULE_INPUT_PORT);
}
/********************************************************************
* Add a list of ports that are used for formal verification to a module
* in the module manager
*
* The formal verification port will appear only when a pre-processing flag is defined
* This function will add the pre-processing flag along with the port
********************************************************************/
void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz sram_orgz_type,
const std::string& preproc_flag,
const size_t& port_size) {
/* Create a port */
std::string port_name = generate_formal_verification_sram_port_name(circuit_lib, sram_model);
BasicPort module_port(port_name, port_size);
/* Add generated ports to the ModuleManager */
ModulePortId port_id = module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT);
/* Add pre-processing flag if defined */
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
* 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
* 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()
********************************************************************/
void add_sram_ports_to_module_manager(ModuleManager& module_manager,
const ModuleId& module_id,
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 SCFF */
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);
/* SCFF 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);
}
/* 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(circuit_lib, sram_model, sram_orgz_type, model_port_types[iport]);
BasicPort module_port(port_name, sram_port_size);
/* Add generated ports to the ModuleManager */
module_manager.add_port(module_id, module_port, module_port_types[iport]);
}
}

View File

@ -9,6 +9,7 @@
/* Include other header files which are dependency on the function declared below */
#include <vector>
#include "device_port.h"
#include "spice_types.h"
#include "circuit_library.h"
#include "module_manager.h"
@ -23,5 +24,20 @@ void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager,
const ModuleId& module_id,
const size_t& port_size);
void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz sram_orgz_type,
const std::string& preproc_flag,
const size_t& port_size);
void add_sram_ports_to_module_manager(ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz sram_orgz_type,
const size_t& port_size);
#endif

View File

@ -2204,11 +2204,10 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
int num_reserved_conf_bits = count_verilog_switch_box_reserved_conf_bits(cur_sram_orgz_info, rr_sb);
/* Estimate the sram_verilog_model->cnt */
int cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
int esti_sram_cnt = cur_num_sram + num_conf_bits;
RRGSB rr_gsb = rr_sb; /* IMPORTANT: this copy will be removed when the config ports are initialized when created!!! */
rr_gsb.set_sb_num_reserved_conf_bits(num_reserved_conf_bits);
rr_gsb.set_sb_conf_bits_lsb(cur_num_sram);
rr_gsb.set_sb_conf_bits_msb(cur_num_sram + num_conf_bits - 1);
rr_gsb.set_sb_num_reserved_conf_bits(size_t(num_reserved_conf_bits));
rr_gsb.set_sb_conf_bits_lsb(size_t(cur_num_sram));
rr_gsb.set_sb_conf_bits_msb(size_t(cur_num_sram + num_conf_bits - 1));
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
@ -2281,35 +2280,29 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
/* Add configuration ports */
/* Reserved sram ports */
if (0 < rr_sb.get_sb_num_reserved_conf_bits()) {
if (0 < rr_gsb.get_sb_num_reserved_conf_bits()) {
/* Check: this SRAM organization type must be memory-bank ! */
VTR_ASSERT( SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type );
/* Generate a list of ports */
add_reserved_sram_ports_to_module_manager(module_manager, module_id,
rr_gsb.get_sb_num_reserved_conf_bits());
}
/* TODO: Normal sram ports */
/*
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
rr_gsb.get_sb_conf_bits_lsb(),
rr_gsb.get_sb_conf_bits_msb(),
VERILOG_PORT_INPUT);
*/
/* Dump ports only visible during formal verification*/
/*
if (0 < rr_sb.get_sb_num_conf_bits()) {
fprintf(fp, "\n");
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
fprintf(fp, ",\n");
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
rr_gsb.get_sb_conf_bits_lsb(),
rr_gsb.get_sb_conf_bits_msb(),
VERILOG_PORT_INPUT, is_explicit_mapping);
fprintf(fp, "\n");
fprintf(fp, "`endif\n");
/* Normal sram ports */
if (0 < rr_gsb.get_sb_num_conf_bits()) {
/* 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);
add_sram_ports_to_module_manager(module_manager, module_id,
circuit_lib, sram_model, cur_sram_orgz_info->type,
rr_gsb.get_sb_num_conf_bits());
/* Add ports only visible during formal verification to the module */
add_formal_verification_sram_ports_to_module_manager(module_manager, module_id, circuit_lib, sram_model,
cur_sram_orgz_info->type,
std::string(verilog_formal_verification_preproc_flag),
rr_gsb.get_sb_num_conf_bits());
}
fprintf(fp, "); \n");
*/
/* Print module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);

View File

@ -70,6 +70,25 @@ void print_verilog_comment(std::fstream& fp,
fp << "// " << comment << std::endl;
}
/************************************************
* Print the declaration of a Verilog preprocessing flag
***********************************************/
void print_verilog_preprocessing_flag(std::fstream& fp,
const std::string& preproc_flag) {
check_file_handler(fp);
fp << "`ifdef " << preproc_flag << std::endl;
}
/************************************************
* Print the endif of a Verilog preprocessing flag
***********************************************/
void print_verilog_endif(std::fstream& fp) {
check_file_handler(fp);
fp << "`endif" << std::endl;
}
/************************************************
* Print a Verilog module definition
* We use the following format:
@ -94,12 +113,32 @@ void print_verilog_module_definition(std::fstream& fp,
/* Port sequence: global, inout, input, output and clock ports, */
size_t port_cnt = 0;
bool printed_ifdef = false; /* A flag to tell if an ifdef has been printed for the last port */
for (const auto& kv : port_type2type_map) {
for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) {
if (0 != port_cnt) {
/* Do not dump a comma for the first port */
fp << "," << std::endl;
}
if (true == printed_ifdef) {
/* Print an endif to pair the ifdef */
print_verilog_endif(fp);
/* Reset the flag */
printed_ifdef = false;
}
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
VTR_ASSERT(ModulePortId::INVALID() != port_id);
/* Print pre-processing flag for a port, if defined */
std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id);
if (false == preproc_flag.empty()) {
/* Print an ifdef Verilog syntax */
print_verilog_preprocessing_flag(fp, preproc_flag);
/* Raise the flag */
printed_ifdef = true;
}
/* Create a space for "module <module_name>" except the first line! */
if (0 != port_cnt) {
std::string port_whitespace(module_head_line.length(), ' ');
@ -107,6 +146,8 @@ void print_verilog_module_definition(std::fstream& fp,
}
/* Print port: only the port name is enough */
fp << port.get_name();
/* Increase the counter */
port_cnt++;
}
}
@ -131,10 +172,24 @@ void print_verilog_module_ports(std::fstream& fp,
/* Port sequence: global, inout, input, output and clock ports, */
for (const auto& kv : port_type2type_map) {
for (const auto& port : module_manager.module_ports_by_type(module_id, kv.first)) {
ModulePortId port_id = module_manager.find_module_port(module_id, port.get_name());
VTR_ASSERT(ModulePortId::INVALID() != port_id);
/* Print pre-processing flag for a port, if defined */
std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id);
if (false == preproc_flag.empty()) {
/* Print an ifdef Verilog syntax */
print_verilog_preprocessing_flag(fp, preproc_flag);
}
/* Print port */
fp << "//----- " << module_manager.module_port_type_str(kv.first) << " -----" << std::endl;
fp << generate_verilog_port(kv.second, port);
fp << ";" << std::endl;
if (false == preproc_flag.empty()) {
/* Print an endif to pair the ifdef */
print_verilog_endif(fp);
}
}
}
@ -149,9 +204,22 @@ void print_verilog_module_ports(std::fstream& fp,
if (false == module_manager.port_is_register(module_id, port_id)) {
continue;
}
/* Print pre-processing flag for a port, if defined */
std::string preproc_flag = module_manager.port_preproc_flag(module_id, port_id);
if (false == preproc_flag.empty()) {
/* Print an ifdef Verilog syntax */
print_verilog_preprocessing_flag(fp, preproc_flag);
}
/* Print port */
fp << generate_verilog_port(VERILOG_PORT_REG, port);
fp << ";" << std::endl;
if (false == preproc_flag.empty()) {
/* Print an endif to pair the ifdef */
print_verilog_endif(fp);
}
}
}
fp << "//----- END Registered ports -----" << std::endl;

View File

@ -26,6 +26,11 @@ void print_verilog_include_defines_preproc_file(std::fstream& fp,
void print_verilog_comment(std::fstream& fp,
const std::string& comment);
void print_verilog_preprocessing_flag(std::fstream& fp,
const std::string& preproc_flag);
void print_verilog_endif(std::fstream& fp);
void print_verilog_module_definition(std::fstream& fp,
const ModuleManager& module_manager, const ModuleId& module_id);