add instance name correlation between module and bitstream generation

This commit is contained in:
tangxifan 2019-10-25 13:06:48 -06:00
parent cb147c1180
commit 4b7a9dfa63
9 changed files with 259 additions and 63 deletions

View File

@ -8,7 +8,9 @@
#include "vtr_assert.h"
#include "sides.h"
#include "vpr_types.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "circuit_library_utils.h"
#include "fpga_x2p_naming.h"
@ -372,6 +374,28 @@ std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
return port_name;
}
/*********************************************************************
* Generate the port name for a Grid
* This is a wrapper function for generate_port_name()
* which can automatically decode the port name by the pin side and height
*********************************************************************/
std::string generate_grid_side_port_name(const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& coordinate,
const e_side& side,
const size_t& pin_id) {
/* Output the pins on the side*/
size_t height = find_grid_pin_height(grids, coordinate, pin_id);
if (1 != grids[coordinate.x()][coordinate.y()].type->pinloc[height][side][pin_id]) {
Side side_manager(side);
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Fail to generate a grid pin (x=%lu, y=%lu, height=%lu, side=%s, index=%d)\n",
__FILE__, __LINE__,
coordinate.x(), coordinate.y(), height, side_manager.c_str(), pin_id);
exit(1);
}
return generate_grid_port_name(coordinate, height, side, pin_id, true);
}
/*********************************************************************
* Generate the port name for a reserved sram port, i.e., BLB/WL port
* When port_type is BLB, a string denoting to the reserved BLB port is generated
@ -742,13 +766,29 @@ std::string generate_sb_memory_instance_name(const std::string& prefix,
const size_t& track_id,
const std::string& postfix) {
std::string instance_name(prefix);
instance_name += std::string("_") + Side(sb_side).to_string();
instance_name += Side(sb_side).to_string();
instance_name += std::string("_track_") + std::to_string(track_id);
instance_name += postfix;
return instance_name;
}
/*********************************************************************
* Generate the instance name for a configurable memory module in a Connection Block
********************************************************************/
std::string generate_cb_memory_instance_name(const std::string& prefix,
const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& coordinate,
const e_side& cb_side,
const size_t& pin_id,
const std::string& postfix) {
std::string instance_name(prefix);
instance_name += generate_grid_side_port_name(grids, coordinate, cb_side, pin_id);
instance_name += postfix;
return instance_name;
}
/*********************************************************************
* Generate the instance name of a grid block

View File

@ -81,12 +81,24 @@ std::string generate_sb_memory_instance_name(const std::string& prefix,
const size_t& track_id,
const std::string& postfix);
std::string generate_cb_memory_instance_name(const std::string& prefix,
const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& coordinate,
const e_side& cb_side,
const size_t& pin_id,
const std::string& postfix);
std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
const size_t& height,
const e_side& side,
const size_t& pin_id,
const bool& for_top_netlist);
std::string generate_grid_side_port_name(const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& coordinate,
const e_side& side,
const size_t& pin_id);
std::string generate_reserved_sram_port_name(const e_spice_model_port_type& port_type);
std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib,

View File

@ -8,6 +8,7 @@
#define FPGA_X2P_RESERVED_WORDS_H
constexpr char* SWITCH_BLOCK_MEM_INSTANCE_PREFIX = "mem_";
constexpr char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_";
constexpr char* MEMORY_MODULE_POSTFIX = "_mem";
#endif

View File

@ -77,7 +77,7 @@ BitstreamManager build_device_bitstream(const t_vpr_setup& vpr_setup,
ConfigBlockId top_block = bitstream_manager.add_block(top_block_name);
/* Create bitstream from routing architectures */
build_routing_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, rr_switches, L_rr_node, L_device_rr_gsb);
build_routing_bitstream(bitstream_manager, top_block, module_manager, circuit_lib, mux_lib, grids, rr_switches, L_rr_node, L_device_rr_gsb);
/* End time count */
clock_t t_end = clock();

View File

