upgrade Verilog SB generator using the RRSwitchBlock

This commit is contained in:
tangxifan 2019-05-23 17:37:39 -06:00
parent ec70bcee99
commit ea8c36ce6e
17 changed files with 1147 additions and 130 deletions

View File

@ -38,6 +38,14 @@ include(FilesToDirs)
# compiler flag configuration checks
include(CheckCXXCompilerFlag)
#
# We require c++14 support
#
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) #No compiler specific extensions
# Set WARN FLAGS
set(WARN_FLAGS "")

View File

@ -29,6 +29,7 @@ class Side {
enum e_side get_rotate_counterclockwise() const;
bool validate() const;
size_t to_size_t() const;
char* to_string() const;
public: /* Mutators */
void set_side(size_t side);
void set_side(enum e_side side);

View File

@ -87,6 +87,22 @@ size_t Side::to_size_t() const {
}
}
/* Convert to char* */
char* Side::to_string() const {
switch (side_) {
case TOP:
return "top";
case RIGHT:
return "right";
case BOTTOM:
return "bottom";
case LEFT:
return "left";
default:
return "invalid_side";
}
}
/* Public Mutators */
void Side::set_side(size_t side) {
switch (side) {

View File

@ -21,6 +21,7 @@ DeviceCoordinator::DeviceCoordinator() {
}
/* Public accessors */
size_t DeviceCoordinator::get_x() const {
return x_;
}

View File

@ -1,6 +1,8 @@
#ifndef DEVICE_COORDINATOR_H
#define DEVICE_COORDINATOR_H
#include "sides.h"
/* Coordinator System for FPGA Device
* It is based on a 3-D (x,y,z) coordinator system
* (x,y) is used for all the routing resources,
@ -8,9 +10,6 @@
*/
class DeviceCoordinator {
public: /* Contructors */
/*
DeviceCoordinator(DeviceCoordinator& coordinator);
*/
DeviceCoordinator(size_t x, size_t y);
DeviceCoordinator();
public: /* Accessors */

View File

@ -3129,7 +3129,7 @@ void spice_backannotate_vpr_post_route_info(t_det_routing_arch RoutingArch,
/* Build Array for each Switch block and Connection block */
vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each Switch block...\n");
alloc_and_build_switch_blocks_info(RoutingArch, num_rr_nodes, rr_node, rr_node_indices);
device_rr_switch_block = build_device_rr_switch_blocks(RoutingArch, num_rr_nodes, rr_node, rr_node_indices);
device_rr_switch_block = build_device_rr_switch_blocks(num_rr_nodes, rr_node, rr_node_indices);
vpr_printf(TIO_MESSAGE_INFO, "Collecting detailed information for each to Connection block...\n");
alloc_and_build_connection_blocks_info(RoutingArch, num_rr_nodes, rr_node, rr_node_indices);

View File

@ -82,7 +82,6 @@ void print_device_rr_chan_stats(DeviceRRChan& device_rr_chan);
static
RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
t_det_routing_arch RoutingArch,
int LL_num_rr_nodes,
t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
@ -846,7 +845,6 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
*/
static
RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
t_det_routing_arch RoutingArch,
int LL_num_rr_nodes,
t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
@ -857,6 +855,9 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
assert((!(0 > sb_x))&&(!(sb_x > (nx + 1))));
assert((!(0 > sb_y))&&(!(sb_y > (ny + 1))));
/* Coordinator initialization */
rr_switch_block.set_coordinator(size_t(sb_x), size_t(sb_y));
/* Basic information*/
rr_switch_block.init_num_sides(4); /* Fixed number of sides */
@ -1000,7 +1001,7 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
/* Grid[x][y+1] BOTTOM side outputs pins */
opin_grid_side[0] = BOTTOM;
/* Grid[x][y] TOP side outputs pins */
opin_grid_side[0] = TOP;
opin_grid_side[1] = TOP;
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
@ -1056,8 +1057,7 @@ RRSwitchBlock build_rr_switch_block(int sb_x, int sb_y,
* Each switch block in the FPGA fabric will be an instance of these modules.
* We maintain a map from each instance to each module
*/
DeviceRRSwitchBlock build_device_rr_switch_blocks(t_det_routing_arch RoutingArch,
int LL_num_rr_nodes,
DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes,
t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
/* Create an object */
@ -1070,7 +1070,7 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(t_det_routing_arch RoutingArch
/* For each switch block, determine the size of array */
for (int ix = 0; ix < (nx + 1); ++ix) {
for (int iy = 0; iy < (ny + 1); ++iy) {
RRSwitchBlock rr_switch_block = build_rr_switch_block(ix, iy, RoutingArch,
RRSwitchBlock rr_switch_block = build_rr_switch_block(ix, iy,
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
DeviceCoordinator sb_coordinator(ix, iy);
LL_device_rr_switch_block.add_rr_switch_block(sb_coordinator, rr_switch_block);

View File

@ -14,8 +14,7 @@ DeviceRRChan build_device_rr_chan(int LL_num_rr_nodes, t_rr_node* LL_rr_node,
* Each switch block in the FPGA fabric will be an instance of these modules.
* We maintain a map from each instance to each module
*/
DeviceRRSwitchBlock build_device_rr_switch_blocks(t_det_routing_arch RoutingArch,
int LL_num_rr_nodes,
DeviceRRSwitchBlock build_device_rr_switch_blocks(int LL_num_rr_nodes,
t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);

View File

@ -35,6 +35,11 @@ enum e_dir_err {
E_DIR_EXIST
};
/***** Local Subroutines *****/
static
enum e_dir_err try_access_dir(char* dir_path);
/***** Subroutines *****/
char* my_gettime() {
time_t current_time;
@ -98,6 +103,7 @@ void my_remove_file(char* file_path) {
return;
}
static
enum e_dir_err try_access_dir(char* dir_path) {
struct stat s;
int err = stat(dir_path, &s);
@ -141,6 +147,7 @@ int create_dir_path(char* dir_path) {
dir_path);
return 1;
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"Create directory(%s)...Failed!\n",dir_path);
exit(1);
@ -651,13 +658,23 @@ char* fpga_spice_create_one_subckt_filename(char* file_name_prefix,
int subckt_x, int subckt_y,
char* file_name_postfix) {
char* fname = NULL;
if ( -1 == subckt_y ) {
fname = (char*) my_malloc(sizeof(char) * (strlen(file_name_prefix)
+ strlen(my_itoa(subckt_x)) + 1
+ strlen(file_name_postfix) + 1));
fname = (char*) my_malloc(sizeof(char) * (strlen(file_name_prefix)
+ strlen(my_itoa(subckt_x)) + 1 + strlen(my_itoa(subckt_y))
+ strlen(file_name_postfix) + 1));
sprintf(fname, "%s%d_%s",
file_name_prefix, subckt_x, file_name_postfix);
sprintf(fname, "%s%d_%d%s",
file_name_prefix, subckt_x, subckt_y, file_name_postfix);
} else {
fname = (char*) my_malloc(sizeof(char) * (strlen(file_name_prefix)
+ strlen(my_itoa(subckt_x)) + 1 + strlen(my_itoa(subckt_y))
+ strlen(file_name_postfix) + 1));
sprintf(fname, "%s%d_%d%s",
file_name_prefix, subckt_x, subckt_y, file_name_postfix);
}
return fname;
}
@ -1226,7 +1243,6 @@ int get_rr_node_net_init_value(t_rr_node node) {
}
}
int recommend_num_sim_clock_cycle(float sim_window_size) {
float avg_density = 0.;
float median_density = 0.;

View File

@ -71,6 +71,9 @@ char* format_spice_node_prefix(char* spice_node_prefix);
t_block* search_mapped_block(int x, int y, int z);
int* my_decimal2binary(int decimal,
int* binary_len);
char** fpga_spice_strtok(char* str,
char* delims,
int* len);
@ -128,7 +131,7 @@ float get_rr_node_net_probability(t_rr_node node);
int get_rr_node_net_init_value(t_rr_node node);
int recommend_num_sim_clock_cycle();
int recommend_num_sim_clock_cycle(float sim_window_size);
void auto_select_num_sim_clock_cycle(t_spice* spice,
float signal_density_weight);
@ -406,4 +409,6 @@ void get_fpga_x2p_global_all_clock_ports(t_llist* head,
int* num_clock_ports,
t_spice_model_port*** clock_port);
int my_strlen_int(int input_int);
#endif

View File

@ -13,6 +13,8 @@
#include <util.h>
#include "quicksort.h"
void my_free(void* ptr);
/* Subroutines */

View File

@ -2,3 +2,10 @@
/* QuickSort functions */
void quicksort_float_index(int len, int* sort_index,
float* sort_value);
void quicksort_float(int len,
float* sort_value);
void do_quicksort_float_index(int len,
int* sort_index,
float* sort_value);

View File

@ -1,4 +1,5 @@
#include <cassert>
#include <string>
#include <algorithm>
#include "rr_blocks.h"
@ -85,6 +86,7 @@ bool RRChan::is_mirror(RRChan& cand) const {
return true;
}
/* Mutators */
/* modify type */
void RRChan::set_type(t_rr_type type) {
@ -306,17 +308,32 @@ bool DeviceRRChan::valid_module_id(t_rr_type chan_type, size_t module_id) const
/* Accessors */
/* get the x coordinator of this switch block */
size_t RRSwitchBlock::get_x() const {
return coordinator_.get_x();
}
/* get the y coordinator of this switch block */
size_t RRSwitchBlock::get_y() const {
return coordinator_.get_y();
}
/* Get the number of sides of this SB */
DeviceCoordinator RRSwitchBlock::get_coordinator() const {
return coordinator_;
}
/* Get the number of sides of this SB */
size_t RRSwitchBlock::get_num_sides() const {
assert (validate_num_sides());
return chan_rr_node_direction_.size();
return chan_node_direction_.size();
}
/* Get the number of routing tracks on a side */
size_t RRSwitchBlock::get_chan_width(enum e_side side) const {
Side side_manager(side);
assert(side_manager.validate());
return chan_rr_node_[side_manager.to_size_t()].size();
return chan_node_[side_manager.to_size_t()].size();
}
/* Get the direction of a rr_node at a given side and track_id */
@ -330,7 +347,7 @@ enum PORTS RRSwitchBlock::get_chan_node_direction(enum e_side side, size_t track
/* Ensure the track is valid in the context of this switch block at a specific side */
assert( validate_track_id(side, track_id) );
return chan_rr_node_direction_[side_manager.to_size_t()][track_id];
return chan_node_direction_[side_manager.to_size_t()][track_id];
}
/* get a rr_node at a given side and track_id */
@ -344,21 +361,61 @@ t_rr_node* RRSwitchBlock::get_chan_node(enum e_side side, size_t track_id) const
/* Ensure the track is valid in the context of this switch block at a specific side */
assert( validate_track_id(side, track_id) );
return chan_rr_node_[side_manager.to_size_t()][track_id];
return chan_node_[side_manager.to_size_t()][track_id];
}
/* Get the number of IPIN rr_nodes on a side */
size_t RRSwitchBlock::get_num_ipin_rr_nodes(enum e_side side) const {
size_t RRSwitchBlock::get_num_ipin_nodes(enum e_side side) const {
Side side_manager(side);
assert(side_manager.validate());
return ipin_rr_node_[side_manager.to_size_t()].size();
return ipin_node_[side_manager.to_size_t()].size();
}
/* Get the number of OPIN rr_nodes on a side */
size_t RRSwitchBlock::get_num_opin_rr_nodes(enum e_side side) const {
size_t RRSwitchBlock::get_num_opin_nodes(enum e_side side) const {
Side side_manager(side);
assert(side_manager.validate());
return opin_rr_node_[side_manager.to_size_t()].size();
return opin_node_[side_manager.to_size_t()].size();
}
/* get a opin_node at a given side and track_id */
t_rr_node* RRSwitchBlock::get_opin_node(enum e_side side, size_t node_id) const {
Side side_manager(side);
assert(side_manager.validate());
/* Ensure the side is valid in the context of this switch block */
assert( validate_side(side) );
/* Ensure the track is valid in the context of this switch block at a specific side */
assert( validate_opin_node_id(side, node_id) );
return opin_node_[side_manager.to_size_t()][node_id];
}
/* get the grid_side of a opin_node at a given side and track_id */
enum e_side RRSwitchBlock::get_opin_node_grid_side(enum e_side side, size_t node_id) const {
Side side_manager(side);
assert(side_manager.validate());
/* Ensure the side is valid in the context of this switch block */
assert( validate_side(side) );
/* Ensure the track is valid in the context of this switch block at a specific side */
assert( validate_opin_node_id(side, node_id) );
return opin_node_grid_side_[side_manager.to_size_t()][node_id];
}
/* get the grid side of a opin_rr_node */
enum e_side RRSwitchBlock::get_opin_node_grid_side(t_rr_node* opin_node) const {
enum e_side side;
int index;
/* Find the side and index */
get_node_side_and_index(opin_node, IN_PORT, &side, &index);
assert(-1 != index);
assert(validate_side(side));
return get_opin_node_grid_side(side, index);
}
/* Get the node index in the array, return -1 if not found */
@ -377,25 +434,25 @@ int RRSwitchBlock::get_node_index(t_rr_node* node,
case CHANX:
case CHANY:
for (size_t inode = 0; inode < get_chan_width(node_side); ++inode) {
if ((node == chan_rr_node_[side_manager.to_size_t()][inode])
if ((node == chan_node_[side_manager.to_size_t()][inode])
/* Check if direction meets specification */
&&(node_direction == chan_rr_node_direction_[side_manager.to_size_t()][inode])) {
&&(node_direction == chan_node_direction_[side_manager.to_size_t()][inode])) {
cnt++;
ret = inode;
}
}
break;
case IPIN:
for (size_t inode = 0; inode < get_num_ipin_rr_nodes(node_side); ++inode) {
if (node == ipin_rr_node_[side_manager.to_size_t()][inode]) {
for (size_t inode = 0; inode < get_num_ipin_nodes(node_side); ++inode) {
if (node == ipin_node_[side_manager.to_size_t()][inode]) {
cnt++;
ret = inode;
}
}
break;
case OPIN:
for (size_t inode = 0; inode < get_num_opin_rr_nodes(node_side); ++inode) {
if (node == opin_rr_node_[side_manager.to_size_t()][inode]) {
for (size_t inode = 0; inode < get_num_opin_nodes(node_side); ++inode) {
if (node == opin_node_[side_manager.to_size_t()][inode]) {
cnt++;
ret = inode;
}
@ -469,11 +526,29 @@ void RRSwitchBlock::get_node_side_and_index(t_rr_node* node,
}
size_t RRSwitchBlock::get_num_reserved_conf_bits() const {
return num_reserved_conf_bits_;
assert (validate_num_reserved_conf_bits());
return reserved_conf_bits_msb_ - reserved_conf_bits_lsb_ + 1;
}
size_t RRSwitchBlock::get_reserved_conf_bits_lsb() const {
return reserved_conf_bits_lsb_;
}
size_t RRSwitchBlock::get_reserved_conf_bits_msb() const {
return reserved_conf_bits_msb_;
}
size_t RRSwitchBlock::get_num_conf_bits() const {
return num_conf_bits_;
assert (validate_num_conf_bits());
return conf_bits_msb_ - conf_bits_lsb_ + 1;
}
size_t RRSwitchBlock::get_conf_bits_lsb() const {
return conf_bits_lsb_;
}
size_t RRSwitchBlock::get_conf_bits_msb() const {
return conf_bits_msb_;
}
/* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */
@ -493,8 +568,6 @@ bool RRSwitchBlock::is_node_imply_short_connection(t_rr_node* src_node) const {
}
return false;
}
/* check if the candidate SB is a mirror of the current one */
@ -547,7 +620,7 @@ bool RRSwitchBlock::is_mirror(RRSwitchBlock& cand) const {
for (size_t side = 0; side < get_num_sides(); ++side) {
Side side_manager(side);
if (get_num_ipin_rr_nodes(side_manager.get_side()) != cand.get_num_ipin_rr_nodes(side_manager.get_side())) {
if (get_num_ipin_nodes(side_manager.get_side()) != cand.get_num_ipin_nodes(side_manager.get_side())) {
return false;
}
}
@ -561,64 +634,144 @@ bool RRSwitchBlock::is_mirror(RRSwitchBlock& cand) const {
return true;
}
/* Public Accessors: Cooridinator conversion */
DeviceCoordinator RRSwitchBlock::get_side_block_coordinator(enum e_side side) const {
Side side_manager(side);
assert(side_manager.validate());
DeviceCoordinator ret(get_x(), get_y());
switch (side_manager.get_side()) {
case TOP:
/* (0 == side) */
/* 1. Channel Y [x][y+1] inputs */
ret.set_y(ret.get_y() + 1);
break;
case RIGHT:
/* 1 == side */
/* 2. Channel X [x+1][y] inputs */
ret.set_x(ret.get_x() + 1);
break;
case BOTTOM:
/* 2 == side */
/* 3. Channel Y [x][y] inputs */
break;
case LEFT:
/* 3 == side */
/* 4. Channel X [x][y] inputs */
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid side!\n",
__FILE__, __LINE__);
exit(1);
}
return ret;
}
/* Public Accessors Verilog writer */
char* RRSwitchBlock::gen_verilog_module_name() const {
char* ret = NULL;
std::string x_str = std::to_string(get_x());
std::string y_str = std::to_string(get_y());
ret = (char*)my_malloc(2 + 1 + x_str.length()
+ 2 + y_str.length()
+ 1 + 1);
sprintf(ret, "sb_%lu__%lu_",
get_x(), get_y());
return ret;
}
char* RRSwitchBlock::gen_verilog_instance_name() const {
char* ret = NULL;
std::string x_str = std::to_string(get_x());
std::string y_str = std::to_string(get_y());
ret = (char*)my_malloc(2 + 1 + x_str.length()
+ 2 + y_str.length()
+ 4 + 1);
sprintf(ret, "sb_%lu__%lu__0_",
get_x(), get_y());
return ret;
}
/* Public mutators */
/* Allocate the vectors with the given number of sides */
void RRSwitchBlock::init_num_sides(size_t num_sides) {
/* Initialize the vectors */
chan_rr_node_direction_.resize(num_sides);
chan_rr_node_.resize(num_sides);
ipin_rr_node_.resize(num_sides);
ipin_rr_node_grid_side_.resize(num_sides);
opin_rr_node_.resize(num_sides);
opin_rr_node_grid_side_.resize(num_sides);
/* Set the coordinator (x,y) for the switch block */
void RRSwitchBlock::set_coordinator(size_t x, size_t y) {
coordinator_.set(x, y);
return;
}
/* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
/* Allocate the vectors with the given number of sides */
void RRSwitchBlock::init_num_sides(size_t num_sides) {
/* Initialize the vectors */
chan_node_direction_.resize(num_sides);
chan_node_.resize(num_sides);
ipin_node_.resize(num_sides);
ipin_node_grid_side_.resize(num_sides);
opin_node_.resize(num_sides);
opin_node_grid_side_.resize(num_sides);
return;
}
/* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */
void RRSwitchBlock::add_chan_node(t_rr_node* node, enum e_side node_side, enum PORTS node_direction) {
Side side_manager(node_side);
assert(validate_side(node_side));
/* resize the array if needed, node is placed in the sequence of node->ptc_num */
if (size_t(node->ptc_num + 1) > chan_rr_node_[side_manager.to_size_t()].size()) {
chan_rr_node_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */
chan_rr_node_direction_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */
if (size_t(node->ptc_num + 1) > chan_node_[side_manager.to_size_t()].size()) {
chan_node_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */
chan_node_direction_[side_manager.to_size_t()].resize(node->ptc_num + 1); /* resize to the maximum */
}
/* fill the dedicated element in the vector */
chan_rr_node_[side_manager.to_size_t()][node->ptc_num] = node;
chan_rr_node_direction_[side_manager.to_size_t()][node->ptc_num] = node_direction;
chan_node_[side_manager.to_size_t()][node->ptc_num] = node;
chan_node_direction_[side_manager.to_size_t()][node->ptc_num] = node_direction;
return;
}
/* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
/* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */
void RRSwitchBlock::add_ipin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side) {
Side side_manager(node_side);
assert(validate_side(node_side));
/* push pack the dedicated element in the vector */
ipin_rr_node_[side_manager.to_size_t()].push_back(node);
ipin_rr_node_grid_side_[side_manager.to_size_t()].push_back(grid_side);
ipin_node_[side_manager.to_size_t()].push_back(node);
ipin_node_grid_side_[side_manager.to_size_t()].push_back(grid_side);
return;
}
/* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
/* Add a node to the chan_node_ list and also assign its direction in chan_node_direction_ */
void RRSwitchBlock::add_opin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side) {
Side side_manager(node_side);
assert(validate_side(node_side));
/* push pack the dedicated element in the vector */
opin_rr_node_[side_manager.to_size_t()].push_back(node);
opin_rr_node_grid_side_[side_manager.to_size_t()].push_back(grid_side);
opin_node_[side_manager.to_size_t()].push_back(node);
opin_node_grid_side_[side_manager.to_size_t()].push_back(grid_side);
return;
}
void RRSwitchBlock::set_num_reserved_conf_bits(size_t num_reserved_conf_bits) {
num_reserved_conf_bits_ = num_reserved_conf_bits;
reserved_conf_bits_lsb_ = 0;
reserved_conf_bits_msb_ = num_reserved_conf_bits - 1;
return;
}
void RRSwitchBlock::set_num_conf_bits(size_t num_conf_bits) {
num_conf_bits_ = num_conf_bits;
void RRSwitchBlock::set_conf_bits_lsb(size_t conf_bits_lsb) {
conf_bits_lsb_ = conf_bits_lsb;
return;
}
void RRSwitchBlock::set_conf_bits_msb(size_t conf_bits_msb) {
conf_bits_msb_ = conf_bits_msb;
return;
}
@ -627,22 +780,26 @@ void RRSwitchBlock::clear() {
assert(validate_num_sides());
/* Clear the inner vector of each matrix */
for (size_t side = 0; side < get_num_sides(); ++side) {
chan_rr_node_direction_[side].clear();
chan_rr_node_[side].clear();
ipin_rr_node_[side].clear();
ipin_rr_node_grid_side_[side].clear();
opin_rr_node_[side].clear();
opin_rr_node_grid_side_[side].clear();
chan_node_direction_[side].clear();
chan_node_[side].clear();
ipin_node_[side].clear();
ipin_node_grid_side_[side].clear();
opin_node_[side].clear();
opin_node_grid_side_[side].clear();
}
chan_rr_node_direction_.clear();
chan_rr_node_.clear();
ipin_rr_node_.clear();
ipin_rr_node_grid_side_.clear();
opin_rr_node_.clear();
opin_rr_node_grid_side_.clear();
chan_node_direction_.clear();
chan_node_.clear();
ipin_node_.clear();
ipin_node_grid_side_.clear();
opin_node_.clear();
opin_node_grid_side_.clear();
set_num_reserved_conf_bits(0);
set_num_conf_bits(0);
/* Just to make the lsb and msb invalidate */
reserved_conf_bits_lsb_ = 1;
reserved_conf_bits_msb_ = 0;
/* Just to make the lsb and msb invalidate */
set_conf_bits_lsb(1);
set_conf_bits_msb(0);
return;
}
@ -652,8 +809,8 @@ void RRSwitchBlock::clear_chan_nodes(enum e_side node_side) {
Side side_manager(node_side);
assert(validate_side(node_side));
chan_rr_node_[side_manager.to_size_t()].clear();
chan_rr_node_direction_[side_manager.to_size_t()].clear();
chan_node_[side_manager.to_size_t()].clear();
chan_node_direction_[side_manager.to_size_t()].clear();
return;
}
@ -662,8 +819,8 @@ void RRSwitchBlock::clear_ipin_nodes(enum e_side node_side) {
Side side_manager(node_side);
assert(validate_side(node_side));
ipin_rr_node_[side_manager.to_size_t()].clear();
ipin_rr_node_grid_side_[side_manager.to_size_t()].clear();
ipin_node_[side_manager.to_size_t()].clear();
ipin_node_grid_side_[side_manager.to_size_t()].clear();
return;
}
@ -672,8 +829,8 @@ void RRSwitchBlock::clear_opin_nodes(enum e_side node_side) {
Side side_manager(node_side);
assert(validate_side(node_side));
opin_rr_node_[side_manager.to_size_t()].clear();
opin_rr_node_grid_side_[side_manager.to_size_t()].clear();
opin_node_[side_manager.to_size_t()].clear();
opin_node_grid_side_[side_manager.to_size_t()].clear();
return;
}
@ -745,25 +902,25 @@ bool RRSwitchBlock::is_node_mirror(RRSwitchBlock& cand,
/* Validate if the number of sides are consistent among internal data arrays ! */
bool RRSwitchBlock::validate_num_sides() const {
size_t num_sides = chan_rr_node_direction_.size();
size_t num_sides = chan_node_direction_.size();
if ( num_sides != chan_rr_node_.size() ) {
if ( num_sides != chan_node_.size() ) {
return false;
}
if ( num_sides != ipin_rr_node_.size() ) {
if ( num_sides != ipin_node_.size() ) {
return false;
}
if ( num_sides != ipin_rr_node_grid_side_.size() ) {
if ( num_sides != ipin_node_grid_side_.size() ) {
return false;
}
if ( num_sides != opin_rr_node_.size() ) {
if ( num_sides != opin_node_.size() ) {
return false;
}
if ( num_sides != opin_rr_node_grid_side_.size() ) {
if ( num_sides != opin_node_grid_side_.size() ) {
return false;
}
@ -779,20 +936,52 @@ bool RRSwitchBlock::validate_side(enum e_side side) const {
return false;
}
/* Check the track_id is valid for chan_rr_node_ and chan_rr_node_direction_ */
/* Check the track_id is valid for chan_node_ and chan_node_direction_ */
bool RRSwitchBlock::validate_track_id(enum e_side side, size_t track_id) const {
Side side_manager(side);
if (false == validate_side(side)) {
return false;
}
if ( track_id < chan_rr_node_[side_manager.to_size_t()].size() ) {
if ( ( track_id < chan_node_[side_manager.to_size_t()].size())
&& ( track_id < chan_node_direction_[side_manager.to_size_t()].size()) ) {
return true;
}
return false;
}
/* Check the opin_node_id is valid for opin_node_ and opin_node_grid_side_ */
bool RRSwitchBlock::validate_opin_node_id(enum e_side side, size_t node_id) const {
Side side_manager(side);
if (false == validate_side(side)) {
return false;
}
if ( ( node_id < opin_node_[side_manager.to_size_t()].size())
&&( node_id < opin_node_grid_side_[side_manager.to_size_t()].size()) ) {
return true;
}
return false;
}
/* Validate the number of configuration bits, MSB should be no less than the LSB !!! */
bool RRSwitchBlock::validate_num_conf_bits() const {
if (conf_bits_msb_ >= conf_bits_lsb_) {
return true;
}
return false;
}
/* Validate the number of configuration bits, MSB should be no less than the LSB !!! */
bool RRSwitchBlock::validate_num_reserved_conf_bits() const {
if (reserved_conf_bits_msb_ >= reserved_conf_bits_lsb_) {
return true;
}
return false;
}
/* Member Functions of Class RRChan */
/* Accessors */

View File

@ -121,26 +121,43 @@ class DeviceRRChan {
class RRSwitchBlock {
public: /* Contructors */
public: /* Accessors */
size_t get_x() const; /* get the x coordinator of this switch block */
size_t get_y() const; /* get the y coordinator of this switch block */
DeviceCoordinator get_coordinator() const; /* Get the number of sides of this SB */
size_t get_num_sides() const; /* Get the number of sides of this SB */
size_t get_chan_width(enum e_side side) const; /* Get the number of routing tracks on a side */
enum PORTS get_chan_node_direction(enum e_side side, size_t track_id) const; /* Get the direction of a rr_node at a given side and track_id */
t_rr_node* get_chan_node(enum e_side side, size_t track_id) const; /* get a rr_node at a given side and track_id */
size_t get_num_ipin_rr_nodes(enum e_side side) const; /* Get the number of IPIN rr_nodes on a side */
size_t get_num_opin_rr_nodes(enum e_side side) const; /* Get the number of OPIN rr_nodes on a side */
size_t get_num_ipin_nodes(enum e_side side) const; /* Get the number of IPIN rr_nodes on a side */
size_t get_num_opin_nodes(enum e_side side) const; /* Get the number of OPIN rr_nodes on a side */
t_rr_node* get_opin_node(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */
enum e_side get_opin_node_grid_side(enum e_side side, size_t node_id) const; /* get a rr_node at a given side and track_id */
enum e_side get_opin_node_grid_side(t_rr_node* opin_node) const; /* get a rr_node at a given side and track_id */
int get_node_index(t_rr_node* node, enum e_side node_side, enum PORTS node_direction) const; /* Get the node index in the array, return -1 if not found */
void get_node_side_and_index(t_rr_node* node, enum PORTS node_direction, enum e_side* node_side, int* node_index) const; /* Given a rr_node, try to find its side and index in the Switch block */
bool is_node_exist_opposite_side(t_rr_node* node, enum e_side node_side) const; /* Check if the node exist in the opposite side of this Switch Block */
size_t get_num_reserved_conf_bits() const;
size_t get_reserved_conf_bits_lsb() const;
size_t get_reserved_conf_bits_msb() const;
size_t get_num_conf_bits() const;
size_t get_conf_bits_lsb() const;
size_t get_conf_bits_msb() const;
bool is_node_imply_short_connection(t_rr_node* src_node) const; /* Check if the node imply a short connection inside the SB, which happens to long wires across a FPGA fabric */
bool is_mirror(RRSwitchBlock& cand) const; /* check if the candidate SB is a mirror of the current one */
public: /* Cooridinator conversion */
DeviceCoordinator get_side_block_coordinator(enum e_side side) const;
public: /* Verilog writer */
char* gen_verilog_module_name() const;
char* gen_verilog_instance_name() const;
public: /* Mutators */
void set_coordinator(size_t x, size_t y);
void init_num_sides(size_t num_sides); /* Allocate the vectors with the given number of sides */
void add_chan_node(t_rr_node* node, enum e_side node_side, enum PORTS node_direction); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
void add_ipin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
void add_opin_node(t_rr_node* node, enum e_side node_side, enum e_side grid_side); /* Add a node to the chan_rr_node_ list and also assign its direction in chan_rr_node_direction_ */
void set_num_reserved_conf_bits(size_t num_reserved_conf_bits);
void set_num_conf_bits(size_t num_conf_bits);
void set_conf_bits_lsb(size_t conf_bits_lsb);
void set_conf_bits_msb(size_t conf_bits_msb);
void clear();
void clear_chan_nodes(enum e_side node_side); /* Clean the chan_width of a side */
void clear_ipin_nodes(enum e_side node_side); /* Clean the number of IPINs of a side */
@ -152,15 +169,21 @@ class RRSwitchBlock {
bool validate_num_sides() const;
bool validate_side(enum e_side side) const;
bool validate_track_id(enum e_side side, size_t track_id) const;
bool validate_opin_node_id(enum e_side side, size_t node_id) const;
bool validate_num_reserved_conf_bits() const;
bool validate_num_conf_bits() const;
private: /* Internal Data */
std::vector< std::vector<enum PORTS> > chan_rr_node_direction_;
std::vector< std::vector<t_rr_node*> > chan_rr_node_;
std::vector< std::vector<t_rr_node*> > ipin_rr_node_;
std::vector< std::vector<enum e_side> > ipin_rr_node_grid_side_;
std::vector< std::vector<t_rr_node*> > opin_rr_node_;
std::vector< std::vector<enum e_side> > opin_rr_node_grid_side_;
size_t num_reserved_conf_bits_;
size_t num_conf_bits_;
DeviceCoordinator coordinator_;
std::vector< std::vector<enum PORTS> > chan_node_direction_;
std::vector< std::vector<t_rr_node*> > chan_node_;
std::vector< std::vector<t_rr_node*> > ipin_node_;
std::vector< std::vector<enum e_side> > ipin_node_grid_side_;
std::vector< std::vector<t_rr_node*> > opin_node_;
std::vector< std::vector<enum e_side> > opin_node_grid_side_;
size_t reserved_conf_bits_lsb_;
size_t reserved_conf_bits_msb_;
size_t conf_bits_lsb_; /* Least Significant Bit (LSB) of configuration port*/
size_t conf_bits_msb_; /* Most Significant Bit (MSB) of configuration port*/
};
/* Object Device Routing Resource Switch Block

View File

@ -10,6 +10,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <algorithm>
/* Include vpr structs*/
#include "util.h"
@ -24,6 +25,7 @@
/* Include SPICE support headers*/
#include "linkedlist.h"
#include "rr_blocks.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_backannotate_utils.h"
@ -37,6 +39,7 @@
#include "verilog_utils.h"
#include "verilog_routing.h"
static
void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* subckt_dir,
@ -53,7 +56,7 @@ void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
/* Print preprocessing flags */
verilog_include_defines_preproc_file(fp, verilog_dir);
/* Comment lines */
fprintf(fp, "//----- Verilog Module of Channel X [%u] -----\n", rr_chan_subckt_id);
fprintf(fp, "//----- Verilog Module of Channel X [%lu] -----\n", rr_chan_subckt_id);
break;
case CHANY:
/* Create file handler */
@ -61,7 +64,7 @@ void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
/* Print preprocessing flags */
verilog_include_defines_preproc_file(fp, verilog_dir);
/* Comment lines */
fprintf(fp, "//----- Verilog Module Channel Y [%u] -----\n", rr_chan_subckt_id);
fprintf(fp, "//----- Verilog Module Channel Y [%lu] -----\n", rr_chan_subckt_id);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
@ -87,15 +90,15 @@ void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) {
switch (rr_chan.get_node(itrack)->direction) {
case INC_DIRECTION:
fprintf(fp, " input in%u, //--- track %u input \n", itrack, itrack);
fprintf(fp, " input in%lu, //--- track %lu input \n", itrack, itrack);
break;
case DEC_DIRECTION:
fprintf(fp, " output out%u, //--- track %u output \n", itrack, itrack);
fprintf(fp, " output out%lu, //--- track %lu output \n", itrack, itrack);
break;
case BI_DIRECTION:
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of rr_node %s[%u]_in/out[%u]!\n",
"(File: %s [LINE%d]) Invalid direction of rr_node %s[%lu]_in/out[%lu]!\n",
__FILE__, __LINE__,
convert_chan_type_to_string(rr_chan.get_type()),
rr_chan_subckt_id, itrack);
@ -105,15 +108,15 @@ void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) {
switch (rr_chan.get_node(itrack)->direction) {
case INC_DIRECTION:
fprintf(fp, " output out%u, //--- track %u output\n", itrack, itrack);
fprintf(fp, " output out%lu, //--- track %lu output\n", itrack, itrack);
break;
case DEC_DIRECTION:
fprintf(fp, " input in%u, //--- track %u input \n", itrack, itrack);
fprintf(fp, " input in%lu, //--- track %lu input \n", itrack, itrack);
break;
case BI_DIRECTION:
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of rr_node %s[%u]_in/out[%u]!\n",
"(File: %s [LINE%d]) Invalid direction of rr_node %s[%lu]_in/out[%lu]!\n",
__FILE__, __LINE__,
convert_chan_type_to_string(rr_chan.get_type()),
rr_chan_subckt_id, itrack);
@ -122,11 +125,11 @@ void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
}
/* Middle point output for connection box inputs */
for (size_t itrack = 0; itrack < rr_chan.get_chan_width(); ++itrack) {
fprintf(fp, " output mid_out%u", itrack);
fprintf(fp, " output mid_out%lu", itrack);
if (itrack < (rr_chan.get_chan_width() - 1)) {
fprintf(fp, ",");
}
fprintf(fp, " // Middle output %u to logic blocks \n", itrack);
fprintf(fp, " // Middle output %lu to logic blocks \n", itrack);
}
fprintf(fp, " );\n");
@ -135,15 +138,15 @@ void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
/* short connecting inputs and outputs:
* length of metal wire and parasitics are handled by semi-custom flow
*/
fprintf(fp, "assign out%u = in%u; \n", itrack, itrack);
fprintf(fp, "assign mid_out%u = in%u; \n", itrack, itrack);
fprintf(fp, "assign out%lu = in%lu; \n", itrack, itrack);
fprintf(fp, "assign mid_out%lu = in%lu; \n", itrack, itrack);
}
fprintf(fp, "endmodule\n");
/* Comment lines */
fprintf(fp,
"//----- END Verilog Module of %s [%u] -----\n\n",
"//----- END Verilog Module of %s [%lu] -----\n\n",
convert_chan_type_to_string(rr_chan.get_type()),
rr_chan_subckt_id);
@ -481,8 +484,6 @@ void dump_verilog_grid_side_pins(FILE* fp,
fprintf(fp, " grid_%d__%d__pin_%d__%d__%d_", x, y, height, side, ipin);
if (TRUE == dump_port_type) {
fprintf(fp, ",\n");
} else {
fprintf(fp, ",\n");
}
}
}
@ -660,6 +661,131 @@ void dump_verilog_switch_box_chan_port(FILE* fp,
return;
}
void dump_verilog_unique_switch_box_chan_port(FILE* fp,
RRSwitchBlock& rr_sb,
enum e_side chan_side,
t_rr_node* cur_rr_node,
enum PORTS cur_rr_node_direction) {
int index = -1;
t_rr_type chan_rr_node_type;
DeviceCoordinator chan_rr_node_coordinator;
/* Check the file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* Get the index in sb_info of cur_rr_node */
index = rr_sb.get_node_index(cur_rr_node, chan_side, cur_rr_node_direction);
/* Make sure this node is included in this sb_info */
assert((-1 != index)&&(NUM_SIDES != chan_side));
chan_rr_node_type = cur_rr_node->type;
chan_rr_node_coordinator = rr_sb.get_side_block_coordinator(chan_side);
fprintf(fp, "%s_%lu__%lu__%s_%d_ ",
convert_chan_type_to_string(chan_rr_node_type),
chan_rr_node_coordinator.get_x(), chan_rr_node_coordinator.get_y(),
convert_chan_rr_node_direction_to_string(cur_rr_node_direction),
cur_rr_node->ptc_num);
return;
}
/* Print a short interconneciton in switch box
* There are two cases should be noticed.
* 1. The actual fan-in of cur_rr_node is 0. In this case,
the cur_rr_node need to be short connected to itself which is on the opposite side of this switch
* 2. The actual fan-in of cur_rr_node is 0. In this case,
* The cur_rr_node need to connected to the drive_rr_node
*/
void dump_verilog_unique_switch_box_short_interc(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
RRSwitchBlock& rr_sb,
enum e_side chan_side,
t_rr_node* cur_rr_node,
int actual_fan_in,
t_rr_node* drive_rr_node) {
/* Check the file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* Check */
assert((0 == actual_fan_in)||(1 == actual_fan_in));
char* chan_name = convert_chan_type_to_string(cur_rr_node->type);
/* Get the index in sb_info of cur_rr_node */
int index = rr_sb.get_node_index(cur_rr_node, chan_side, OUT_PORT);
char* des_chan_port_name = "out";
fprintf(fp, "//----- Short connection %s[%lu][%lu]_%s[%d] -----\n",
chan_name, rr_sb.get_coordinator().get_x(), rr_sb.get_coordinator().get_y(), des_chan_port_name, cur_rr_node->ptc_num);
fprintf(fp, "assign ");
/* Output port */
dump_verilog_unique_switch_box_chan_port(fp, rr_sb, chan_side, cur_rr_node, OUT_PORT);
fprintf(fp, " = ");
/* Check the driver*/
if (0 == actual_fan_in) {
assert(drive_rr_node == cur_rr_node);
} else {
/* drive_rr_node = &(rr_node[cur_rr_node->prev_node]); */
assert(1 == rr_node_drive_switch_box(drive_rr_node, cur_rr_node, rr_sb.get_coordinator().get_x(), rr_sb.get_coordinator().get_y(), chan_side));
}
int grid_x = drive_rr_node->xlow;
int grid_y = drive_rr_node->ylow; /*Plus the offset in function fprint_grid_side_pin_with_given_index */
switch (drive_rr_node->type) {
/* case SOURCE: */
case OPIN:
/* Find grid_x and grid_y */
/* Print a grid pin */
dump_verilog_grid_side_pin_with_given_index(fp, IPIN, /* this is an input of a Switch Box */
drive_rr_node->ptc_num,
rr_sb.get_opin_node_grid_side(drive_rr_node),
grid_x, grid_y,
FALSE); /* Do not dump the direction of the port! */
break;
case CHANX:
case CHANY:
enum e_side side;
/* Should an input */
if (cur_rr_node == drive_rr_node) {
/* To be strict, the input should locate on the opposite side.
* Use the else part if this may change in some architecture.
*/
Side side_manager(chan_side);
side = side_manager.get_opposite();
} else {
rr_sb.get_node_side_and_index(drive_rr_node, IN_PORT, &side, &index);
assert ( -1 != index );
assert ( NUM_SIDES != side );
}
/* We need to be sure that drive_rr_node is part of the SB */
dump_verilog_unique_switch_box_chan_port(fp, rr_sb, side, drive_rr_node, IN_PORT);
break;
/* SOURCE is invalid as well */
default: /* 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);
}
/* END */
fprintf(fp, ";\n");
return;
}
/* Print a short interconneciton in switch box
* There are two cases should be noticed.
* 1. The actual fan-in of cur_rr_node is 0. In this case,
@ -1005,6 +1131,246 @@ void dump_verilog_switch_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
return;
}
/* Print the SPICE netlist of multiplexer that drive this rr_node */
void dump_verilog_unique_switch_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
RRSwitchBlock& rr_sb,
enum e_side chan_side,
t_rr_node* cur_rr_node,
int mux_size,
t_rr_node** drive_rr_nodes,
int switch_index) {
int input_cnt = 0;
t_spice_model* verilog_model = NULL;
int mux_level, path_id, cur_num_sram;
int num_mux_sram_bits = 0;
int* mux_sram_bits = NULL;
int num_mux_conf_bits = 0;
int num_mux_reserved_conf_bits = 0;
int cur_bl, cur_wl;
t_spice_model* mem_model = NULL;
char* mem_subckt_name = NULL;
/* Check the file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* Check */
/* Check current rr_node is CHANX or CHANY*/
assert((CHANX == cur_rr_node->type)||(CHANY == cur_rr_node->type));
/* Allocate drive_rr_nodes according to the fan-in*/
assert((2 == mux_size)||(2 < mux_size));
/* Get verilog model*/
verilog_model = switch_inf[switch_index].spice_model;
/* Specify the input bus */
fprintf(fp, "wire [0:%d] %s_size%d_%d_inbus;\n",
mux_size - 1,
verilog_model->prefix, mux_size, verilog_model->cnt);
char* name_mux = (char *) my_malloc(sizeof(char)*(1
+ strlen(verilog_model->prefix) + 5
+ strlen(my_itoa(mux_size)) + 1
+ strlen(my_itoa(verilog_model->cnt)) + 5));
sprintf(name_mux, "/%s_size%d_%d_/in", verilog_model->prefix, mux_size, verilog_model->cnt);
char* path_hierarchy = rr_sb.gen_verilog_instance_name();
cur_rr_node->name_mux = my_strcat(path_hierarchy, name_mux);
/* Input ports*/
/* Connect input ports to bus */
for (size_t inode = 0; inode < size_t(mux_size); ++inode) {
enum e_side side;
int index;
int grid_x = drive_rr_nodes[inode]->xlow;
int grid_y = drive_rr_nodes[inode]->ylow; /*Plus the offset in function fprint_grid_side_pin_with_given_index */
switch (drive_rr_nodes[inode]->type) {
/* case SOURCE: */
case OPIN:
/* Indicate a CLB Outpin*/
/* Find grid_x and grid_y */
/* Print a grid pin */
fprintf(fp, "assign %s_size%d_%d_inbus[%d] = ",
verilog_model->prefix, mux_size, verilog_model->cnt, input_cnt);
dump_verilog_grid_side_pin_with_given_index(fp, IPIN, drive_rr_nodes[inode]->ptc_num,
rr_sb.get_opin_node_grid_side(drive_rr_nodes[inode]),
grid_x, grid_y, FALSE);
fprintf(fp, ";\n");
input_cnt++;
break;
case CHANX:
case CHANY:
/* Should be an input ! */
rr_sb.get_node_side_and_index(drive_rr_nodes[inode], IN_PORT, &side, &index);
/* We need to be sure that drive_rr_node is part of the SB */
assert((-1 != index) && (NUM_SIDES != side));
fprintf(fp, "assign %s_size%d_%d_inbus[%d] = ",
verilog_model->prefix, mux_size, verilog_model->cnt, input_cnt);
dump_verilog_unique_switch_box_chan_port(fp, rr_sb, side, drive_rr_nodes[inode], IN_PORT);
fprintf(fp, ";\n");
input_cnt++;
break;
default: /* 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);
}
}
assert(input_cnt == mux_size);
/* Print SRAMs that configure this MUX */
/* cur_num_sram = sram_verilog_model->cnt; */
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl);
/* connect to reserved BL/WLs ? */
num_mux_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model,
cur_sram_orgz_info->type,
mux_size);
/* Get the number of configuration bits required by this MUX */
num_mux_conf_bits = count_num_conf_bits_one_spice_model(verilog_model,
cur_sram_orgz_info->type,
mux_size);
/* Dump the configuration port bus */
dump_verilog_mux_config_bus(fp, verilog_model, cur_sram_orgz_info,
mux_size, cur_num_sram, num_mux_reserved_conf_bits, num_mux_conf_bits);
/* Dump ports visible only during formal verification */
fprintf(fp, "\n");
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
/*
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
cur_num_sram,
cur_num_sram + num_mux_conf_bits - 1,
VERILOG_PORT_WIRE);
fprintf(fp, ";\n");
*/
dump_verilog_formal_verification_mux_sram_ports_wiring(fp, cur_sram_orgz_info,
verilog_model, mux_size,
cur_num_sram,
cur_num_sram + num_mux_conf_bits - 1);
fprintf(fp, "`endif\n");
/* Now it is the time print the SPICE netlist of MUX*/
fprintf(fp, "%s_size%d %s_size%d_%d_ (",
verilog_model->prefix, mux_size,
verilog_model->prefix, mux_size, verilog_model->cnt);
/* Dump global ports */
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE, FALSE)) {
fprintf(fp, ",\n");
}
fprintf(fp, "%s_size%d_%d_inbus, ",
verilog_model->prefix, mux_size, verilog_model->cnt);
/* Output port */
dump_verilog_unique_switch_box_chan_port(fp, rr_sb, chan_side, cur_rr_node, OUT_PORT);
/* Add a comma because dump_verilog_switch_box_chan_port does not add so */
fprintf(fp, ", ");
/* Different design technology requires different configuration bus! */
dump_verilog_mux_config_bus_ports(fp, verilog_model, cur_sram_orgz_info,
mux_size, cur_num_sram, num_mux_reserved_conf_bits, num_mux_conf_bits);
fprintf(fp, ");\n");
/* Configuration bits for this MUX*/
path_id = DEFAULT_PATH_ID;
for (int inode = 0; inode < mux_size; ++inode) {
if (drive_rr_nodes[inode] == &(rr_node[cur_rr_node->prev_node])) {
path_id = inode;
cur_rr_node->id_path = inode;
break;
}
}
/* Depend on both technology and structure of this MUX*/
switch (verilog_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
decode_cmos_mux_sram_bits(verilog_model, mux_size, path_id, &num_mux_sram_bits, &mux_sram_bits, &mux_level);
break;
case SPICE_MODEL_DESIGN_RRAM:
decode_rram_mux(verilog_model, mux_size, path_id, &num_mux_sram_bits, &mux_sram_bits, &mux_level);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology for verilog model (%s)!\n",
__FILE__, __LINE__, verilog_model->name);
exit(1);
}
/* Print the encoding in SPICE netlist for debugging */
switch (verilog_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
fprintf(fp, "//----- SRAM bits for MUX[%d], level=%d, select_path_id=%d. -----\n",
verilog_model->cnt, mux_level, path_id);
fprintf(fp, "//----- From LSB(LEFT) TO MSB (RIGHT) -----\n");
fprintf(fp, "//-----");
fprint_commented_sram_bits(fp, num_mux_sram_bits, mux_sram_bits);
fprintf(fp, "-----\n");
break;
case SPICE_MODEL_DESIGN_RRAM:
fprintf(fp, "//----- BL/WL bits for 4T1R MUX[%d], level=%d, select_path_id=%d. -----\n",
verilog_model->cnt, mux_level, path_id);
fprintf(fp, "//----- From LSB(LEFT) TO MSB (RIGHT) -----\n");
fprintf(fp, "//---- BL: ");
fprint_commented_sram_bits(fp, num_mux_sram_bits/2, mux_sram_bits);
fprintf(fp, "-----\n");
fprintf(fp, "//----- From LSB(LEFT) TO MSB (RIGHT) -----\n");
fprintf(fp, "//---- WL: ");
fprint_commented_sram_bits(fp, num_mux_sram_bits/2, mux_sram_bits + num_mux_sram_bits/2);
fprintf(fp, "-----\n");
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology for verilog model (%s)!\n",
__FILE__, __LINE__, verilog_model->name);
}
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
/* Dump sram modules */
switch (verilog_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
/* Call the memory module defined for this SRAM-based MUX! */
mem_subckt_name = generate_verilog_mux_subckt_name(verilog_model, mux_size, verilog_mem_posfix);
fprintf(fp, "%s %s_%d_ ( ",
mem_subckt_name, mem_subckt_name, verilog_model->cnt);
dump_verilog_mem_sram_submodule(fp, cur_sram_orgz_info, verilog_model, mux_size, mem_model,
cur_num_sram, cur_num_sram + num_mux_conf_bits - 1);
fprintf(fp, ");\n");
/* update the number of memory bits */
update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + num_mux_conf_bits);
break;
case SPICE_MODEL_DESIGN_RRAM:
/* RRAM-based MUX does not need any SRAM dumping
* But we have to get the number of configuration bits required by this MUX
* and update the number of memory bits
*/
update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + num_mux_conf_bits);
update_sram_orgz_info_num_blwl(cur_sram_orgz_info,
cur_bl + num_mux_conf_bits,
cur_wl + num_mux_conf_bits);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology for verilog model (%s)!\n",
__FILE__, __LINE__, verilog_model->name);
}
/* update sram counter */
verilog_model->cnt++;
/* Free */
my_free(mux_sram_bits);
my_free(mem_subckt_name);
return;
}
/* Count the number of configuration bits of a rr_node*/
int count_verilog_switch_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb cur_sb_info, int chan_side,
@ -1041,6 +1407,43 @@ int count_verilog_switch_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_in
}
}
/* Count the number of configuration bits of a rr_node*/
size_t count_verilog_switch_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
RRSwitchBlock& rr_sb, enum e_side chan_side,
t_rr_node* cur_rr_node) {
size_t num_conf_bits = 0;
int switch_idx = 0;
int num_drive_rr_nodes = 0;
if (NULL == cur_rr_node) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])NULL cur_rr_node!\n",
__FILE__, __LINE__);
exit(1);
return num_conf_bits;
}
/* Determine if the interc lies inside a channel wire, that is interc between segments */
if (true == rr_sb.is_node_exist_opposite_side(cur_rr_node, chan_side)) {
num_drive_rr_nodes = 0;
} else {
num_drive_rr_nodes = cur_rr_node->num_drive_rr_nodes;
}
/* fan_in >= 2 implies a MUX and requires configuration bits */
if (2 > num_drive_rr_nodes) {
return num_conf_bits;
} else {
switch_idx = cur_rr_node->drive_switches[0];
assert(-1 < switch_idx);
assert(SPICE_MODEL_MUX == switch_inf[switch_idx].spice_model->type);
num_conf_bits = count_num_conf_bits_one_spice_model(switch_inf[switch_idx].spice_model,
cur_sram_orgz_info->type,
num_drive_rr_nodes);
return num_conf_bits;
}
}
/* Count the number of reserved configuration bits of a rr_node*/
int count_verilog_switch_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb cur_sb_info, int chan_side,
@ -1078,6 +1481,42 @@ int count_verilog_switch_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sra
}
}
/* Count the number of reserved configuration bits of a rr_node*/
size_t count_verilog_switch_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
RRSwitchBlock& rr_sb, enum e_side chan_side,
t_rr_node* cur_rr_node) {
size_t num_reserved_conf_bits = 0;
int switch_idx = 0;
int num_drive_rr_nodes = 0;
if (NULL == cur_rr_node) {
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])NULL cur_rr_node!\n",
__FILE__, __LINE__);
exit(1);
return num_reserved_conf_bits;
}
/* Determine if the interc lies inside a channel wire, that is interc between segments */
if (1 == rr_sb.is_node_exist_opposite_side(cur_rr_node, chan_side)) {
num_drive_rr_nodes = 0;
} else {
num_drive_rr_nodes = cur_rr_node->num_drive_rr_nodes;
}
/* fan_in >= 2 implies a MUX and requires configuration bits */
if (2 > num_drive_rr_nodes) {
return num_reserved_conf_bits;
} else {
switch_idx = cur_rr_node->drive_switches[0];
assert(-1 < switch_idx);
assert(SPICE_MODEL_MUX == switch_inf[switch_idx].spice_model->type);
num_reserved_conf_bits =
count_num_reserved_conf_bits_one_spice_model(switch_inf[switch_idx].spice_model,
cur_sram_orgz_info->type,
num_drive_rr_nodes);
return num_reserved_conf_bits;
}
}
void dump_verilog_switch_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
@ -1134,6 +1573,54 @@ void dump_verilog_switch_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
return;
}
void dump_verilog_unique_switch_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
RRSwitchBlock& rr_sb,
enum e_side chan_side,
t_rr_node* cur_rr_node) {
int num_drive_rr_nodes = 0;
t_rr_node** drive_rr_nodes = NULL;
/* Check the file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* Determine if the interc lies inside a channel wire, that is interc between segments */
/* Check each num_drive_rr_nodes, see if they appear in the cur_sb_info */
if (true == rr_sb.is_node_imply_short_connection(cur_rr_node)) {
/* Double check if the interc lies inside a channel wire, that is interc between segments */
assert(true == rr_sb.is_node_exist_opposite_side(cur_rr_node, chan_side));
num_drive_rr_nodes = 0;
drive_rr_nodes = NULL;
} else {
num_drive_rr_nodes = cur_rr_node->num_drive_rr_nodes;
drive_rr_nodes = cur_rr_node->drive_rr_nodes;
}
if (0 == num_drive_rr_nodes) {
/* Print a special direct connection*/
dump_verilog_unique_switch_box_short_interc(cur_sram_orgz_info, fp, rr_sb, chan_side, cur_rr_node,
num_drive_rr_nodes, cur_rr_node);
} else if (1 == num_drive_rr_nodes) {
/* Print a direct connection*/
dump_verilog_unique_switch_box_short_interc(cur_sram_orgz_info, fp, rr_sb, chan_side, cur_rr_node,
num_drive_rr_nodes, drive_rr_nodes[DEFAULT_SWITCH_ID]);
} else if (1 < num_drive_rr_nodes) {
/* Print the multiplexer, fan_in >= 2 */
dump_verilog_unique_switch_box_mux(cur_sram_orgz_info, fp, rr_sb, chan_side, cur_rr_node,
num_drive_rr_nodes, drive_rr_nodes,
cur_rr_node->drive_switches[DEFAULT_SWITCH_ID]);
} /*Nothing should be done else*/
/* Free */
return;
}
/* Count the number of configuration bits of a Switch Box */
int count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb* cur_sb_info) {
@ -1166,6 +1653,38 @@ int count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_
return num_reserved_conf_bits;
}
/* Count the number of configuration bits of a Switch Box */
size_t count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
RRSwitchBlock& rr_sb) {
size_t num_reserved_conf_bits = 0;
size_t temp_num_reserved_conf_bits = 0;
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
Side side_manager(side);
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) {
switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
case OUT_PORT:
temp_num_reserved_conf_bits =
count_verilog_switch_box_interc_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(),
rr_sb.get_chan_node(side_manager.get_side(), itrack));
/* Always select the largest number of reserved conf_bits */
num_reserved_conf_bits = std::max(num_reserved_conf_bits, temp_num_reserved_conf_bits);
break;
case IN_PORT:
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of port Channel node[%d] track[%d]!\n",
__FILE__, __LINE__, side, itrack);
exit(1);
}
}
}
return num_reserved_conf_bits;
}
/* Count the number of configuration bits of a Switch Box */
int count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb* cur_sb_info) {
@ -1192,6 +1711,216 @@ int count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
return num_conf_bits;
}
/* Count the number of configuration bits of a Switch Box */
size_t count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
RRSwitchBlock& rr_sb) {
size_t num_conf_bits = 0;
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
Side side_manager(side);
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) {
switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
case OUT_PORT:
num_conf_bits += count_verilog_switch_box_interc_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(),
rr_sb.get_chan_node(side_manager.get_side(), itrack));
break;
case IN_PORT:
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of port Channel node[%d] track[%d]!\n",
__FILE__, __LINE__, side, itrack);
exit(1);
}
}
}
return num_conf_bits;
}
/* Task: Print the subckt of a Switch Box.
* A Switch Box subckt consists of following ports:
* 1. Channel Y [x][y] inputs
* 2. Channel X [x+1][y] inputs
* 3. Channel Y [x][y-1] outputs
* 4. Channel X [x][y] outputs
* 5. Grid[x][y+1] Right side outputs pins
* 6. Grid[x+1][y+1] Left side output pins
* 7. Grid[x+1][y+1] Bottom side output pins
* 8. Grid[x+1][y] Top side output pins
* 9. Grid[x+1][y] Left side output pins
* 10. Grid[x][y] Right side output pins
* 11. Grid[x][y] Top side output pins
* 12. Grid[x][y+1] Bottom side output pins
*
* -------------- --------------
* | | | |
* | Grid | ChanY | Grid |
* | [x][y+1] | [x][y+1] | [x+1][y+1] |
* | | | |
* -------------- --------------
* ----------
* ChanX | Switch | ChanX
* [x][y] | Box | [x+1][y]
* | [x][y] |
* ----------
* -------------- --------------
* | | | |
* | Grid | ChanY | Grid |
* | [x][y] | [x][y] | [x+1][y] |
* | | | |
* -------------- --------------
*/
void dump_verilog_routing_switch_box_unique_subckt(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir, char* subckt_dir,
RRSwitchBlock& rr_sb,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_syn_verilog_opts fpga_verilog_opts) {
FILE* fp = NULL;
char* fname = NULL;
/* Count the number of configuration bits to be consumed by this Switch block */
int num_conf_bits = count_verilog_switch_box_conf_bits(cur_sram_orgz_info, rr_sb);
/* Count the number of reserved configuration bits to be consumed by this Switch block */
int num_reserved_conf_bits = count_verilog_switch_box_reserved_conf_bits(cur_sram_orgz_info, rr_sb);
/* Estimate the sram_verilog_model->cnt */
int cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
int esti_sram_cnt = cur_num_sram + num_conf_bits;
/* Record the index */
rr_sb.set_num_reserved_conf_bits(num_reserved_conf_bits);
rr_sb.set_conf_bits_lsb(cur_num_sram);
rr_sb.set_conf_bits_msb(cur_num_sram + num_conf_bits);
/* Create file handler */
fp = verilog_create_one_subckt_file(subckt_dir, "Unique Switch Block ",
sb_verilog_file_name_prefix, rr_sb.get_x(), rr_sb.get_y(), &fname);
/* Print preprocessing flags */
verilog_include_defines_preproc_file(fp, verilog_dir);
/* Comment lines */
fprintf(fp, "//----- Verilog Module of Unique Switch Box[%lu][%lu] -----\n", rr_sb.get_x(), rr_sb.get_y());
/* Print the definition of subckt*/
fprintf(fp, "module %s ( \n", rr_sb.gen_verilog_module_name());
/* dump global ports */
if (0 < dump_verilog_global_ports(fp, global_ports_head, TRUE)) {
fprintf(fp, ",\n");
}
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
Side side_manager(side);
/* Print ports */
fprintf(fp, "//----- Inputs/outputs of %s side -----\n", side_manager.to_string());
DeviceCoordinator port_coordinator = rr_sb.get_side_block_coordinator(side_manager.get_side());
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) {
switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
case OUT_PORT:
fprintf(fp, " output %s,\n",
gen_verilog_routing_channel_one_pin_name(rr_sb.get_chan_node(side_manager.get_side(), itrack),
port_coordinator.get_x(), port_coordinator.get_y(), itrack,
rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)));
break;
case IN_PORT:
fprintf(fp, " input %s,\n",
gen_verilog_routing_channel_one_pin_name(rr_sb.get_chan_node(side_manager.get_side(), itrack),
port_coordinator.get_x(), port_coordinator.get_y(), itrack,
rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)));
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of chan[%d][%d]_track[%d]!\n",
__FILE__, __LINE__, rr_sb.get_x(), rr_sb.get_y(), itrack);
exit(1);
}
}
/* Dump OPINs of adjacent CLBs */
for (size_t inode = 0; inode < rr_sb.get_num_opin_nodes(side_manager.get_side()); ++inode) {
fprintf(fp, " ");
dump_verilog_grid_side_pin_with_given_index(fp, OPIN, /* This is an input of a SB */
rr_sb.get_opin_node(side_manager.get_side(), inode)->ptc_num,
rr_sb.get_opin_node_grid_side(side_manager.get_side(), inode),
rr_sb.get_opin_node(side_manager.get_side(), inode)->xlow,
rr_sb.get_opin_node(side_manager.get_side(), inode)->ylow,
TRUE); /* Dump the direction of the port ! */
}
}
/* Put down configuration port */
/* output of each configuration bit */
/* Reserved sram ports */
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
rr_sb.get_reserved_conf_bits_lsb(),
rr_sb.get_reserved_conf_bits_msb(),
VERILOG_PORT_INPUT);
if (0 < rr_sb.get_num_reserved_conf_bits()) {
fprintf(fp, ",\n");
}
/* Normal sram ports */
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
rr_sb.get_conf_bits_lsb(),
rr_sb.get_conf_bits_msb(),
VERILOG_PORT_INPUT);
/* Dump ports only visible during formal verification*/
if (0 < rr_sb.get_num_conf_bits()) {
fprintf(fp, "\n");
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
fprintf(fp, ",\n");
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
rr_sb.get_conf_bits_lsb(),
rr_sb.get_conf_bits_msb(),
VERILOG_PORT_OUTPUT);
fprintf(fp, "\n");
fprintf(fp, "`endif\n");
}
fprintf(fp, "); \n");
/* Local wires for memory configurations */
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info,
rr_sb.get_conf_bits_lsb(),
rr_sb.get_conf_bits_msb() - 1);
/* Put down all the multiplexers */
for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) {
Side side_manager(side);
fprintf(fp, "//----- %s side Multiplexers -----\n",
side_manager.to_string());
for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) {
assert((CHANX == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type)
||(CHANY == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type));
/* We care INC_DIRECTION tracks at this side*/
if (OUT_PORT == rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) {
dump_verilog_unique_switch_box_interc(cur_sram_orgz_info, fp, rr_sb,
side_manager.get_side(),
rr_sb.get_chan_node(side_manager.get_side(), itrack));
}
}
}
fprintf(fp, "endmodule\n");
/* Comment lines */
fprintf(fp, "//----- END Verilog Module of Switch Box[%lu][%lu] -----\n\n", rr_sb.get_x(), rr_sb.get_y());
/* Check */
assert(esti_sram_cnt == get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info));
/* Close file handler */
fclose(fp);
/* 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);
/* Free chan_rr_nodes */
my_free(fname);
return;
}
/* Task: Print the subckt of a Switch Box.
* A Switch Box subckt consists of following ports:
* 1. Channel Y [x][y] inputs
@ -2172,14 +2901,24 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
}
/* Switch Boxes*/
for (ix = 0; ix < (nx + 1); ix++) {
for (iy = 0; iy < (ny + 1); iy++) {
/* vpr_printf(TIO_MESSAGE_INFO, "Writing Switch Boxes[%d][%d]...\n", ix, iy); */
update_spice_models_routing_index_low(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
dump_verilog_routing_switch_box_subckt(cur_sram_orgz_info, verilog_dir, subckt_dir, &(sb_info[ix][iy]),
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
fpga_verilog_opts, compact_routing_hierarchy);
update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
if (TRUE == compact_routing_hierarchy) {
for (size_t isb = 0; isb < device_rr_switch_block.get_num_unique_mirror(); ++isb) {
/* Output unique mirrors */
RRSwitchBlock unique_mirror = device_rr_switch_block.get_unique_mirror(isb);
dump_verilog_routing_switch_box_unique_subckt(cur_sram_orgz_info, verilog_dir, subckt_dir, unique_mirror,
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
fpga_verilog_opts);
}
} else {
for (ix = 0; ix < (nx + 1); ix++) {
for (iy = 0; iy < (ny + 1); iy++) {
/* vpr_printf(TIO_MESSAGE_INFO, "Writing Switch Boxes[%d][%d]...\n", ix, iy); */
update_spice_models_routing_index_low(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
dump_verilog_routing_switch_box_subckt(cur_sram_orgz_info, verilog_dir, subckt_dir, &(sb_info[ix][iy]),
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
fpga_verilog_opts, compact_routing_hierarchy);
update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
}
}
}

View File

@ -368,11 +368,22 @@ FILE* verilog_create_one_subckt_file(char* subckt_dir,
}
/* Generate the descriptions*/
file_description = (char*) my_malloc(sizeof(char) * (strlen(subckt_name_prefix) + 2
+ strlen(my_itoa(grid_x)) + 2 + strlen(my_itoa(grid_y))
+ 10));
sprintf(file_description, "%s [%d][%d] in FPGA",
subckt_name_prefix, grid_x, grid_y);
if (-1 == grid_y) {
file_description = (char*) my_malloc(sizeof(char) * (strlen(subckt_name_prefix) + 2
+ strlen(my_itoa(grid_x)) + 2
+ 10));
sprintf(file_description,
"%s [%d] in FPGA",
subckt_name_prefix, grid_x);
} else {
file_description = (char*) my_malloc(sizeof(char) * (strlen(subckt_name_prefix) + 2
+ strlen(my_itoa(grid_x)) + 2 + strlen(my_itoa(grid_y))
+ 10));
sprintf(file_description,
"%s [%d][%d] in FPGA",
subckt_name_prefix, grid_x, grid_y);
}
dump_verilog_file_header(fp, file_description);
/* Free */

View File

@ -247,8 +247,9 @@ char* gen_verilog_one_cb_instance_name(t_cb* cur_cb_info);
char* gen_verilog_one_sb_module_name(t_sb* cur_sb_info);
char* gen_verilog_one_sb_instance_name(t_sb* cur_sb_info);
char* gen_verilog_one_sb_module_name(size_t rr_sb_id);
char* gen_verilog_one_sb_instance_name(t_sb* cur_sb_info);
char* gen_verilog_one_routing_channel_module_name(t_rr_type chan_type,
int x, int y);