Merge branch 'refactoring' into dev
This commit is contained in:
commit
86387ff79c
|
@ -0,0 +1,304 @@
|
||||||
|
/*********************************************************************
|
||||||
|
* This file includes functions that are used for
|
||||||
|
* generating ports for memory modules
|
||||||
|
*********************************************************************/
|
||||||
|
#include "vtr_assert.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "fpga_x2p_naming.h"
|
||||||
|
#include "fpga_x2p_mem_utils.h"
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Create a port-to-port map for a CMOS memory module
|
||||||
|
*
|
||||||
|
* Configuration Chain
|
||||||
|
* -------------------
|
||||||
|
*
|
||||||
|
* config_bus (head) config_bus (tail)
|
||||||
|
* | ^
|
||||||
|
* v |
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | CMOS-based Memory Module |
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | |
|
||||||
|
* v v
|
||||||
|
* sram_out sram_outb
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Memory bank
|
||||||
|
* -----------
|
||||||
|
*
|
||||||
|
* config_bus (BL) config_bus (WL)
|
||||||
|
* | |
|
||||||
|
* v v
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | CMOS-based Memory Module |
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | |
|
||||||
|
* v v
|
||||||
|
* sram_out sram_outb
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
static
|
||||||
|
std::map<std::string, BasicPort> generate_cmos_mem_module_port2port_map(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& mem_module,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const std::vector<BasicPort>& mem_output_bus_ports,
|
||||||
|
const e_sram_orgz& sram_orgz_type) {
|
||||||
|
std::map<std::string, BasicPort> port2port_name_map;
|
||||||
|
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case SPICE_SRAM_STANDALONE:
|
||||||
|
/* Nothing to do */
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_SCAN_CHAIN: {
|
||||||
|
/* Link the head port of the memory module:
|
||||||
|
* the LSB of config bus port is the head port index
|
||||||
|
*/
|
||||||
|
std::vector<BasicPort> config_bus_ports;
|
||||||
|
config_bus_ports.push_back(BasicPort(generate_local_config_bus_port_name(), config_bus.get_msb(), config_bus.get_msb() + 1));
|
||||||
|
BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb());
|
||||||
|
port2port_name_map[generate_configuration_chain_head_name()] = head_port;
|
||||||
|
|
||||||
|
/* Link the tail port of the memory module:
|
||||||
|
* the MSB of config bus port is the tail port index
|
||||||
|
*/
|
||||||
|
BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb());
|
||||||
|
port2port_name_map[generate_configuration_chain_tail_name()] = tail_port;
|
||||||
|
|
||||||
|
/* Link the SRAM output ports of the memory module */
|
||||||
|
VTR_ASSERT( 2 == mem_output_bus_ports.size() );
|
||||||
|
port2port_name_map[generate_configuration_chain_data_out_name()] = mem_output_bus_ports[0];
|
||||||
|
port2port_name_map[generate_configuration_chain_inverted_data_out_name()] = mem_output_bus_ports[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPICE_SRAM_MEMORY_BANK:
|
||||||
|
/* TODO: */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port2port_name_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Create a port-to-port map for a ReRAM-based memory module
|
||||||
|
* Memory bank
|
||||||
|
* -----------
|
||||||
|
*
|
||||||
|
* config_bus (BL) config_bus (WL)
|
||||||
|
* | |
|
||||||
|
* v v
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | ReRAM-based Memory Module |
|
||||||
|
* +-------------------------------------+
|
||||||
|
* | |
|
||||||
|
* v v
|
||||||
|
* Mem_out Mem_outb
|
||||||
|
**********************************************************************/
|
||||||
|
static
|
||||||
|
std::map<std::string, BasicPort> generate_rram_mem_module_port2port_map(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& mem_module,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const std::vector<BasicPort>& mem_output_bus_ports,
|
||||||
|
const e_sram_orgz& sram_orgz_type) {
|
||||||
|
std::map<std::string, BasicPort> port2port_name_map;
|
||||||
|
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case SPICE_SRAM_STANDALONE:
|
||||||
|
/* Not supported */
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_SCAN_CHAIN: {
|
||||||
|
/* Link the head port of the memory module:
|
||||||
|
* the LSB of config bus port is the head port index
|
||||||
|
*/
|
||||||
|
std::vector<BasicPort> config_bus_ports;
|
||||||
|
config_bus_ports.push_back(BasicPort(generate_local_config_bus_port_name(), config_bus.get_msb(), config_bus.get_msb() + 1));
|
||||||
|
BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb());
|
||||||
|
port2port_name_map[generate_configuration_chain_head_name()] = head_port;
|
||||||
|
|
||||||
|
/* Link the tail port of the memory module:
|
||||||
|
* the MSB of config bus port is the tail port index
|
||||||
|
*/
|
||||||
|
BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb());
|
||||||
|
port2port_name_map[generate_configuration_chain_tail_name()] = tail_port;
|
||||||
|
|
||||||
|
/* Link the SRAM output ports of the memory module */
|
||||||
|
VTR_ASSERT( 2 == mem_output_bus_ports.size() );
|
||||||
|
port2port_name_map[generate_configuration_chain_data_out_name()] = mem_output_bus_ports[0];
|
||||||
|
port2port_name_map[generate_configuration_chain_inverted_data_out_name()] = mem_output_bus_ports[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SPICE_SRAM_MEMORY_BANK:
|
||||||
|
/* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port2port_name_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Create a port-to-port map for a memory module
|
||||||
|
* The content of the port-to-port map will depend not only
|
||||||
|
* the design technology of the memory cells but also the
|
||||||
|
* configuration styles of FPGA fabric.
|
||||||
|
* Here we will branch on the design technology
|
||||||
|
**********************************************************************/
|
||||||
|
std::map<std::string, BasicPort> generate_mem_module_port2port_map(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& mem_module,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const std::vector<BasicPort>& mem_output_bus_ports,
|
||||||
|
const e_spice_model_design_tech& mem_design_tech,
|
||||||
|
const e_sram_orgz& sram_orgz_type) {
|
||||||
|
std::map<std::string, BasicPort> port2port_name_map;
|
||||||
|
|
||||||
|
switch (mem_design_tech) {
|
||||||
|
case SPICE_MODEL_DESIGN_CMOS:
|
||||||
|
port2port_name_map = generate_cmos_mem_module_port2port_map(module_manager, mem_module, config_bus, mem_output_bus_ports, sram_orgz_type);
|
||||||
|
break;
|
||||||
|
case SPICE_MODEL_DESIGN_RRAM:
|
||||||
|
port2port_name_map = generate_rram_mem_module_port2port_map(module_manager, mem_module, config_bus, mem_output_bus_ports, sram_orgz_type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of memory design technology !\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port2port_name_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Update the LSB and MSB of a configuration bus based on the number of
|
||||||
|
* memory bits of a CMOS memory module.
|
||||||
|
**********************************************************************/
|
||||||
|
static
|
||||||
|
void update_cmos_mem_module_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const size_t& num_config_bits,
|
||||||
|
BasicPort& config_bus) {
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case SPICE_SRAM_STANDALONE:
|
||||||
|
/* Not supported */
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_SCAN_CHAIN:
|
||||||
|
/* Scan-chain of a memory module only has a head and a tail.
|
||||||
|
* LSB and MSB of configuration bus will be shifted to the next head.
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(true == config_bus.rotate(1));
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_MEMORY_BANK:
|
||||||
|
/* In this case, a memory module has a number of BL/WL and BLB/WLB (possibly).
|
||||||
|
* LSB and MSB of configuration bus will be shifted by the number of BL/WL/BLB/WLB.
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(true == config_bus.rotate(num_config_bits));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Update the LSB and MSB of a configuration bus based on the number of
|
||||||
|
* memory bits of a ReRAM memory module.
|
||||||
|
**********************************************************************/
|
||||||
|
static
|
||||||
|
void update_rram_mem_module_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const size_t& num_config_bits,
|
||||||
|
BasicPort& config_bus) {
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case SPICE_SRAM_STANDALONE:
|
||||||
|
/* Not supported */
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_SCAN_CHAIN:
|
||||||
|
/* Scan-chain of a memory module only has a head and a tail.
|
||||||
|
* LSB and MSB of configuration bus will be shifted to the next head.
|
||||||
|
* TODO: this may be changed later!!!
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(true == config_bus.rotate(1));
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_MEMORY_BANK:
|
||||||
|
/* In this case, a memory module contains unique BL/WL or BLB/WLB,
|
||||||
|
* which are not shared with other modules
|
||||||
|
* TODO: this may be changed later!!!
|
||||||
|
*/
|
||||||
|
VTR_ASSERT(true == config_bus.rotate(1));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Update the LSB and MSB of a configuration bus based on the number of
|
||||||
|
* memory bits of a module.
|
||||||
|
* Note that this function is designed to do such simple job, in purpose of
|
||||||
|
* being independent from adding ports or printing ports.
|
||||||
|
* As such, this function can be re-used in bitstream generation
|
||||||
|
* when Verilog generation is not needed.
|
||||||
|
* DO NOT update the configuration bus in the function of adding/printing ports
|
||||||
|
**********************************************************************/
|
||||||
|
void update_mem_module_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const e_spice_model_design_tech& mem_design_tech,
|
||||||
|
const size_t& num_config_bits,
|
||||||
|
BasicPort& config_bus) {
|
||||||
|
switch (mem_design_tech) {
|
||||||
|
case SPICE_MODEL_DESIGN_CMOS:
|
||||||
|
update_cmos_mem_module_config_bus(sram_orgz_type, num_config_bits, config_bus);
|
||||||
|
break;
|
||||||
|
case SPICE_MODEL_DESIGN_RRAM:
|
||||||
|
update_rram_mem_module_config_bus(sram_orgz_type, num_config_bits, config_bus);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of memory design technology !\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Check if the MSB of a configuration bus of a switch block
|
||||||
|
* matches the expected value
|
||||||
|
********************************************************************/
|
||||||
|
bool check_mem_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const size_t& local_expected_msb) {
|
||||||
|
switch (sram_orgz_type) {
|
||||||
|
case SPICE_SRAM_STANDALONE:
|
||||||
|
/* Not supported */
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_SCAN_CHAIN:
|
||||||
|
/* TODO: comment on why
|
||||||
|
*/
|
||||||
|
return (local_expected_msb == config_bus.get_msb());
|
||||||
|
break;
|
||||||
|
case SPICE_SRAM_MEMORY_BANK:
|
||||||
|
/* TODO: comment on why
|
||||||
|
*/
|
||||||
|
return (local_expected_msb == config_bus.get_msb());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* Reach here, it means something goes wrong, return a false value */
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/********************************************************************
|
||||||
|
* Header file for fpga_x2p_mem_utils.cpp
|
||||||
|
**********************************************************************/
|
||||||
|
#ifndef FPGA_X2P_MEM_UTILS_H
|
||||||
|
#define FPGA_X2P_MEM_UTILS_H
|
||||||
|
|
||||||
|
/* Header files are included for the data types appear in the function declaration below */
|
||||||
|
#include <vector>
|
||||||
|
#include "device_port.h"
|
||||||
|
#include "spice_types.h"
|
||||||
|
#include "module_manager.h"
|
||||||
|
|
||||||
|
std::map<std::string, BasicPort> generate_mem_module_port2port_map(const ModuleManager& module_manager,
|
||||||
|
const ModuleId& mem_module,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const std::vector<BasicPort>& mem_output_bus_ports,
|
||||||
|
const e_spice_model_design_tech& mem_design_tech,
|
||||||
|
const e_sram_orgz& sram_orgz_type);
|
||||||
|
|
||||||
|
void update_mem_module_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const e_spice_model_design_tech& mem_design_tech,
|
||||||
|
const size_t& num_config_bits,
|
||||||
|
BasicPort& config_bus);
|
||||||
|
|
||||||
|
bool check_mem_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const size_t& local_expected_msb);
|
||||||
|
|
||||||
|
#endif
|
|
@ -168,6 +168,30 @@ std::string generate_routing_block_netlist_name(const std::string& prefix,
|
||||||
return std::string( prefix + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + postfix );
|
return std::string( prefix + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + postfix );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Generate the netlist name for a connection block with a given coordinate
|
||||||
|
*********************************************************************/
|
||||||
|
std::string generate_connection_block_netlist_name(const t_rr_type& cb_type,
|
||||||
|
const vtr::Point<size_t>& coordinate,
|
||||||
|
const std::string& postfix) {
|
||||||
|
std::string prefix("cb");
|
||||||
|
switch (cb_type) {
|
||||||
|
case CHANX:
|
||||||
|
prefix += std::string("x_");
|
||||||
|
break;
|
||||||
|
case CHANY:
|
||||||
|
prefix += std::string("y_");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File: %s [LINE%d]) Invalid type of connection block!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return generate_routing_block_netlist_name(prefix, coordinate, postfix);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate the module name for a unique routing channel
|
* Generate the module name for a unique routing channel
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
@ -242,6 +266,33 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type,
|
||||||
return port_name;
|
return port_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Generate the middle output port name for a routing track
|
||||||
|
* with a given coordinate
|
||||||
|
*********************************************************************/
|
||||||
|
std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type,
|
||||||
|
const vtr::Point<size_t>& coordinate,
|
||||||
|
const size_t& track_id) {
|
||||||
|
/* Channel must be either CHANX or CHANY */
|
||||||
|
VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
|
||||||
|
|
||||||
|
/* Create a map between chan_type and module_prefix */
|
||||||
|
std::map<t_rr_type, std::string> module_prefix_map;
|
||||||
|
/* TODO: use a constexpr string to replace the fixed name? */
|
||||||
|
module_prefix_map[CHANX] = std::string("chanx");
|
||||||
|
module_prefix_map[CHANY] = std::string("chany");
|
||||||
|
|
||||||
|
std::string port_name = module_prefix_map[chan_type];
|
||||||
|
port_name += std::string("_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("__"));
|
||||||
|
|
||||||
|
port_name += std::string("midout_");
|
||||||
|
|
||||||
|
/* Add the track id to the port name */
|
||||||
|
port_name += std::to_string(track_id) + std::string("_");
|
||||||
|
|
||||||
|
return port_name;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate the module name for a switch block with a given coordinate
|
* Generate the module name for a switch block with a given coordinate
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
@ -249,6 +300,29 @@ std::string generate_switch_block_module_name(const vtr::Point<size_t>& coordina
|
||||||
return std::string( "sb_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") );
|
return std::string( "sb_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Generate the module name for a connection block with a given coordinate
|
||||||
|
*********************************************************************/
|
||||||
|
std::string generate_connection_block_module_name(const t_rr_type& cb_type,
|
||||||
|
const vtr::Point<size_t>& coordinate) {
|
||||||
|
std::string prefix("cb");
|
||||||
|
switch (cb_type) {
|
||||||
|
case CHANX:
|
||||||
|
prefix += std::string("x_");
|
||||||
|
break;
|
||||||
|
case CHANY:
|
||||||
|
prefix += std::string("y_");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File: %s [LINE%d]) Invalid type of connection block!\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string( prefix + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") );
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate the port name for a Grid
|
* Generate the port name for a Grid
|
||||||
* TODO: add more comments about why we need different names for
|
* TODO: add more comments about why we need different names for
|
||||||
|
|
|
@ -48,6 +48,10 @@ std::string generate_routing_block_netlist_name(const std::string& prefix,
|
||||||
const vtr::Point<size_t>& block_id,
|
const vtr::Point<size_t>& block_id,
|
||||||
const std::string& postfix);
|
const std::string& postfix);
|
||||||
|
|
||||||
|
std::string generate_connection_block_netlist_name(const t_rr_type& cb_type,
|
||||||
|
const vtr::Point<size_t>& coordinate,
|
||||||
|
const std::string& postfix);
|
||||||
|
|
||||||
std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
|
std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
|
||||||
const size_t& block_id);
|
const size_t& block_id);
|
||||||
|
|
||||||
|
@ -59,8 +63,15 @@ std::string generate_routing_track_port_name(const t_rr_type& chan_type,
|
||||||
const size_t& track_id,
|
const size_t& track_id,
|
||||||
const PORTS& port_direction);
|
const PORTS& port_direction);
|
||||||
|
|
||||||
|
std::string generate_routing_track_middle_output_port_name(const t_rr_type& chan_type,
|
||||||
|
const vtr::Point<size_t>& coordinate,
|
||||||
|
const size_t& track_id);
|
||||||
|
|
||||||
std::string generate_switch_block_module_name(const vtr::Point<size_t>& coordinate);
|
std::string generate_switch_block_module_name(const vtr::Point<size_t>& coordinate);
|
||||||
|
|
||||||
|
std::string generate_connection_block_module_name(const t_rr_type& cb_type,
|
||||||
|
const vtr::Point<size_t>& coordinate);
|
||||||
|
|
||||||
std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
|
std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
|
||||||
const size_t& height,
|
const size_t& height,
|
||||||
const e_side& side,
|
const e_side& side,
|
||||||
|
|
|
@ -210,150 +210,3 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
* Create a port-to-port map for a CMOS memory module
|
|
||||||
*
|
|
||||||
* Configuration Chain
|
|
||||||
* -------------------
|
|
||||||
*
|
|
||||||
* config_bus (head) config_bus (tail)
|
|
||||||
* | ^
|
|
||||||
* v |
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | CMOS-based Memory Module |
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | |
|
|
||||||
* v v
|
|
||||||
* sram_out sram_outb
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Memory bank
|
|
||||||
* -----------
|
|
||||||
*
|
|
||||||
* config_bus (BL) config_bus (WL)
|
|
||||||
* | |
|
|
||||||
* v v
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | CMOS-based Memory Module |
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | |
|
|
||||||
* v v
|
|
||||||
* sram_out sram_outb
|
|
||||||
*
|
|
||||||
**********************************************************************/
|
|
||||||
static
|
|
||||||
std::map<std::string, BasicPort> generate_cmos_mem_module_port2port_map(const ModuleManager& module_manager,
|
|
||||||
const ModuleId& mem_module,
|
|
||||||
const std::vector<BasicPort>& config_bus_ports,
|
|
||||||
const std::vector<BasicPort>& mem_output_bus_ports,
|
|
||||||
const e_sram_orgz& sram_orgz_type) {
|
|
||||||
std::map<std::string, BasicPort> port2port_name_map;
|
|
||||||
|
|
||||||
switch (sram_orgz_type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
/* Nothing to do */
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN: {
|
|
||||||
/* Link the head port of the memory module:
|
|
||||||
* the LSB of config bus port is the head port index
|
|
||||||
*/
|
|
||||||
VTR_ASSERT( 1 == config_bus_ports.size() );
|
|
||||||
BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb());
|
|
||||||
port2port_name_map[generate_configuration_chain_head_name()] = head_port;
|
|
||||||
|
|
||||||
/* Link the tail port of the memory module:
|
|
||||||
* the MSB of config bus port is the tail port index
|
|
||||||
*/
|
|
||||||
BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb());
|
|
||||||
port2port_name_map[generate_configuration_chain_tail_name()] = tail_port;
|
|
||||||
|
|
||||||
/* Link the SRAM output ports of the memory module */
|
|
||||||
VTR_ASSERT( 2 == mem_output_bus_ports.size() );
|
|
||||||
port2port_name_map[generate_configuration_chain_data_out_name()] = mem_output_bus_ports[0];
|
|
||||||
port2port_name_map[generate_configuration_chain_inverted_data_out_name()] = mem_output_bus_ports[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 port2port_name_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
* Create a port-to-port map for a ReRAM-based memory module
|
|
||||||
* Memory bank
|
|
||||||
* -----------
|
|
||||||
*
|
|
||||||
* config_bus (BL) config_bus (WL)
|
|
||||||
* | |
|
|
||||||
* v v
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | ReRAM-based Memory Module |
|
|
||||||
* +-------------------------------------+
|
|
||||||
* | |
|
|
||||||
* v v
|
|
||||||
* Mem_out Mem_outb
|
|
||||||
**********************************************************************/
|
|
||||||
static
|
|
||||||
std::map<std::string, BasicPort> generate_rram_mem_module_port2port_map(const ModuleManager& module_manager,
|
|
||||||
const ModuleId& mem_module,
|
|
||||||
const e_sram_orgz& sram_orgz_type) {
|
|
||||||
std::map<std::string, BasicPort> port2port_name_map;
|
|
||||||
|
|
||||||
switch (sram_orgz_type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
/* Not supported */
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
/* TODO: to be supported */
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return port2port_name_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
* Create a port-to-port map for a memory module
|
|
||||||
* The content of the port-to-port map will depend not only
|
|
||||||
* the design technology of the memory cells but also the
|
|
||||||
* configuration styles of FPGA fabric.
|
|
||||||
* Here we will branch on the design technology
|
|
||||||
**********************************************************************/
|
|
||||||
std::map<std::string, BasicPort> generate_mem_module_port2port_map(const ModuleManager& module_manager,
|
|
||||||
const ModuleId& mem_module,
|
|
||||||
const std::vector<BasicPort>& config_bus_ports,
|
|
||||||
const std::vector<BasicPort>& mem_output_bus_ports,
|
|
||||||
const e_spice_model_design_tech& mem_design_tech,
|
|
||||||
const e_sram_orgz& sram_orgz_type) {
|
|
||||||
std::map<std::string, BasicPort> port2port_name_map;
|
|
||||||
|
|
||||||
switch (mem_design_tech) {
|
|
||||||
case SPICE_MODEL_DESIGN_CMOS:
|
|
||||||
port2port_name_map = generate_cmos_mem_module_port2port_map(module_manager, mem_module, config_bus_ports, mem_output_bus_ports, sram_orgz_type);
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_DESIGN_RRAM:
|
|
||||||
port2port_name_map = generate_rram_mem_module_port2port_map(module_manager, mem_module, sram_orgz_type);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(File:%s,[LINE%d])Invalid type of memory design technology !\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return port2port_name_map;
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,12 +38,5 @@ void add_sram_ports_to_module_manager(ModuleManager& module_manager,
|
||||||
const e_sram_orgz sram_orgz_type,
|
const e_sram_orgz sram_orgz_type,
|
||||||
const size_t& port_size);
|
const size_t& port_size);
|
||||||
|
|
||||||
std::map<std::string, BasicPort> generate_mem_module_port2port_map(const ModuleManager& module_manager,
|
|
||||||
const ModuleId& mem_module,
|
|
||||||
const std::vector<BasicPort>& config_bus_ports,
|
|
||||||
const std::vector<BasicPort>& mem_output_bus_ports,
|
|
||||||
const e_spice_model_design_tech& mem_design_tech,
|
|
||||||
const e_sram_orgz& sram_orgz_type);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,64 @@
|
||||||
#include "fpga_x2p_types.h"
|
#include "fpga_x2p_types.h"
|
||||||
#include "rr_blocks_utils.h"
|
#include "rr_blocks_utils.h"
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* This function will find the global ports required by a Connection Block
|
||||||
|
* module. It will find all the circuit models in the circuit library
|
||||||
|
* that may be included in the connection block
|
||||||
|
* Collect the global ports from the circuit_models and merge with the same name
|
||||||
|
********************************************************************/
|
||||||
|
std::vector<CircuitPortId> find_connection_block_global_ports(const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const std::vector<t_switch_inf>& switch_lib) {
|
||||||
|
std::vector<CircuitModelId> sub_models;
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
std::vector<enum e_side> cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type);
|
||||||
|
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
|
||||||
|
enum e_side cb_ipin_side = cb_ipin_sides[iside];
|
||||||
|
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
|
||||||
|
/* Find the size of routing multiplexers driving this IPIN node */
|
||||||
|
int mux_size = rr_gsb.get_ipin_node(cb_ipin_side, inode)->fan_in;
|
||||||
|
/* Bypass fan_in == 1 or 0, they are not considered as routing multiplexers */
|
||||||
|
if (2 > mux_size) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Find the driver switch of the node */
|
||||||
|
short driver_switch = rr_gsb.get_ipin_node(cb_ipin_side, inode)->drive_switches[DEFAULT_SWITCH_ID];
|
||||||
|
/* Find the circuit model id of the driver switch */
|
||||||
|
VTR_ASSERT( (size_t)driver_switch < switch_lib.size() );
|
||||||
|
/* Get the model, and try to add to the sub_model list */
|
||||||
|
CircuitModelId switch_circuit_model = switch_lib[driver_switch].circuit_model;
|
||||||
|
/* Make sure it is a valid id */
|
||||||
|
VTR_ASSERT( CircuitModelId::INVALID() != switch_circuit_model );
|
||||||
|
/* Get the model, and try to add to the sub_model list */
|
||||||
|
if (sub_models.end() == std::find(sub_models.begin(), sub_models.end(), switch_circuit_model)) {
|
||||||
|
/* Not yet in the list, add it */
|
||||||
|
sub_models.push_back(switch_circuit_model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CircuitPortId> global_ports;
|
||||||
|
/* Iterate over the model list, and add the global ports*/
|
||||||
|
for (const auto& model : sub_models) {
|
||||||
|
std::vector<CircuitPortId> temp_global_ports = circuit_lib.model_global_ports(model, true);
|
||||||
|
/* Add the temp_global_ports to the list to be returned, make sure we do not have any duplicated ports */
|
||||||
|
for (const auto& port_candidate : temp_global_ports) {
|
||||||
|
if (global_ports.end() == std::find(global_ports.begin(), global_ports.end(), port_candidate)) {
|
||||||
|
/* Not yet in the list, add it */
|
||||||
|
global_ports.push_back(port_candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* 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 will find all the circuit models in the circuit library
|
* module. It will find all the circuit models in the circuit library
|
||||||
|
@ -61,6 +119,32 @@ 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 connection Block module.
|
||||||
|
********************************************************************/
|
||||||
|
size_t find_connection_block_number_of_muxes(const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type) {
|
||||||
|
size_t num_muxes = 0;
|
||||||
|
|
||||||
|
std::vector<enum e_side> cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type);
|
||||||
|
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
|
||||||
|
enum e_side cb_ipin_side = cb_ipin_sides[iside];
|
||||||
|
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
|
||||||
|
/* Find the size of routing multiplexers driving this IPIN node */
|
||||||
|
int mux_size = rr_gsb.get_ipin_node(cb_ipin_side, inode)->fan_in;
|
||||||
|
/* Bypass fan_in == 1 or 0, they are not considered as routing multiplexers */
|
||||||
|
if (2 > mux_size) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* This means we need a multiplexer, update the counter */
|
||||||
|
num_muxes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_muxes;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* This function will find the number of multiplexers required by
|
* This function will find the number of multiplexers required by
|
||||||
* a Switch Block module.
|
* a Switch Block module.
|
||||||
|
|
|
@ -10,10 +10,18 @@
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
#include "rr_blocks.h"
|
#include "rr_blocks.h"
|
||||||
|
|
||||||
|
std::vector<CircuitPortId> find_connection_block_global_ports(const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const std::vector<t_switch_inf>& switch_lib);
|
||||||
|
|
||||||
std::vector<CircuitPortId> find_switch_block_global_ports(const RRGSB& rr_gsb,
|
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_connection_block_number_of_muxes(const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type);
|
||||||
|
|
||||||
size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb);
|
size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "mux_utils.h"
|
#include "mux_utils.h"
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "module_manager_utils.h"
|
#include "module_manager_utils.h"
|
||||||
|
#include "fpga_x2p_mem_utils.h"
|
||||||
|
|
||||||
/* Include Verilog support headers*/
|
/* Include Verilog support headers*/
|
||||||
#include "verilog_global.h"
|
#include "verilog_global.h"
|
||||||
|
@ -50,6 +51,30 @@
|
||||||
#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 connection blocks
|
||||||
|
* It will count the number of connection blocks, which is the
|
||||||
|
* port width for local wires when Configuration chain is used
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_connection_block_local_sram_wires(std::fstream& fp,
|
||||||
|
const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
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) {
|
||||||
|
/* Plus 1 for the wire size to connect to the tail of the configuration chain */
|
||||||
|
local_port_size = find_connection_block_number_of_muxes(rr_gsb, cb_type) + 1;
|
||||||
|
}
|
||||||
|
print_verilog_local_sram_wires(fp, circuit_lib, sram_model, sram_orgz_type, local_port_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Print local wires that are used for SRAM configuration
|
* Print local wires that are used for SRAM configuration
|
||||||
* This function is supposed to be used by Verilog generation
|
* This function is supposed to be used by Verilog generation
|
||||||
|
@ -62,7 +87,7 @@ void print_verilog_switch_block_local_sram_wires(std::fstream& fp,
|
||||||
const RRGSB& rr_gsb,
|
const RRGSB& rr_gsb,
|
||||||
const CircuitLibrary& circuit_lib,
|
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 size_t& port_size) {
|
const size_t& port_size) {
|
||||||
size_t local_port_size = port_size;
|
size_t local_port_size = port_size;
|
||||||
if (SPICE_SRAM_SCAN_CHAIN == sram_orgz_type) {
|
if (SPICE_SRAM_SCAN_CHAIN == sram_orgz_type) {
|
||||||
|
@ -72,6 +97,28 @@ void print_verilog_switch_block_local_sram_wires(std::fstream& fp,
|
||||||
print_verilog_local_sram_wires(fp, circuit_lib, sram_model, sram_orgz_type, local_port_size);
|
print_verilog_local_sram_wires(fp, circuit_lib, sram_model, sram_orgz_type, local_port_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Check if the MSB of a configuration bus of a switch block
|
||||||
|
* matches the expected value
|
||||||
|
* Exception:
|
||||||
|
* 1. Configuration bus for configuration chain will follow
|
||||||
|
* the number of multiplexers in the switch block
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
bool check_switch_block_mem_config_bus(const e_sram_orgz& sram_orgz_type,
|
||||||
|
const RRGSB& rr_gsb,
|
||||||
|
const BasicPort& config_bus,
|
||||||
|
const size_t& expected_msb) {
|
||||||
|
size_t local_expected_msb = expected_msb;
|
||||||
|
if (SPICE_SRAM_SCAN_CHAIN == sram_orgz_type) {
|
||||||
|
/* Note the size of local wires is number of routing multiplexers + 1
|
||||||
|
* Wire MSB is the number of routing multiplexers in the configuration chain
|
||||||
|
*/
|
||||||
|
local_expected_msb = find_switch_block_number_of_muxes(rr_gsb);
|
||||||
|
}
|
||||||
|
return check_mem_config_bus(sram_orgz_type, config_bus, local_expected_msb);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* 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
|
||||||
|
@ -2157,6 +2204,29 @@ void update_routing_connection_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_inf
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Generate a port for a routing track of a swtich block
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
BasicPort generate_verilog_connection_box_ipin_port(const RRGSB& rr_gsb,
|
||||||
|
t_rr_node* src_rr_node) {
|
||||||
|
|
||||||
|
/* Ensure the src_rr_node is an input pin of a CLB */
|
||||||
|
VTR_ASSERT(IPIN == src_rr_node->type);
|
||||||
|
/* Create port description for input pin of a CLB */
|
||||||
|
vtr::Point<size_t> port_coord(src_rr_node->xlow, src_rr_node->ylow);
|
||||||
|
/* Search all the sides of a SB, see this drive_rr_node is an INPUT of this SB */
|
||||||
|
enum e_side cb_ipin_side = NUM_SIDES;
|
||||||
|
int cb_ipin_index = -1;
|
||||||
|
rr_gsb.get_node_side_and_index(src_rr_node, OUT_PORT, &cb_ipin_side, &cb_ipin_index);
|
||||||
|
/* We need to be sure that drive_rr_node is part of the CB */
|
||||||
|
VTR_ASSERT((-1 != cb_ipin_index)&&(NUM_SIDES != cb_ipin_side));
|
||||||
|
std::string port_name = generate_grid_side_port_name(port_coord,
|
||||||
|
rr_gsb.get_ipin_node_grid_side(cb_ipin_side, cb_ipin_index),
|
||||||
|
rr_gsb.get_ipin_node(cb_ipin_side, cb_ipin_index)->ptc_num);
|
||||||
|
return BasicPort(port_name, 1); /* Every grid output has a port size of 1 */
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate a port for a routing track of a swtich block
|
* Generate a port for a routing track of a swtich block
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
@ -2179,6 +2249,39 @@ BasicPort generate_verilog_unique_switch_box_chan_port(const RRGSB& rr_sb,
|
||||||
return BasicPort(chan_port_name, 1); /* Every track has a port size of 1 */
|
return BasicPort(chan_port_name, 1); /* Every track has a port size of 1 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Generate an input port for routing multiplexer inside the connection block
|
||||||
|
* which is the middle output of a routing track
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
BasicPort generate_connection_block_chan_port(const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
t_rr_node* chan_rr_node) {
|
||||||
|
BasicPort input_port;
|
||||||
|
/* Generate the input port object */
|
||||||
|
switch (chan_rr_node->type) {
|
||||||
|
case CHANX:
|
||||||
|
case CHANY: {
|
||||||
|
/* Create port description for the routing track middle output */
|
||||||
|
vtr::Point<size_t> middle_output_port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||||
|
int chan_node_track_id = rr_gsb.get_cb_chan_node_index(cb_type, chan_rr_node);
|
||||||
|
/* Create a port description for the middle output */
|
||||||
|
std::string middle_output_port_name = generate_routing_track_middle_output_port_name(cb_type, middle_output_port_coord, chan_node_track_id);
|
||||||
|
input_port.set_name(middle_output_port_name);
|
||||||
|
input_port.set_width(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: /* OPIN, SOURCE, IPIN, SINK are invalid*/
|
||||||
|
vpr_printf(TIO_MESSAGE_ERROR,
|
||||||
|
"(File:%s, [LINE%d])Invalid rr_node type! Should be [OPIN|CHANX|CHANY].\n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return input_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate an input port for routing multiplexer inside the switch block
|
* Generate an input port for routing multiplexer inside the switch block
|
||||||
* In addition to give the Routing Resource node of the input
|
* In addition to give the Routing Resource node of the input
|
||||||
|
@ -2231,6 +2334,24 @@ BasicPort generate_switch_block_input_port(const RRGSB& rr_sb,
|
||||||
return input_port;
|
return input_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Generate a list of routing track middle output ports
|
||||||
|
* for routing multiplexer inside the connection block
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
std::vector<BasicPort> generate_connection_block_mux_input_ports(const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
const std::vector<t_rr_node*>& input_rr_nodes) {
|
||||||
|
std::vector<BasicPort> input_ports;
|
||||||
|
|
||||||
|
for (auto input_rr_node : input_rr_nodes) {
|
||||||
|
input_ports.push_back(generate_connection_block_chan_port(rr_gsb, cb_type, input_rr_node));
|
||||||
|
}
|
||||||
|
|
||||||
|
return input_ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Generate a list of input ports for routing multiplexer inside the switch block
|
* Generate a list of input ports for routing multiplexer inside the switch block
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
|
@ -2330,6 +2451,7 @@ static
|
||||||
void print_verilog_unique_switch_box_mux(ModuleManager& module_manager,
|
void print_verilog_unique_switch_box_mux(ModuleManager& module_manager,
|
||||||
std::fstream& fp,
|
std::fstream& fp,
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
BasicPort& config_bus,
|
||||||
const ModuleId& sb_module,
|
const ModuleId& sb_module,
|
||||||
const RRGSB& rr_sb,
|
const RRGSB& rr_sb,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
@ -2460,18 +2582,22 @@ void print_verilog_unique_switch_box_mux(ModuleManager& module_manager,
|
||||||
std::map<std::string, BasicPort> mem_port2port_name_map;
|
std::map<std::string, BasicPort> mem_port2port_name_map;
|
||||||
|
|
||||||
/* TODO: Make the port2port map generation more generic!!! */
|
/* TODO: Make the port2port map generation more generic!!! */
|
||||||
std::vector<BasicPort> config_ports;
|
/* Link the SRAM ports of the routing multiplexer to the memory module */
|
||||||
config_ports.push_back(BasicPort(generate_local_config_bus_port_name(), mux_instance_id - 1, mux_instance_id));
|
|
||||||
std::vector<BasicPort> mem_output_ports;
|
std::vector<BasicPort> mem_output_ports;
|
||||||
mem_output_ports.push_back(mux_config_port);
|
mem_output_ports.push_back(mux_config_port);
|
||||||
mem_output_ports.push_back(mux_config_inv_port);
|
mem_output_ports.push_back(mux_config_inv_port);
|
||||||
mem_port2port_name_map = generate_mem_module_port2port_map(module_manager, mem_module,
|
mem_port2port_name_map = generate_mem_module_port2port_map(module_manager, mem_module,
|
||||||
config_ports,
|
config_bus,
|
||||||
mem_output_ports,
|
mem_output_ports,
|
||||||
circuit_lib.design_tech_type(mux_model),
|
circuit_lib.design_tech_type(mux_model),
|
||||||
cur_sram_orgz_info->type);
|
cur_sram_orgz_info->type);
|
||||||
|
/* Update the config bus for the module */
|
||||||
|
update_mem_module_config_bus(cur_sram_orgz_info->type,
|
||||||
|
circuit_lib.design_tech_type(mux_model),
|
||||||
|
mux_num_config_bits,
|
||||||
|
config_bus);
|
||||||
|
|
||||||
/* Print an instance of the MUX Module */
|
/* Print an instance of the memory module associated with the routing multiplexer */
|
||||||
print_verilog_comment(fp, std::string("----- BEGIN Instanciation of memory cells for a routing multiplexer -----"));
|
print_verilog_comment(fp, std::string("----- BEGIN Instanciation of memory cells for a routing multiplexer -----"));
|
||||||
print_verilog_module_instance(fp, module_manager, sb_module, mem_module, mem_port2port_name_map, use_explicit_mapping);
|
print_verilog_module_instance(fp, module_manager, sb_module, mem_module, mem_port2port_name_map, use_explicit_mapping);
|
||||||
print_verilog_comment(fp, std::string("----- END Instanciation of memory cells for a routing multiplexer -----"));
|
print_verilog_comment(fp, std::string("----- END Instanciation of memory cells for a routing multiplexer -----"));
|
||||||
|
@ -2500,6 +2626,7 @@ static
|
||||||
void print_verilog_unique_switch_box_interc(ModuleManager& module_manager,
|
void print_verilog_unique_switch_box_interc(ModuleManager& module_manager,
|
||||||
std::fstream& fp,
|
std::fstream& fp,
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
BasicPort& config_bus,
|
||||||
const ModuleId& sb_module,
|
const ModuleId& sb_module,
|
||||||
const RRGSB& rr_sb,
|
const RRGSB& rr_sb,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
@ -2534,7 +2661,7 @@ void print_verilog_unique_switch_box_interc(ModuleManager& module_manager,
|
||||||
drive_rr_nodes[DEFAULT_SWITCH_ID]);
|
drive_rr_nodes[DEFAULT_SWITCH_ID]);
|
||||||
} else if (1 < drive_rr_nodes.size()) {
|
} else if (1 < drive_rr_nodes.size()) {
|
||||||
/* Print the multiplexer, fan_in >= 2 */
|
/* Print the multiplexer, fan_in >= 2 */
|
||||||
print_verilog_unique_switch_box_mux(module_manager, fp, cur_sram_orgz_info,
|
print_verilog_unique_switch_box_mux(module_manager, fp, cur_sram_orgz_info, config_bus,
|
||||||
sb_module, rr_sb, circuit_lib, mux_lib,
|
sb_module, rr_sb, circuit_lib, mux_lib,
|
||||||
rr_switches, chan_side, cur_rr_node,
|
rr_switches, chan_side, cur_rr_node,
|
||||||
drive_rr_nodes,
|
drive_rr_nodes,
|
||||||
|
@ -2734,6 +2861,11 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
|
||||||
rr_gsb.get_sb_num_conf_bits());
|
rr_gsb.get_sb_num_conf_bits());
|
||||||
print_verilog_comment(fp, std::string("---- END local wires for SRAM data ports ----"));
|
print_verilog_comment(fp, std::string("---- END local wires for SRAM data ports ----"));
|
||||||
|
|
||||||
|
/* Create a counter for the configuration bus */
|
||||||
|
BasicPort config_bus;
|
||||||
|
/* Counter start from 0 */
|
||||||
|
config_bus.set_width(0, 0);
|
||||||
|
|
||||||
/* TODO: Print routing multiplexers */
|
/* TODO: Print routing multiplexers */
|
||||||
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
|
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
|
||||||
Side side_manager(side);
|
Side side_manager(side);
|
||||||
|
@ -2741,7 +2873,8 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
|
||||||
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
|
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
|
||||||
/* We care INC_DIRECTION tracks at this side*/
|
/* We care INC_DIRECTION tracks at this side*/
|
||||||
if (OUT_PORT == rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
|
if (OUT_PORT == rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
|
||||||
print_verilog_unique_switch_box_interc(module_manager, fp, cur_sram_orgz_info, module_id, rr_sb,
|
print_verilog_unique_switch_box_interc(module_manager, fp, cur_sram_orgz_info, config_bus,
|
||||||
|
module_id, rr_sb,
|
||||||
circuit_lib, mux_lib, rr_switches,
|
circuit_lib, mux_lib, rr_switches,
|
||||||
side_manager.get_side(),
|
side_manager.get_side(),
|
||||||
itrack, is_explicit_mapping);
|
itrack, is_explicit_mapping);
|
||||||
|
@ -2749,6 +2882,11 @@ void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Add check code for config_bus. The MSB should match the number of configuration bits!!! */
|
||||||
|
VTR_ASSERT(true == check_switch_block_mem_config_bus(cur_sram_orgz_info->type,
|
||||||
|
rr_gsb, config_bus,
|
||||||
|
rr_gsb.get_sb_num_conf_bits()));
|
||||||
|
|
||||||
/* 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));
|
||||||
|
|
||||||
|
@ -3261,6 +3399,46 @@ int count_verilog_connection_box_one_side_reserved_conf_bits(t_sram_orgz_info* c
|
||||||
return num_reserved_conf_bits;
|
return num_reserved_conf_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Print a short interconneciton in connection
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_connection_box_short_interc(std::fstream& fp,
|
||||||
|
const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
t_rr_node* src_rr_node) {
|
||||||
|
/* Check the file handler*/
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Ensure we have only one 1 driver node */
|
||||||
|
VTR_ASSERT_SAFE(1 == src_rr_node->fan_in);
|
||||||
|
|
||||||
|
/* Find the driver node */
|
||||||
|
t_rr_node* drive_rr_node = src_rr_node->drive_rr_nodes[0];
|
||||||
|
|
||||||
|
/* We have OPINs since we may have direct connections:
|
||||||
|
* These connections should be handled by other functions in the compact_netlist.c
|
||||||
|
* So we just return here for OPINs
|
||||||
|
*/
|
||||||
|
if (OPIN == drive_rr_node->type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTR_ASSERT((CHANX == drive_rr_node->type) || (CHANY == drive_rr_node->type));
|
||||||
|
|
||||||
|
/* Create port description for the routing track middle output */
|
||||||
|
BasicPort middle_output_port = generate_connection_block_chan_port(rr_gsb, cb_type, drive_rr_node);
|
||||||
|
|
||||||
|
/* Create port description for input pin of a CLB */
|
||||||
|
BasicPort input_port = generate_verilog_connection_box_ipin_port(rr_gsb, src_rr_node);
|
||||||
|
|
||||||
|
/* Print the wire connection */
|
||||||
|
print_verilog_wire_connection(fp, input_port, middle_output_port, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* SRC rr_node is the IPIN of a grid.*/
|
/* SRC rr_node is the IPIN of a grid.*/
|
||||||
static
|
static
|
||||||
void dump_verilog_connection_box_short_interc(FILE* fp,
|
void dump_verilog_connection_box_short_interc(FILE* fp,
|
||||||
|
@ -3411,6 +3589,186 @@ void dump_verilog_connection_box_short_interc(FILE* fp,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* Print a Verilog instance of a routing multiplexer as well as
|
||||||
|
* associated memory modules for a connection inside a connection block
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_connection_box_mux(ModuleManager& module_manager,
|
||||||
|
std::fstream& fp,
|
||||||
|
t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
BasicPort& config_bus,
|
||||||
|
const ModuleId& cb_module,
|
||||||
|
const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const MuxLibrary& mux_lib,
|
||||||
|
const std::vector<t_switch_inf>& rr_switches,
|
||||||
|
t_rr_node* cur_rr_node,
|
||||||
|
const bool& use_explicit_mapping) {
|
||||||
|
/* Check the file handler*/
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Check */
|
||||||
|
/* Check current rr_node is an input pin of a CLB */
|
||||||
|
VTR_ASSERT(IPIN == cur_rr_node->type);
|
||||||
|
|
||||||
|
/* Build a vector of driver rr_nodes */
|
||||||
|
std::vector<t_rr_node*> drive_rr_nodes;
|
||||||
|
for (int inode = 0; inode < cur_rr_node->num_drive_rr_nodes; inode++) {
|
||||||
|
drive_rr_nodes.push_back(cur_rr_node->drive_rr_nodes[inode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int switch_index = cur_rr_node->drive_switches[DEFAULT_SWITCH_ID];
|
||||||
|
|
||||||
|
/* Get the circuit model id of the routing multiplexer */
|
||||||
|
CircuitModelId mux_model = rr_switches[switch_index].circuit_model;
|
||||||
|
|
||||||
|
/* Find the input size of the implementation of a routing multiplexer */
|
||||||
|
size_t datapath_mux_size = drive_rr_nodes.size();
|
||||||
|
|
||||||
|
/* Get the multiplexing graph from the Mux Library */
|
||||||
|
MuxId mux_id = mux_lib.mux_graph(mux_model, datapath_mux_size);
|
||||||
|
const MuxGraph& mux_graph = mux_lib.mux_graph(mux_id);
|
||||||
|
|
||||||
|
/* Find the module name of the multiplexer and try to find it in the module manager */
|
||||||
|
std::string mux_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(""));
|
||||||
|
ModuleId mux_module = module_manager.find_module(mux_module_name);
|
||||||
|
VTR_ASSERT (true == module_manager.valid_module_id(mux_module));
|
||||||
|
|
||||||
|
/* Get the MUX instance id from the module manager */
|
||||||
|
size_t mux_instance_id = module_manager.num_instance(cb_module, mux_module);
|
||||||
|
|
||||||
|
/* Print the input bus for the inputs of a multiplexer
|
||||||
|
* We use the datapath input size (mux_size) to name the bus
|
||||||
|
* just to following the naming convention when the tool is built
|
||||||
|
* The bus port size should be the input size of multiplexer implementation
|
||||||
|
*/
|
||||||
|
BasicPort inbus_port;
|
||||||
|
inbus_port.set_name(generate_mux_input_bus_port_name(circuit_lib, mux_model, datapath_mux_size, mux_instance_id));
|
||||||
|
inbus_port.set_width(datapath_mux_size);
|
||||||
|
|
||||||
|
/* TODO: Generate input ports that are wired to the input bus of the routing multiplexer */
|
||||||
|
std::vector<BasicPort> mux_input_ports = generate_connection_block_mux_input_ports(rr_gsb, cb_type, drive_rr_nodes);
|
||||||
|
/* Connect input ports to bus */
|
||||||
|
print_verilog_comment(fp, std::string("----- BEGIN A local bus wire for multiplexer inputs -----"));
|
||||||
|
fp << generate_verilog_local_wire(inbus_port, mux_input_ports) << std::endl;
|
||||||
|
print_verilog_comment(fp, std::string("----- END A local bus wire for multiplexer inputs -----"));
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Find the number of reserved configuration bits for the routing multiplexer */
|
||||||
|
size_t mux_num_reserved_config_bits = find_mux_num_reserved_config_bits(circuit_lib, mux_model, mux_graph);
|
||||||
|
|
||||||
|
/* Find the number of configuration bits for the routing multiplexer */
|
||||||
|
size_t mux_num_config_bits = find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, cur_sram_orgz_info->type);
|
||||||
|
|
||||||
|
/* Print the configuration bus for the routing multiplexers */
|
||||||
|
print_verilog_comment(fp, std::string("----- BEGIN Local wires to group configuration ports -----"));
|
||||||
|
print_verilog_mux_config_bus(fp, circuit_lib, mux_model, cur_sram_orgz_info->type,
|
||||||
|
datapath_mux_size, mux_instance_id,
|
||||||
|
mux_num_reserved_config_bits, mux_num_config_bits);
|
||||||
|
print_verilog_comment(fp, std::string("----- END Local wires to group configuration ports -----"));
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Dump ports visible only during formal verification */
|
||||||
|
print_verilog_comment(fp, std::string("----- BEGIN Local wires used in only formal verification purpose -----"));
|
||||||
|
print_verilog_preprocessing_flag(fp, std::string(verilog_formal_verification_preproc_flag));
|
||||||
|
/* Print the SRAM configuration ports for formal verification */
|
||||||
|
/* TODO: align with the port width of formal verification port of SB module */
|
||||||
|
print_verilog_formal_verification_mux_sram_ports_wiring(fp, circuit_lib, mux_model,
|
||||||
|
datapath_mux_size, mux_instance_id, mux_num_config_bits);
|
||||||
|
print_verilog_endif(fp);
|
||||||
|
print_verilog_comment(fp, std::string("----- END Local wires used in only formal verification purpose -----"));
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Instanciate the MUX Module */
|
||||||
|
/* Create port-to-port map */
|
||||||
|
std::map<std::string, BasicPort> mux_port2port_name_map;
|
||||||
|
|
||||||
|
/* Link input bus port to routing track middle outputs */
|
||||||
|
std::vector<CircuitPortId> mux_model_input_ports = circuit_lib.model_ports_by_type(mux_model, SPICE_MODEL_PORT_INPUT, true);
|
||||||
|
VTR_ASSERT(1 == mux_model_input_ports.size());
|
||||||
|
/* Use the port name convention in the circuit library */
|
||||||
|
mux_port2port_name_map[circuit_lib.port_lib_name(mux_model_input_ports[0])] = inbus_port;
|
||||||
|
|
||||||
|
/* Link output port to Connection Block output: src_rr_node */
|
||||||
|
std::vector<CircuitPortId> mux_model_output_ports = circuit_lib.model_ports_by_type(mux_model, SPICE_MODEL_PORT_OUTPUT, true);
|
||||||
|
VTR_ASSERT(1 == mux_model_output_ports.size());
|
||||||
|
/* Use the port name convention in the circuit library */
|
||||||
|
mux_port2port_name_map[circuit_lib.port_lib_name(mux_model_output_ports[0])] = generate_verilog_connection_box_ipin_port(rr_gsb, cur_rr_node);
|
||||||
|
|
||||||
|
/* Link SRAM port to different configuraton port for the routing multiplexer
|
||||||
|
* Different design technology requires different configuration bus!
|
||||||
|
*/
|
||||||
|
std::vector<CircuitPortId> mux_model_sram_ports = circuit_lib.model_ports_by_type(mux_model, SPICE_MODEL_PORT_SRAM, true);
|
||||||
|
VTR_ASSERT( 1 == mux_model_sram_ports.size() );
|
||||||
|
/* For the regular SRAM port, module port use the same name */
|
||||||
|
std::string mux_module_sram_port_name = circuit_lib.port_lib_name(mux_model_sram_ports[0]);
|
||||||
|
BasicPort mux_config_port(generate_mux_sram_port_name(circuit_lib, mux_model, datapath_mux_size, mux_instance_id, SPICE_MODEL_PORT_INPUT),
|
||||||
|
mux_num_config_bits);
|
||||||
|
mux_port2port_name_map[mux_module_sram_port_name] = mux_config_port;
|
||||||
|
|
||||||
|
/* For the inverted SRAM port */
|
||||||
|
std::string mux_module_sram_inv_port_name = circuit_lib.port_lib_name(mux_model_sram_ports[0]) + std::string("_inv");
|
||||||
|
BasicPort mux_config_inv_port(generate_mux_sram_port_name(circuit_lib, mux_model, datapath_mux_size, mux_instance_id, SPICE_MODEL_PORT_OUTPUT),
|
||||||
|
mux_num_config_bits);
|
||||||
|
mux_port2port_name_map[mux_module_sram_inv_port_name] = mux_config_inv_port;
|
||||||
|
|
||||||
|
/* Print an instance of the MUX Module */
|
||||||
|
print_verilog_comment(fp, std::string("----- BEGIN Instanciation of a routing multiplexer -----"));
|
||||||
|
print_verilog_module_instance(fp, module_manager, cb_module, mux_module, mux_port2port_name_map, use_explicit_mapping);
|
||||||
|
print_verilog_comment(fp, std::string("----- END Instanciation of a routing multiplexer -----"));
|
||||||
|
fp << std::endl;
|
||||||
|
/* IMPORTANT: this update MUST be called after the instance outputting!!!!
|
||||||
|
* update the module manager with the relationship between the parent and child modules
|
||||||
|
*/
|
||||||
|
module_manager.add_child_module(cb_module, mux_module);
|
||||||
|
|
||||||
|
/* Instanciate memory modules */
|
||||||
|
/* Find the name and module id of the memory module */
|
||||||
|
std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(verilog_mem_posfix));
|
||||||
|
ModuleId mem_module = module_manager.find_module(mem_module_name);
|
||||||
|
VTR_ASSERT (true == module_manager.valid_module_id(mem_module));
|
||||||
|
|
||||||
|
/* Create port-to-port map */
|
||||||
|
std::map<std::string, BasicPort> mem_port2port_name_map;
|
||||||
|
|
||||||
|
/* TODO: Make the port2port map generation more generic!!! */
|
||||||
|
/* Link the SRAM ports of the routing multiplexer to the memory module */
|
||||||
|
std::vector<BasicPort> mem_output_ports;
|
||||||
|
mem_output_ports.push_back(mux_config_port);
|
||||||
|
mem_output_ports.push_back(mux_config_inv_port);
|
||||||
|
mem_port2port_name_map = generate_mem_module_port2port_map(module_manager, mem_module,
|
||||||
|
config_bus,
|
||||||
|
mem_output_ports,
|
||||||
|
circuit_lib.design_tech_type(mux_model),
|
||||||
|
cur_sram_orgz_info->type);
|
||||||
|
/* Update the config bus for the module */
|
||||||
|
update_mem_module_config_bus(cur_sram_orgz_info->type,
|
||||||
|
circuit_lib.design_tech_type(mux_model),
|
||||||
|
mux_num_config_bits,
|
||||||
|
config_bus);
|
||||||
|
|
||||||
|
/* Print an instance of the memory module associated with the routing multiplexer */
|
||||||
|
print_verilog_comment(fp, std::string("----- BEGIN Instanciation of memory cells for a routing multiplexer -----"));
|
||||||
|
print_verilog_module_instance(fp, module_manager, cb_module, mem_module, mem_port2port_name_map, use_explicit_mapping);
|
||||||
|
print_verilog_comment(fp, std::string("----- END Instanciation of memory cells for a routing multiplexer -----"));
|
||||||
|
fp << std::endl;
|
||||||
|
/* IMPORTANT: this update MUST be called after the instance outputting!!!!
|
||||||
|
* update the module manager with the relationship between the parent and child modules
|
||||||
|
*/
|
||||||
|
module_manager.add_child_module(cb_module, mem_module);
|
||||||
|
|
||||||
|
/* Create the path of the input of multiplexer in the hierarchy
|
||||||
|
* TODO: this MUST be deprecated later because module manager is created to handle these problems!!!
|
||||||
|
*/
|
||||||
|
std::string mux_input_hie_path = std::string(rr_gsb.gen_cb_verilog_instance_name(cb_type)) + std::string("/")
|
||||||
|
+ mux_module_name + std::string("_")
|
||||||
|
+ std::to_string(mux_instance_id) + std::string("_/in");
|
||||||
|
cur_rr_node->name_mux = my_strdup(mux_input_hie_path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void dump_verilog_connection_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
|
void dump_verilog_connection_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
FILE* fp,
|
FILE* fp,
|
||||||
|
@ -3903,6 +4261,43 @@ void dump_verilog_connection_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print internal connections of a connection block
|
||||||
|
* For a IPIN node that is driven by only 1 fan-in,
|
||||||
|
* a short wire will be created
|
||||||
|
* For a IPIN node that is driven by more than two fan-ins,
|
||||||
|
* a routing multiplexer will be instanciated
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_connection_box_interc(ModuleManager& module_manager,
|
||||||
|
std::fstream& fp,
|
||||||
|
t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
BasicPort& config_bus,
|
||||||
|
const ModuleId& cb_module,
|
||||||
|
const RRGSB& rr_gsb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const MuxLibrary& mux_lib,
|
||||||
|
const std::vector<t_switch_inf>& rr_switches,
|
||||||
|
t_rr_node* src_rr_node,
|
||||||
|
const bool& use_explicit_mapping) {
|
||||||
|
if (1 > src_rr_node->fan_in) {
|
||||||
|
return; /* This port has no driver, skip it */
|
||||||
|
} else if (1 == src_rr_node->fan_in) {
|
||||||
|
/* Print a direct connection */
|
||||||
|
print_verilog_connection_box_short_interc(fp, rr_gsb, cb_type, src_rr_node);
|
||||||
|
|
||||||
|
} else if (1 < src_rr_node->fan_in) {
|
||||||
|
/* Print the multiplexer, fan_in >= 2 */
|
||||||
|
print_verilog_connection_box_mux(module_manager, fp, cur_sram_orgz_info, config_bus,
|
||||||
|
cb_module, rr_gsb, cb_type,
|
||||||
|
circuit_lib, mux_lib, rr_switches,
|
||||||
|
src_rr_node, use_explicit_mapping);
|
||||||
|
} /*Nothing should be done else*/
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void dump_verilog_connection_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
|
void dump_verilog_connection_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
FILE* fp,
|
FILE* fp,
|
||||||
|
@ -4050,6 +4445,279 @@ int count_verilog_connection_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_o
|
||||||
return num_reserved_conf_bits;
|
return num_reserved_conf_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Print the sub-circuit of a connection Box (Type: [CHANX|CHANY])
|
||||||
|
* Actually it is very similiar to switch box but
|
||||||
|
* the difference is connection boxes connect Grid INPUT Pins to channels
|
||||||
|
* NOTE: direct connection between CLBs should NOT be included inside this
|
||||||
|
* module! They should be added in the top-level module as their connection
|
||||||
|
* is not limited to adjacent CLBs!!!
|
||||||
|
*
|
||||||
|
* Location of a X- and Y-direction Connection Block in FPGA fabric
|
||||||
|
* +------------+ +-------------+
|
||||||
|
* | |------>| |
|
||||||
|
* | CLB |<------| Y-direction |
|
||||||
|
* | | ... | Connection |
|
||||||
|
* | |------>| Block |
|
||||||
|
* +------------+ +-------------+
|
||||||
|
* | ^ ... | | ^ ... |
|
||||||
|
* v | v v | v
|
||||||
|
* +-------------------+ +-------------+
|
||||||
|
* --->| |--->| |
|
||||||
|
* <---| X-direction |<---| Switch |
|
||||||
|
* ...| Connection block |... | Block |
|
||||||
|
* --->| |--->| |
|
||||||
|
* +-------------------+ +-------------+
|
||||||
|
*
|
||||||
|
* Internal structure:
|
||||||
|
* This is an example of a X-direction connection block
|
||||||
|
* Note that middle output ports are shorted wire from inputs of routing tracks,
|
||||||
|
* which are also the inputs of routing multiplexer of the connection block
|
||||||
|
*
|
||||||
|
* CLB Input Pins
|
||||||
|
* (IPINs)
|
||||||
|
* ^ ^ ^
|
||||||
|
* | | ... |
|
||||||
|
* +--------------------------+
|
||||||
|
* | ^ ^ ^ |
|
||||||
|
* | | | ... | |
|
||||||
|
* | +--------------------+ |
|
||||||
|
* | | routing | |
|
||||||
|
* | | multiplexers | |
|
||||||
|
* | +--------------------+ |
|
||||||
|
* | middle outputs |
|
||||||
|
* | of routing channel |
|
||||||
|
* | ^ ^ ^ ^ ^ ^ ^ ^ |
|
||||||
|
* | | | | | ... | | | | |
|
||||||
|
* in[0] -->|------------------------->|---> out[0]
|
||||||
|
* out[1] <--|<-------------------------|<--- in[1]
|
||||||
|
* | ... |
|
||||||
|
* in[W-2] -->|------------------------->|---> out[W-2]
|
||||||
|
* out[W-1] <--|<-------------------------|<--- in[W-1]
|
||||||
|
* +--------------------------+
|
||||||
|
*
|
||||||
|
* W: routing channel width
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
static
|
||||||
|
void print_verilog_routing_connection_box_unique_module(ModuleManager& module_manager,
|
||||||
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const MuxLibrary& mux_lib,
|
||||||
|
const std::vector<t_switch_inf>& rr_switches,
|
||||||
|
t_sram_orgz_info* cur_sram_orgz_info,
|
||||||
|
const std::string& verilog_dir,
|
||||||
|
const std::string& subckt_dir,
|
||||||
|
const RRGSB& rr_cb,
|
||||||
|
const t_rr_type& cb_type,
|
||||||
|
const bool& use_explicit_mapping) {
|
||||||
|
RRGSB rr_gsb = rr_cb; /* IMPORTANT: this copy will be removed when the config ports are initialized when created!!! */
|
||||||
|
|
||||||
|
/* TODO: These should be done when initializing the tool */
|
||||||
|
/* Count the number of configuration bits to be consumed by this Switch block */
|
||||||
|
int num_conf_bits = count_verilog_connection_box_conf_bits(cur_sram_orgz_info, rr_gsb, cb_type);
|
||||||
|
/* Count the number of reserved configuration bits to be consumed by this Switch block */
|
||||||
|
int num_reserved_conf_bits = count_verilog_connection_box_reserved_conf_bits(cur_sram_orgz_info, rr_gsb, cb_type);
|
||||||
|
/* Estimate the sram_verilog_model->cnt */
|
||||||
|
int cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
||||||
|
/* Record index */
|
||||||
|
rr_gsb.set_cb_num_reserved_conf_bits(cb_type, num_reserved_conf_bits);
|
||||||
|
rr_gsb.set_cb_conf_bits_lsb(cb_type, cur_num_sram);
|
||||||
|
rr_gsb.set_cb_conf_bits_msb(cb_type, cur_num_sram + num_conf_bits - 1);
|
||||||
|
|
||||||
|
/* Create the netlist */
|
||||||
|
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||||
|
std::string verilog_fname(subckt_dir + generate_connection_block_netlist_name(cb_type, gsb_coordinate, std::string(verilog_netlist_file_postfix)));
|
||||||
|
/* TODO: remove the bak file when the file is ready */
|
||||||
|
verilog_fname += ".bak";
|
||||||
|
|
||||||
|
/* Create the file stream */
|
||||||
|
std::fstream fp;
|
||||||
|
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
|
||||||
|
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
print_verilog_file_header(fp, std::string("Verilog modules for Unique Connection Blocks[" + std::to_string(rr_gsb.get_cb_x(cb_type)) + "]["+ std::to_string(rr_gsb.get_cb_y(cb_type)) + "]"));
|
||||||
|
|
||||||
|
/* Print preprocessing flags */
|
||||||
|
print_verilog_include_defines_preproc_file(fp, verilog_dir);
|
||||||
|
|
||||||
|
/* Create a Verilog Module based on the circuit model, and add to module manager */
|
||||||
|
ModuleId module_id = module_manager.add_module(generate_connection_block_module_name(cb_type, gsb_coordinate));
|
||||||
|
|
||||||
|
/* Add ports to the module */
|
||||||
|
/* Global ports:
|
||||||
|
* In the circuit_library, find all the circuit models that may be included in the Connection Block
|
||||||
|
* Collect the global ports from the circuit_models and merge with the same name
|
||||||
|
*/
|
||||||
|
std::vector<CircuitPortId> global_ports = find_connection_block_global_ports(rr_gsb, cb_type, circuit_lib, rr_switches);
|
||||||
|
for (const auto& port : global_ports) {
|
||||||
|
BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
|
||||||
|
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_GLOBAL_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the input and output ports of routing tracks in the channel
|
||||||
|
* Routing tracks pass through the connection blocks
|
||||||
|
*/
|
||||||
|
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
|
||||||
|
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||||
|
std::string port_name = generate_routing_track_port_name(cb_type,
|
||||||
|
port_coord, itrack,
|
||||||
|
IN_PORT);
|
||||||
|
BasicPort module_port(port_name, 1); /* Every track has a port size of 1 */
|
||||||
|
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT);
|
||||||
|
}
|
||||||
|
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
|
||||||
|
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||||
|
std::string port_name = generate_routing_track_port_name(cb_type,
|
||||||
|
port_coord, itrack,
|
||||||
|
OUT_PORT);
|
||||||
|
BasicPort module_port(port_name, 1); /* Every track has a port size of 1 */
|
||||||
|
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the input pins of grids, which are output ports of the connection block */
|
||||||
|
std::vector<enum e_side> cb_ipin_sides = rr_gsb.get_cb_ipin_sides(cb_type);
|
||||||
|
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
|
||||||
|
enum e_side cb_ipin_side = cb_ipin_sides[iside];
|
||||||
|
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
|
||||||
|
t_rr_node* ipin_node = rr_gsb.get_ipin_node(cb_ipin_side, inode);
|
||||||
|
vtr::Point<size_t> port_coord(ipin_node->xlow, ipin_node->ylow);
|
||||||
|
std::string port_name = generate_grid_side_port_name(port_coord,
|
||||||
|
rr_gsb.get_ipin_node_grid_side(cb_ipin_side, inode),
|
||||||
|
ipin_node->ptc_num);
|
||||||
|
BasicPort module_port(port_name, 1); /* Every grid output has a port size of 1 */
|
||||||
|
/* Grid outputs are inputs of switch blocks */
|
||||||
|
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add configuration ports */
|
||||||
|
/* Reserved sram ports */
|
||||||
|
if (0 < rr_gsb.get_cb_num_reserved_conf_bits(cb_type)) {
|
||||||
|
/* 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_cb_num_reserved_conf_bits(cb_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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_cb_num_conf_bits(cb_type)) {
|
||||||
|
add_sram_ports_to_module_manager(module_manager, module_id,
|
||||||
|
circuit_lib, sram_model, cur_sram_orgz_info->type,
|
||||||
|
rr_gsb.get_cb_num_conf_bits(cb_type));
|
||||||
|
/* 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,
|
||||||
|
std::string(verilog_formal_verification_preproc_flag),
|
||||||
|
rr_gsb.get_cb_num_conf_bits(cb_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print module definition + ports */
|
||||||
|
print_verilog_module_declaration(fp, module_manager, module_id);
|
||||||
|
/* Finish printing ports */
|
||||||
|
|
||||||
|
/* Print an empty line a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Print local wires, which are middle outputs of routing tracks */
|
||||||
|
print_verilog_comment(fp, std::string("---- BEGIN local wires for middle output ports of routing tracks ----"));
|
||||||
|
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
|
||||||
|
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||||
|
/* Create a port description for the middle output */
|
||||||
|
std::string port_name = generate_routing_track_middle_output_port_name(cb_type,
|
||||||
|
port_coord, itrack);
|
||||||
|
BasicPort middle_output_port(port_name, 1);
|
||||||
|
fp << generate_verilog_port(VERILOG_PORT_WIRE, middle_output_port) << ";" << std::endl;
|
||||||
|
}
|
||||||
|
print_verilog_comment(fp, std::string("---- END local wires for middle output ports of routing tracks ----"));
|
||||||
|
/* Print an empty line a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Print short-wire connection for each routing track :
|
||||||
|
* Each input port is short-wired to its output port and middle output port
|
||||||
|
*
|
||||||
|
* in[i] ----------> out[i]
|
||||||
|
* |
|
||||||
|
* +-----> mid_out[i]
|
||||||
|
*/
|
||||||
|
print_verilog_comment(fp, std::string("---- BEGIN wire connection between inputs, outputs and middle outputs of routing tracks ----"));
|
||||||
|
for (size_t itrack = 0; itrack < rr_gsb.get_cb_chan_width(cb_type); ++itrack) {
|
||||||
|
vtr::Point<size_t> port_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
|
||||||
|
/* Create a port description for the input */
|
||||||
|
std::string input_port_name = generate_routing_track_port_name(cb_type,
|
||||||
|
port_coord, itrack,
|
||||||
|
IN_PORT);
|
||||||
|
BasicPort input_port(input_port_name, 1); /* Every track has a port size of 1 */
|
||||||
|
|
||||||
|
/* Create a port description for the output */
|
||||||
|
std::string output_port_name = generate_routing_track_port_name(cb_type,
|
||||||
|
port_coord, itrack,
|
||||||
|
OUT_PORT);
|
||||||
|
BasicPort output_port(output_port_name, 1); /* Every track has a port size of 1 */
|
||||||
|
|
||||||
|
/* Create a port description for the middle output */
|
||||||
|
std::string middle_output_port_name = generate_routing_track_middle_output_port_name(cb_type, port_coord, itrack);
|
||||||
|
BasicPort middle_output_port(middle_output_port_name, 1);
|
||||||
|
|
||||||
|
/* Print short-wires: input port ---> output port */
|
||||||
|
print_verilog_wire_connection(fp, output_port, input_port, false);
|
||||||
|
/* Print short-wires: input port ---> middle output port */
|
||||||
|
print_verilog_wire_connection(fp, middle_output_port, input_port, false);
|
||||||
|
}
|
||||||
|
print_verilog_comment(fp, std::string("---- END wire connection between inputs, outputs and middle outputs of routing tracks ----"));
|
||||||
|
|
||||||
|
/* Print an empty line a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
print_verilog_comment(fp, std::string("---- BEGIN local wires for SRAM data ports ----"));
|
||||||
|
/* Print local wires for memory configurations */
|
||||||
|
print_verilog_connection_block_local_sram_wires(fp, rr_gsb, cb_type, circuit_lib, sram_model, cur_sram_orgz_info->type,
|
||||||
|
rr_gsb.get_cb_num_conf_bits(cb_type));
|
||||||
|
print_verilog_comment(fp, std::string("---- END local wires for SRAM data ports ----"));
|
||||||
|
|
||||||
|
/* Print an empty line a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Create a counter for the configuration bus */
|
||||||
|
BasicPort config_bus;
|
||||||
|
/* Counter start from 0 */
|
||||||
|
config_bus.set_width(0, 0);
|
||||||
|
|
||||||
|
/* TODO: Print routing multiplexers or direct interconnect*/
|
||||||
|
for (size_t iside = 0; iside < cb_ipin_sides.size(); ++iside) {
|
||||||
|
enum e_side cb_ipin_side = cb_ipin_sides[iside];
|
||||||
|
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
|
||||||
|
print_verilog_connection_box_interc(module_manager, fp, cur_sram_orgz_info,
|
||||||
|
config_bus, module_id, rr_gsb, cb_type,
|
||||||
|
circuit_lib, mux_lib, rr_switches,
|
||||||
|
rr_gsb.get_ipin_node(cb_ipin_side, inode),
|
||||||
|
use_explicit_mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put an end to the Verilog module */
|
||||||
|
print_verilog_module_end(fp, module_manager.module_name(module_id));
|
||||||
|
|
||||||
|
/* Add an empty line as a splitter */
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
/* Close file handler */
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
/* Add fname to the linked list */
|
||||||
|
/*
|
||||||
|
routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, fname);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Print connection boxes
|
/* Print connection boxes
|
||||||
* Print the sub-circuit of a connection Box (Type: [CHANX|CHANY])
|
* Print the sub-circuit of a connection Box (Type: [CHANX|CHANY])
|
||||||
* Actually it is very similiar to switch box but
|
* Actually it is very similiar to switch box but
|
||||||
|
@ -4632,6 +5300,15 @@ void print_verilog_routing_resources(ModuleManager& module_manager,
|
||||||
dump_verilog_routing_connection_box_unique_module(cur_sram_orgz_info,
|
dump_verilog_routing_connection_box_unique_module(cur_sram_orgz_info,
|
||||||
verilog_dir, subckt_dir, unique_mirror, CHANX,
|
verilog_dir, subckt_dir, unique_mirror, CHANX,
|
||||||
explicit_port_mapping);
|
explicit_port_mapping);
|
||||||
|
|
||||||
|
print_verilog_routing_connection_box_unique_module(module_manager,
|
||||||
|
arch.spice->circuit_lib, mux_lib,
|
||||||
|
rr_switches,
|
||||||
|
cur_sram_orgz_info,
|
||||||
|
std::string(verilog_dir),
|
||||||
|
std::string(subckt_dir),
|
||||||
|
unique_mirror, CHANX,
|
||||||
|
explicit_port_mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Y - channels [1...ny][0..nx]*/
|
/* Y - channels [1...ny][0..nx]*/
|
||||||
|
@ -4640,6 +5317,15 @@ void print_verilog_routing_resources(ModuleManager& module_manager,
|
||||||
dump_verilog_routing_connection_box_unique_module(cur_sram_orgz_info,
|
dump_verilog_routing_connection_box_unique_module(cur_sram_orgz_info,
|
||||||
verilog_dir, subckt_dir, unique_mirror, CHANY,
|
verilog_dir, subckt_dir, unique_mirror, CHANY,
|
||||||
explicit_port_mapping);
|
explicit_port_mapping);
|
||||||
|
|
||||||
|
print_verilog_routing_connection_box_unique_module(module_manager,
|
||||||
|
arch.spice->circuit_lib, mux_lib,
|
||||||
|
rr_switches,
|
||||||
|
cur_sram_orgz_info,
|
||||||
|
std::string(verilog_dir),
|
||||||
|
std::string(subckt_dir),
|
||||||
|
unique_mirror, CHANY,
|
||||||
|
explicit_port_mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore sram_orgz_info to the base */
|
/* Restore sram_orgz_info to the base */
|
||||||
|
|
Loading…
Reference in New Issue