@ -59,7 +59,7 @@ void build_switch_block_mux_bitstream(BitstreamManager& bitstream_manager,
);
/* Generate bitstream depend on both technology and structure of this MUX */
std::vector<bool> mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id);
std::vector<bool> mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id);
/* Find the module in module manager and ensure the bitstream size matches! */
std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX));
@ -141,7 +141,7 @@ void build_switch_block_interc_bitstream(BitstreamManager& bitstream_manager,
*******************************************************************/
static
void build_switch_block_bitstream(BitstreamManager& bitstream_manager,
const ConfigBlockId& sb_configurable_block,
const ConfigBlockId& sb_config_block,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
@ -159,7 +159,7 @@ void build_switch_block_bitstream(BitstreamManager& bitstream_manager,
if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
continue;
}
build_switch_block_interc_bitstream(bitstream_manager, sb_configurable_block,
build_switch_block_interc_bitstream(bitstream_manager, sb_config_block,
module_manager,
circuit_lib, mux_lib, rr_switches, L_rr_node,
rr_gsb, side_manager.get_side(), itrack);
@ -167,6 +167,178 @@ void build_switch_block_bitstream(BitstreamManager& bitstream_manager,
}
}
/********************************************************************
* This function generates bitstream for a routing multiplexer
* in a Connection block
* This function will identify if a node indicates a routing multiplexer
* If not a routing multiplexer, no bitstream is needed here
* If yes, we will generate the bitstream for the routing multiplexer
*******************************************************************/
static
void build_connection_block_mux_bitstream(BitstreamManager& bitstream_manager,
const ConfigBlockId& mux_mem_block,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* L_rr_node,
t_rr_node* src_rr_node) {
/* Find the circuit model id of the mux, we need its design technology which matters the bitstream generation */
int switch_index = src_rr_node->drive_switches[DEFAULT_SWITCH_ID];
CircuitModelId mux_model = rr_switches[switch_index].circuit_model;
/* Find drive_rr_nodes*/
size_t datapath_mux_size = (size_t)(src_rr_node->num_drive_rr_nodes);
/* Configuration bits for MUX*/
int path_id = DEFAULT_PATH_ID;
for (size_t inode = 0; inode < datapath_mux_size; ++inode) {
if (src_rr_node->drive_rr_nodes[inode] == &(L_rr_node[src_rr_node->prev_node])) {
path_id = (int)inode;
break;
}
}
/* Ensure that our path id makes sense! */
VTR_ASSERT( (DEFAULT_PATH_ID == path_id)
|| ( (DEFAULT_PATH_ID < path_id) && (path_id < (int)datapath_mux_size) )
);
/* Generate bitstream depend on both technology and structure of this MUX */
std::vector<bool> mux_bitstream = build_mux_bitstream(circuit_lib, mux_model, mux_lib, datapath_mux_size, path_id);
/* Find the module in module manager and ensure the bitstream size matches! */
std::string mem_module_name = generate_mux_subckt_name(circuit_lib, mux_model, datapath_mux_size, std::string(MEMORY_MODULE_POSTFIX));
ModuleId mux_mem_module = module_manager.find_module(mem_module_name);
VTR_ASSERT (true == module_manager.valid_module_id(mux_mem_module));
ModulePortId mux_mem_out_port_id = module_manager.find_module_port(mux_mem_module, generate_configuration_chain_data_out_name());
VTR_ASSERT(mux_bitstream.size() == module_manager.module_port(mux_mem_module, mux_mem_out_port_id).get_width());
/* Add the bistream to the bitstream manager */
for (const bool& bit : mux_bitstream) {
ConfigBitId config_bit = bitstream_manager.add_bit(bit);
/* Link the memory bits to the mux mem block */
bitstream_manager.add_bit_to_block(mux_mem_block, config_bit);
}
}
/********************************************************************
* This function generates bitstream for an interconnection,
* i.e., a routing multiplexer, in a Connection Block
* This function will identify if a node indicates a routing multiplexer
* If not a routing multiplexer, no bitstream is needed here
* If yes, we will generate the bitstream for the routing multiplexer
*******************************************************************/
static
void build_connection_block_interc_bitstream(BitstreamManager& bitstream_manager,
const ConfigBlockId& cb_configurable_block,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* L_rr_node,
const RRGSB& rr_gsb,
const e_side& cb_ipin_side,
const size_t& ipin_index) {
t_rr_node* src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index);
if (1 == src_rr_node->fan_in) {
/* No bitstream generation required by a special direct connection*/
} else if (1 < src_rr_node->fan_in) {
/* Create the block denoting the memory instances that drives this node in Switch Block */
vtr::Point<size_t> ipin_coord(src_rr_node->xlow, src_rr_node->ylow);
std::string mem_block_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, grids, ipin_coord, rr_gsb.get_ipin_node_grid_side(cb_ipin_side, ipin_index), src_rr_node->ptc_num, std::string(""));
ConfigBlockId mux_mem_block = bitstream_manager.add_block(mem_block_name);
bitstream_manager.add_child_block(cb_configurable_block, mux_mem_block);
/* This is a routing multiplexer! Generate bitstream */
build_connection_block_mux_bitstream(bitstream_manager, mux_mem_block,
module_manager, circuit_lib, mux_lib, rr_switches,
L_rr_node, src_rr_node);
} /*Nothing should be done else*/
}
/********************************************************************
* This function generates bitstream for a Connection Block
* and add it to the bitstream manager
* This function will spot all the routing multiplexers in a Connection Block
* using a simple but effective rule:
* The fan-in of each output node.
* If there are more than 2 fan-in, there is a routing multiplexer
*
* Note that the output nodes are the IPIN rr node in a Connection Block
* So, we will iterate over that.
*******************************************************************/
static
void build_connection_block_bitstream(BitstreamManager& bitstream_manager,
const ConfigBlockId& cb_configurable_block,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* L_rr_node,
const RRGSB& rr_gsb,
const t_rr_type& cb_type) {
/* Find routing multiplexers on the sides of a Connection block where IPIN nodes locate */
std::vector<enum e_side> cb_sides = rr_gsb.get_cb_ipin_sides(cb_type);
for (size_t side = 0; side < cb_sides.size(); ++side) {
enum e_side cb_ipin_side = cb_sides[side];
Side side_manager(cb_ipin_side);
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
build_connection_block_interc_bitstream(bitstream_manager, cb_configurable_block,
module_manager, circuit_lib, mux_lib,
grids, rr_switches, L_rr_node,
rr_gsb,
cb_ipin_side, inode);
}
}
}
/********************************************************************
* Create bitstream for a X-direction or Y-direction Connection Blocks
*******************************************************************/
static
void build_connection_block_bitstreams(BitstreamManager& bitstream_manager,
const ConfigBlockId& top_configurable_block,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* L_rr_node,
const DeviceRRGSB& L_device_rr_gsb,
const t_rr_type& cb_type) {
DeviceCoordinator cb_range = L_device_rr_gsb.get_gsb_range();
for (size_t ix = 0; ix < cb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < cb_range.get_y(); ++iy) {
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
/* Check if the connection block exists in the device!
* Some of them do NOT exist due to heterogeneous blocks (height > 1)
* We will skip those modules
*/
if ( (TRUE != is_cb_exist(cb_type, rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)))
|| (true != rr_gsb.is_cb_exist(cb_type))) {
continue;
}
/* Create a block for the bitstream which corresponds to the Switch block */
vtr::Point<size_t> cb_coord(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
ConfigBlockId cb_configurable_block = bitstream_manager.add_block(generate_connection_block_module_name(cb_type, cb_coord));
/* Set switch block as a child of top block */
bitstream_manager.add_child_block(top_configurable_block, cb_configurable_block);
build_connection_block_bitstream(bitstream_manager, cb_configurable_block, module_manager,
circuit_lib, mux_lib, grids, rr_switches, L_rr_node,
rr_gsb, cb_type);
}
}
}
/********************************************************************
* Top-level function to create bitstream for global routing architecture
* Two major tasks:
@ -178,6 +350,7 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* L_rr_node,
const DeviceRRGSB& L_device_rr_gsb) {
@ -208,30 +381,16 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
* To organize the bitstream in blocks, we create a block for each connection block
* and give names which are same as they are in top-level module managers
*/
DeviceCoordinator cb_range = L_device_rr_gsb.get_gsb_range();
vpr_printf(TIO_MESSAGE_INFO,"Generating bitstream for Connection blocks ...\n");
vpr_printf(TIO_MESSAGE_INFO,"Generating bitstream for X-directionConnection blocks ...\n");
build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager,
circuit_lib, mux_lib, grids, rr_switches, L_rr_node,
L_device_rr_gsb, CHANX);
vpr_printf(TIO_MESSAGE_INFO,"Generating bitstream for Y-directionConnection blocks ...\n");
build_connection_block_bitstreams(bitstream_manager, top_configurable_block, module_manager,
circuit_lib, mux_lib, grids, rr_switches, L_rr_node,
L_device_rr_gsb, CHANY);
for (size_t ix = 0; ix < cb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < cb_range.get_y(); ++iy) {
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
/* X - channels [1...nx][0..ny]*/
if ((TRUE == is_cb_exist(CHANX, ix, iy))
&&(true == rr_gsb.is_cb_exist(CHANX))) {
/*
fpga_spice_generate_bitstream_routing_connection_box_subckt(fp,
rr_gsb, CHANX,
cur_sram_orgz_info);
*/
}
/* Y - channels [1...ny][0..nx]*/
if ((TRUE == is_cb_exist(CHANY, ix, iy))
&&(true == rr_gsb.is_cb_exist(CHANY))) {
/*
fpga_spice_generate_bitstream_routing_connection_box_subckt(fp,
rr_gsb, CHANY,
cur_sram_orgz_info);
*/
}
}
}
}

