refactored local wire generation for Switch block

This commit is contained in:
tangxifan 2019-09-25 21:05:02 -06:00
parent 2b0e2615fa
commit 5bb40e7f74
9 changed files with 275 additions and 23 deletions

View File

@ -307,8 +307,6 @@ std::string generate_reserved_sram_port_name(const e_spice_model_port_type& port
/********************************************************************* /*********************************************************************
* Generate the port name for a sram port, used for formal verification * 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 * 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, std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model) { const CircuitModelId& sram_model) {
@ -318,17 +316,14 @@ std::string generate_formal_verification_sram_port_name(const CircuitLibrary& ci
} }
/********************************************************************* /*********************************************************************
* Generate the port name for a regular sram port * Generate the port name for a regular sram port which appears in the
* port list of a module
* The port name is named after the cell name of SRAM in circuit library * 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, std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model, const CircuitModelId& sram_model,
const e_sram_orgz& sram_orgz_type, const e_sram_orgz& sram_orgz_type,
const e_spice_model_port_type& port_type) { const e_spice_model_port_type& port_type) {
/* Get memory_model */
std::string port_name = circuit_lib.model_name(sram_model) + std::string("_"); std::string port_name = circuit_lib.model_name(sram_model) + std::string("_");
switch (sram_orgz_type) { switch (sram_orgz_type) {
@ -395,3 +390,69 @@ std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
return port_name; return port_name;
} }
/*********************************************************************
* Generate the port name for a regular sram port which is an internal
* wire of a module
* The port name is named after the cell name of SRAM in circuit library
*********************************************************************/
std::string generate_sram_local_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) {
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_local_bus");
} else {
VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
port_name += std::string("outb_local_bus");
}
break;
}
case SPICE_SRAM_SCAN_CHAIN:
/* Three types of ports are available:
* (1) Input of Scan-chain Flip-Flops (SCFFs), enabled by port type of INPUT
* (2) Output of a chian of Scan-chain Flip-flops (SCFFs), enabled by port type of OUTPUT
* (2) Inverted output of a chian of Scan-chain Flip-flops (SCFFs), enabled by port type of INOUT
* +------+ +------+ +------+
* Head --->| SCFF |--->| SCFF |--->| SCFF |---> Tail
* +------+ +------+ +------+
*/
if (SPICE_MODEL_PORT_INPUT == port_type) {
port_name += std::string("scff_in_local_bus");
} else if ( SPICE_MODEL_PORT_OUTPUT == port_type ) {
port_name += std::string("scff_out_local_bus");
} else {
VTR_ASSERT( SPICE_MODEL_PORT_INOUT == port_type );
port_name += std::string("scff_outb_local_bus");
}
break;
case SPICE_SRAM_MEMORY_BANK: {
/* 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_local_bus");
} else {
VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
port_name += std::string("outb_local_bus");
}
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

@ -77,4 +77,9 @@ std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
const e_sram_orgz& sram_orgz_type, const e_sram_orgz& sram_orgz_type,
const e_spice_model_port_type& port_type); const e_spice_model_port_type& port_type);
std::string generate_sram_local_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 #endif

View File

@ -482,7 +482,7 @@ void link_circuit_library_to_arch(t_arch* arch,
/* Check Circuit models first*/ /* Check Circuit models first*/
VTR_ASSERT_SAFE( (NULL != arch) && (NULL != arch->spice) ); VTR_ASSERT_SAFE( (NULL != arch) && (NULL != arch->spice) );
/* 1. Link the spice model defined in pb_types and routing switches */ /* 1. Link the circuit model defined in pb_types and routing switches */
/* Step A: Check routing switches, connection blocks*/ /* Step A: Check routing switches, connection blocks*/
if (0 >= arch->num_cb_switch) { if (0 >= arch->num_cb_switch) {
vpr_printf(TIO_MESSAGE_ERROR, vpr_printf(TIO_MESSAGE_ERROR,
@ -500,7 +500,7 @@ void link_circuit_library_to_arch(t_arch* arch,
__FILE__, __LINE__, arch->cb_switches[i].spice_model_name, arch->cb_switches[i].name); __FILE__, __LINE__, arch->cb_switches[i].spice_model_name, arch->cb_switches[i].name);
exit(1); exit(1);
} }
/* Check the spice model structure is matched with the structure in switch_inf */ /* Check the circuit model structure is matched with the structure in switch_inf */
if (0 < check_circuit_model_structure_match_switch_inf(arch->cb_switches[i], arch->spice->circuit_lib)) { if (0 < check_circuit_model_structure_match_switch_inf(arch->cb_switches[i], arch->spice->circuit_lib)) {
exit(1); exit(1);
} }
@ -544,7 +544,7 @@ void link_circuit_library_to_arch(t_arch* arch,
/* Step C: Find SRAM Model*/ /* Step C: Find SRAM Model*/
link_sram_inf(&(arch->sram_inf), arch->spice->circuit_lib); link_sram_inf(&(arch->sram_inf), arch->spice->circuit_lib);
/* Step D: Find the segment spice_model*/ /* Step D: Find the segment circuit_model*/
for (int i = 0; i < arch->num_segments; i++) { for (int i = 0; i < arch->num_segments; i++) {
arch->Segments[i].circuit_model = link_circuit_model_by_name_and_type(arch->Segments[i].spice_model_name, arch->Segments[i].circuit_model = link_circuit_model_by_name_and_type(arch->Segments[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_CHAN_WIRE); arch->spice->circuit_lib, SPICE_MODEL_CHAN_WIRE);
@ -562,7 +562,7 @@ void link_circuit_library_to_arch(t_arch* arch,
for (int i = 0; i < arch->num_directs; i++) { for (int i = 0; i < arch->num_directs; i++) {
arch->Directs[i].circuit_model = link_circuit_model_by_name_and_type(arch->Directs[i].spice_model_name, arch->Directs[i].circuit_model = link_circuit_model_by_name_and_type(arch->Directs[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_WIRE); arch->spice->circuit_lib, SPICE_MODEL_WIRE);
/* Check SPICE model type */ /* Check Circuit model type */
if (CircuitModelId::INVALID() == arch->Directs[i].circuit_model) { if (CircuitModelId::INVALID() == arch->Directs[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR, vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of CLB to CLB Direct Connection (name=%s) is undefined in circuit models!\n", "(FILE:%s, LINE[%d])Invalid circuit model name(%s) of CLB to CLB Direct Connection (name=%s) is undefined in circuit models!\n",

View File

@ -140,6 +140,8 @@ void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_
* 2. Scan-chain Flip-flops: * 2. Scan-chain Flip-flops:
* two ports will be added, which are the head of scan-chain * two ports will be added, which are the head of scan-chain
* and the tail 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: * 3. Memory decoders:
* 2-4 ports will be added, depending on the ports available in the SRAM * 2-4 ports will be added, depending on the ports available in the SRAM
* Among these, two ports are mandatory: BL and WL * Among these, two ports are mandatory: BL and WL

View File

@ -11,7 +11,7 @@
/********************************************************************* /*********************************************************************
* This function will find the global ports required by a Switch Block * This function will find the global ports required by a Switch Block
* module. It wil find all the circuit models in the circuit library * module. It will find all the circuit models in the circuit library
* that may be included in the Switch Block * that may be included in the Switch Block
* Collect the global ports from the circuit_models and merge with the same name * Collect the global ports from the circuit_models and merge with the same name
********************************************************************/ ********************************************************************/
@ -60,3 +60,31 @@ std::vector<CircuitPortId> find_switch_block_global_ports(const RRGSB& rr_gsb,
return global_ports; return global_ports;
} }
/*********************************************************************
* This function will find the number of multiplexers required by
* a Switch Block module.
********************************************************************/
size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb) {
size_t num_muxes = 0;
/* Walk through the OUTPUT nodes at each side of a GSB,
* get the switch id of incoming edges
* and get the circuit model linked to the switch id
*/
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
continue;
}
/* Check if this node is driven by a multiplexer */
if (true == rr_gsb.is_sb_node_passing_wire(side_manager.get_side(), itrack)) {
continue;
}
/* This means we need a multiplexer, update the counter */
num_muxes++;
}
}
return num_muxes;
}

View File

@ -14,4 +14,6 @@ std::vector<CircuitPortId> find_switch_block_global_ports(const RRGSB& rr_gsb,
const CircuitLibrary& circuit_lib, const CircuitLibrary& circuit_lib,
const std::vector<t_switch_inf>& switch_lib); const std::vector<t_switch_inf>& switch_lib);
size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb);
#endif #endif

View File

@ -48,6 +48,27 @@
#include "verilog_writer_utils.h" #include "verilog_writer_utils.h"
#include "verilog_routing.h" #include "verilog_routing.h"
/********************************************************************
* Print local wires that are used for SRAM configuration
* This function is supposed to be used by Verilog generation
* of switch blocks
* It will count the number of switch blocks, which is the
* port width for local wires when Configuration chain is used
********************************************************************/
static
void print_verilog_switch_block_local_sram_wires(std::fstream& fp,
const RRGSB& rr_gsb,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz sram_orgz_type,
const size_t& port_size) {
size_t local_port_size = port_size;
if (SPICE_SRAM_SCAN_CHAIN == sram_orgz_type) {
local_port_size = find_switch_block_number_of_muxes(rr_gsb);
}
print_verilog_local_sram_wires(fp, circuit_lib, sram_model, sram_orgz_type, local_port_size);
}
/********************************************************************* /*********************************************************************
* Generate the Verilog module for a routing channel * Generate the Verilog module for a routing channel
* Routing track wire, which is 1-input and dual output * Routing track wire, which is 1-input and dual output
@ -2287,13 +2308,15 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
add_reserved_sram_ports_to_module_manager(module_manager, module_id, add_reserved_sram_ports_to_module_manager(module_manager, module_id,
rr_gsb.get_sb_num_reserved_conf_bits()); rr_gsb.get_sb_num_reserved_conf_bits());
} }
/* Normal sram ports */
if (0 < rr_gsb.get_sb_num_conf_bits()) {
/* TODO: this should be added to the cur_sram_orgz_info !!! */ /* TODO: this should be added to the cur_sram_orgz_info !!! */
t_spice_model* mem_model = NULL; t_spice_model* mem_model = NULL;
get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model); get_sram_orgz_info_mem_model(cur_sram_orgz_info, & mem_model);
CircuitModelId sram_model = circuit_lib.model(mem_model->name); CircuitModelId sram_model = circuit_lib.model(mem_model->name);
VTR_ASSERT(CircuitModelId::INVALID() != sram_model); VTR_ASSERT(CircuitModelId::INVALID() != sram_model);
/* Normal sram ports */
if (0 < rr_gsb.get_sb_num_conf_bits()) {
add_sram_ports_to_module_manager(module_manager, module_id, add_sram_ports_to_module_manager(module_manager, module_id,
circuit_lib, sram_model, cur_sram_orgz_info->type, circuit_lib, sram_model, cur_sram_orgz_info->type,
rr_gsb.get_sb_num_conf_bits()); rr_gsb.get_sb_num_conf_bits());
@ -2308,12 +2331,14 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
print_verilog_module_declaration(fp, module_manager, module_id); print_verilog_module_declaration(fp, module_manager, module_id);
/* Finish printing ports */ /* Finish printing ports */
/* TODO: Local wires for memory configurations */ print_verilog_comment(fp, std::string("---- BEGIN local wires for SRAM data ports ----"));
/* /* Local wires for memory configurations */
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info, print_verilog_switch_block_local_sram_wires(fp, rr_gsb, circuit_lib, sram_model, cur_sram_orgz_info->type,
rr_gsb.get_sb_conf_bits_lsb(), rr_gsb.get_sb_num_conf_bits());
rr_gsb.get_sb_conf_bits_msb()); print_verilog_comment(fp, std::string("---- END local wires for SRAM data ports ----"));
*/
/* TODO: Print routing multiplexers */
/* Put an end to the Verilog module */ /* Put an end to the Verilog module */
print_verilog_module_end(fp, module_manager.module_name(module_id)); print_verilog_module_end(fp, module_manager.module_name(module_id));

View File

@ -12,6 +12,7 @@
/* FPGA-X2P context header files */ /* FPGA-X2P context header files */
#include "spice_types.h" #include "spice_types.h"
#include "fpga_x2p_naming.h"
#include "fpga_x2p_utils.h" #include "fpga_x2p_utils.h"
/* FPGA-Verilog context header files */ /* FPGA-Verilog context header files */
@ -646,3 +647,125 @@ void print_verilog_buffer_instance(std::fstream& fp,
module_manager.add_child_module(parent_module_id, buffer_module_id); module_manager.add_child_module(parent_module_id, buffer_module_id);
} }
/********************************************************************
* Print local wires that are used for SRAM configuration
* The local wires are strongly dependent on the organization of SRAMs.
* 1. Standalone SRAMs:
* No need for local wires, their outputs are port of the module
*
* Module
* +------------------------------+
* | Sub-module |
* | +---------------------+ |
* | | sram_out|---->|---->sram_out
* | | | |
* | | sram_out|---->|---->sram_out
* | | | |
* | +---------------------+ |
* +------------------------------+
*
* 2. Configuration-chain Flip-flops:
* two ports will be added, which are the head of scan-chain
* and the tail of scan-chain
*
* Module
* +-----------------------------------------+
* | |
* | +------+ +------+ +------+ |
* | +->| CCFF |--->| CCFF | ... | CCFF |-+ |
* | | +------+ | +------+ | +------+ | |
* head--->|-+-----------+------------+-----------+->|--->tail
* | local wire |
* +-----------------------------------------+
* 3. Memory decoders:
* two ports will be added, which are regular output and inverted output
* Note that the outputs are the data outputs of SRAMs
* BL/WLs of memory decoders are ports of module but not local wires
*
* Module
* +-----------------------------------------+
* | |
* | +------+ +------+ +------+ |
* | | SRAM | | SRAM | ... | SRAM | |
* | +------+ +------+ +------+ |
* | ^ ^ ^ |
* | | | | |
* BL/WL--->|---------------------------------------->|
* | local wire |
* +-----------------------------------------+
*
********************************************************************/
void print_verilog_local_sram_wires(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz sram_orgz_type,
const size_t& port_size) {
/* Make sure we have a valid file handler*/
check_file_handler(fp);
/* Port size must be at least one! */
if (0 == port_size) {
return;
}
/* Depend on the configuraion style */
switch(sram_orgz_type) {
case SPICE_SRAM_STANDALONE:
/* Nothing to do here */
break;
case SPICE_SRAM_SCAN_CHAIN: {
/* Generate the name of local wire for the CCFF inputs, CCFF output and inverted output */
std::vector<BasicPort> ccff_ports;
/* [0] => CCFF input */
ccff_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_INPUT), port_size));
/* [1] => CCFF output */
ccff_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_OUTPUT), port_size));
/* [2] => CCFF inverted output */
ccff_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_INOUT), port_size));
/* Print local wire definition */
for (const auto& ccff_port : ccff_ports) {
fp << generate_verilog_port(VERILOG_PORT_WIRE, ccff_port) << ";" << std::endl;
}
/* Connect first CCFF to the head */
/* Head is always a 1-bit port */
BasicPort ccff_head_port(generate_sram_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_INPUT), 1);
BasicPort ccff_head_local_port(ccff_ports[0].get_name(), 1);
print_verilog_wire_connection(fp, ccff_head_local_port, ccff_head_port, false);
/* Connect last CCFF to the tail */
/* Tail is always a 1-bit port */
BasicPort ccff_tail_port(generate_sram_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_OUTPUT), 1);
BasicPort ccff_tail_local_port(ccff_ports[1].get_name(), ccff_ports[1].get_msb(), ccff_ports[1].get_msb());
print_verilog_wire_connection(fp, ccff_tail_local_port, ccff_tail_port, false);
/* Connect CCFFs into chains */
/* If port size is 0 or 1, there is no need for the chain connection */
if (2 > port_size) {
break;
}
/* Cascade the CCFF between head and tail */
BasicPort ccff_chain_input_port(ccff_ports[0].get_name(), port_size - 1);
BasicPort ccff_chain_output_port(ccff_ports[1].get_name(), 1, port_size - 1);
print_verilog_wire_connection(fp, ccff_chain_output_port, ccff_chain_input_port, false);
break;
}
case SPICE_SRAM_MEMORY_BANK: {
/* Generate the name of local wire for the SRAM output and inverted output */
std::vector<BasicPort> sram_ports;
/* [0] => SRAM output */
sram_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_INPUT), port_size));
/* [1] => SRAM inverted output */
sram_ports.push_back(BasicPort(generate_sram_local_port_name(circuit_lib, sram_model, sram_orgz_type, SPICE_MODEL_PORT_OUTPUT), port_size));
/* Print local wire definition */
for (const auto& sram_port : sram_ports) {
fp << generate_verilog_port(VERILOG_PORT_WIRE, sram_port) << ";" << std::endl;
}
break;
}
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d])Invalid SRAM organization!\n",
__FILE__, __LINE__);
exit(1);
}
}

View File

@ -84,4 +84,10 @@ void print_verilog_buffer_instance(std::fstream& fp,
const BasicPort& instance_input_port, const BasicPort& instance_input_port,
const BasicPort& instance_output_port); const BasicPort& instance_output_port);
void print_verilog_local_sram_wires(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_sram_orgz sram_orgz_type,
const size_t& port_size);
#endif #endif