refactored local wire generation for Switch block
This commit is contained in:
parent
2b0e2615fa
commit
5bb40e7f74
|
@ -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
|
||||
* 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) {
|
||||
|
@ -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
|
||||
* 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) {
|
||||
|
@ -395,3 +390,69 @@ std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -77,4 +77,9 @@ std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
|
|||
const e_sram_orgz& sram_orgz_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
|
||||
|
|
|
@ -482,7 +482,7 @@ void link_circuit_library_to_arch(t_arch* arch,
|
|||
/* Check Circuit models first*/
|
||||
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*/
|
||||
if (0 >= arch->num_cb_switch) {
|
||||
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);
|
||||
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)) {
|
||||
exit(1);
|
||||
}
|
||||
|
@ -544,7 +544,7 @@ void link_circuit_library_to_arch(t_arch* arch,
|
|||
/* Step C: Find SRAM Model*/
|
||||
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++) {
|
||||
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);
|
||||
|
@ -562,7 +562,7 @@ void link_circuit_library_to_arch(t_arch* arch,
|
|||
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->spice->circuit_lib, SPICE_MODEL_WIRE);
|
||||
/* Check SPICE model type */
|
||||
/* Check Circuit model type */
|
||||
if (CircuitModelId::INVALID() == arch->Directs[i].circuit_model) {
|
||||
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",
|
||||
|
|
|
@ -140,6 +140,8 @@ void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_
|
|||
* 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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
/*********************************************************************
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,4 +14,6 @@ std::vector<CircuitPortId> find_switch_block_global_ports(const RRGSB& rr_gsb,
|
|||
const CircuitLibrary& circuit_lib,
|
||||
const std::vector<t_switch_inf>& switch_lib);
|
||||
|
||||
size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,6 +48,27 @@
|
|||
#include "verilog_writer_utils.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
|
||||
* 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,
|
||||
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 !!! */
|
||||
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);
|
||||
|
||||
/* Normal sram ports */
|
||||
if (0 < rr_gsb.get_sb_num_conf_bits()) {
|
||||
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());
|
||||
|
@ -2308,12 +2331,14 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
|
|||
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||
/* Finish printing ports */
|
||||
|
||||
/* TODO: Local wires for memory configurations */
|
||||
/*
|
||||
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info,
|
||||
rr_gsb.get_sb_conf_bits_lsb(),
|
||||
rr_gsb.get_sb_conf_bits_msb());
|
||||
*/
|
||||
print_verilog_comment(fp, std::string("---- BEGIN local wires for SRAM data ports ----"));
|
||||
/* Local wires for memory configurations */
|
||||
print_verilog_switch_block_local_sram_wires(fp, rr_gsb, circuit_lib, sram_model, cur_sram_orgz_info->type,
|
||||
rr_gsb.get_sb_num_conf_bits());
|
||||
print_verilog_comment(fp, std::string("---- END local wires for SRAM data ports ----"));
|
||||
|
||||
/* TODO: Print routing multiplexers */
|
||||
|
||||
/* Put an end to the Verilog module */
|
||||
print_verilog_module_end(fp, module_manager.module_name(module_id));
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
/* FPGA-X2P context header files */
|
||||
#include "spice_types.h"
|
||||
#include "fpga_x2p_naming.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,4 +84,10 @@ void print_verilog_buffer_instance(std::fstream& fp,
|
|||
const BasicPort& instance_input_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
|
||||
|
|
Loading…
Reference in New Issue