View File

@ -17,6 +17,7 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* L_rr_node,
const DeviceRRGSB& L_device_rr_gsb);

View File

@ -9,29 +9,6 @@
#include "fpga_x2p_pbtypes_utils.h"
#include "build_module_graph_utils.h"
/*********************************************************************
* Generate the port name for a Grid
* This is a wrapper function for generate_port_name()
* which can automatically decode the port name by the pin side and height
*********************************************************************/
std::string generate_grid_side_port_name(const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& coordinate,
const e_side& side,
const size_t& pin_id) {
/* Output the pins on the side*/
size_t height = find_grid_pin_height(grids, coordinate, pin_id);
if (1 != grids[coordinate.x()][coordinate.y()].type->pinloc[height][side][pin_id]) {
Side side_manager(side);
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Fail to generate a grid pin (x=%lu, y=%lu, height=%lu, side=%s, index=%d)\n",
__FILE__, __LINE__,
coordinate.x(), coordinate.y(), height, side_manager.c_str(), pin_id);
exit(1);
}
return generate_grid_port_name(coordinate, height, side, pin_id, true);
}
/********************************************************************
* Find input port of a buffer/inverter module
********************************************************************/

View File

@ -13,11 +13,6 @@
#include "module_manager.h"
#include "circuit_library.h"
std::string generate_grid_side_port_name(const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& coordinate,
const e_side& side,
const size_t& pin_id);
ModulePortId find_inverter_buffer_module_port(const ModuleManager& module_manager,
const ModuleId& module_id,
const CircuitLibrary& circuit_lib,

View File

@ -693,8 +693,10 @@ void build_connection_block_mux_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* cur_rr_node,
const e_side& cb_ipin_side,
const size_t& ipin_index,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
t_rr_node* cur_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index);
/* Check current rr_node is an input pin of a CLB */
VTR_ASSERT(IPIN == cur_rr_node->type);
@ -770,6 +772,13 @@ void build_connection_block_mux_module(ModuleManager& module_manager,
size_t mem_instance_id = module_manager.num_instance(cb_module, mem_module);
module_manager.add_child_module(cb_module, mem_module);
/* Give an instance name: this name should be consistent with the block name given in bitstream manager,
* If you want to bind the bitstream generation to modules
*/
vtr::Point<size_t> ipin_coord(cur_rr_node->xlow, cur_rr_node->ylow);
std::string mem_instance_name = generate_cb_memory_instance_name(CONNECTION_BLOCK_MEM_INSTANCE_PREFIX, grids, ipin_coord, rr_gsb.get_ipin_node_grid_side(cb_ipin_side, ipin_index), cur_rr_node->ptc_num, std::string(""));
module_manager.set_child_instance_name(cb_module, mem_module, mem_instance_id, mem_instance_name);
/* Add nets to connect regular and mode-select SRAM ports to the SRAM port of memory module */
add_module_nets_between_logic_and_memory_sram_bus(module_manager, cb_module,
mux_module, mux_instance_id,
@ -794,8 +803,10 @@ void build_connection_block_interc_modules(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& rr_switches,
t_rr_node* src_rr_node,
const e_side& cb_ipin_side,
const size_t& ipin_index,
const std::map<ModulePortId, ModuleNetId>& input_port_to_module_nets) {
t_rr_node* src_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, ipin_index);
if (1 > src_rr_node->fan_in) {
return; /* This port has no driver, skip it */
} else if (1 == src_rr_node->fan_in) {
@ -807,7 +818,7 @@ void build_connection_block_interc_modules(ModuleManager& module_manager,
build_connection_block_mux_module(module_manager,
cb_module, rr_gsb, cb_type,
circuit_lib, grids, rr_switches,
src_rr_node,
cb_ipin_side, ipin_index,
input_port_to_module_nets);
} /*Nothing should be done else*/
}
@ -967,7 +978,7 @@ void build_connection_block_module(ModuleManager& module_manager,
build_connection_block_interc_modules(module_manager,
cb_module, rr_gsb, cb_type,
circuit_lib, grids, rr_switches,
rr_gsb.get_ipin_node(cb_ipin_side, inode),
cb_ipin_side, inode,
input_port_to_module_nets);
}
}
@ -1029,7 +1040,7 @@ void build_flatten_connection_block_modules(ModuleManager& module_manager,
* We will skip those modules
*/
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
if ( (TRUE != is_cb_exist(CHANX, rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)))
if ( (TRUE != is_cb_exist(cb_type, rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)))
|| (true != rr_gsb.is_cb_exist(cb_type))) {
continue;
}