Update FPGA-SPICE and flow configurations
This commit is contained in:
parent
4d7f4350de
commit
90669d19c5
|
@ -24,10 +24,10 @@ vpr_arch = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/
|
|||
mpack1_abc_stdlib = DRLC7T_SiNWFET.genlib # Use relative path under ABC folder is OK
|
||||
m2net_conf = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/m2net_conf/m2x2_SiNWFET.conf
|
||||
mpack2_arch = K6_pattern7_I24.arch
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/vtr7_release/vtr_flow/tech/PTM_45nm/45nm.xml # Use relative path under VPR folder is OK
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/OpenFPGA/fpga_flow/tech/tsmc40nm.xml # Use relative path under VPR folder is OK
|
||||
|
||||
[csv_tags]
|
||||
mpack1_tags = Global mapping efficiency:|efficiency:|occupancy wo buf:|efficiency wo buf:
|
||||
mpack2_tags = BLE Number:|BLE Fill Rate:
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took|Average net density:|Median net density:|Recommend no. of clock cycles:
|
||||
vpr_power_tags = PB Types|Routing
|
||||
|
|
|
@ -24,10 +24,10 @@ vpr_arch = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/
|
|||
mpack1_abc_stdlib = DRLC7T_SiNWFET.genlib # Use relative path under ABC folder is OK
|
||||
m2net_conf = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/m2net_conf/m2x2_SiNWFET.conf
|
||||
mpack2_arch = K6_pattern7_I24.arch
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/vtr7_release/vtr_flow/tech/PTM_45nm/45nm.xml # Use relative path under VPR folder is OK
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/OpenFPGA/fpga_flow/tech/tsmc40nm.xml # Use relative path under VPR folder is OK
|
||||
|
||||
[csv_tags]
|
||||
mpack1_tags = Global mapping efficiency:|efficiency:|occupancy wo buf:|efficiency wo buf:
|
||||
mpack2_tags = BLE Number:|BLE Fill Rate:
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took|Average net density:|Median net density:|Recommend no. of clock cycles:
|
||||
vpr_power_tags = PB Types|Routing
|
||||
|
|
|
@ -24,10 +24,10 @@ vpr_arch = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/
|
|||
mpack1_abc_stdlib = DRLC7T_SiNWFET.genlib # Use relative path under ABC folder is OK
|
||||
m2net_conf = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/m2net_conf/m2x2_SiNWFET.conf
|
||||
mpack2_arch = K6_pattern7_I24.arch
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/vtr7_release/vtr_flow/tech/PTM_45nm/45nm.xml # Use relative path under VPR folder is OK
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/OpenFPGA/fpga_flow/tech/tsmc40nm.xml # Use relative path under VPR folder is OK
|
||||
|
||||
[csv_tags]
|
||||
mpack1_tags = Global mapping efficiency:|efficiency:|occupancy wo buf:|efficiency wo buf:
|
||||
mpack2_tags = BLE Number:|BLE Fill Rate:
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took|Average net density:|Median net density:|Recommend no. of clock cycles:
|
||||
vpr_power_tags = PB Types|Routing
|
||||
|
|
|
@ -24,10 +24,10 @@ vpr_arch = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/
|
|||
mpack1_abc_stdlib = DRLC7T_SiNWFET.genlib # Use relative path under ABC folder is OK
|
||||
m2net_conf = /research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/fpga_flow/m2net_conf/m2x2_SiNWFET.conf
|
||||
mpack2_arch = K6_pattern7_I24.arch
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/vtr7_release/vtr_flow/tech/PTM_45nm/45nm.xml # Use relative path under VPR folder is OK
|
||||
power_tech_xml = /research/ece/lnis/USERS/tang/research/OpenFPGA/fpga_flow/tech/tsmc40nm.xml # Use relative path under VPR folder is OK
|
||||
|
||||
[csv_tags]
|
||||
mpack1_tags = Global mapping efficiency:|efficiency:|occupancy wo buf:|efficiency wo buf:
|
||||
mpack2_tags = BLE Number:|BLE Fill Rate:
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took
|
||||
vpr_tags = Netlist clb blocks:|Final critical path:|Total logic delay:|total net delay:|Total routing area:|Total used logic block area:|Total wirelength:|Packing took|Placement took|Routing took|Average net density:|Median net density:|Recommend no. of clock cycles:
|
||||
vpr_power_tags = PB Types|Routing
|
||||
|
|
|
@ -875,6 +875,9 @@ typedef struct s_direct_inf {
|
|||
int y_offset;
|
||||
int z_offset;
|
||||
int line;
|
||||
/* Xifan Tang: FPGA-SPICE support */
|
||||
char* spice_model_name;
|
||||
t_spice_model* spice_model;
|
||||
} t_direct_inf;
|
||||
|
||||
|
||||
|
|
|
@ -3445,6 +3445,13 @@ static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs,
|
|||
Node->line);
|
||||
exit(1);
|
||||
}
|
||||
/* Spice Model Support: Xifan TANG
|
||||
* We should have a spice_model_name for this direct connection
|
||||
*/
|
||||
(*Directs)[i].spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", FALSE));
|
||||
(*Directs)[i].spice_model = NULL;
|
||||
ezxml_set_attr(Node,"spice_model_name",NULL);
|
||||
|
||||
|
||||
(*Directs)[i].line = Node->line;
|
||||
/* Should I check that the direct chain offset is not greater than the chip? How? */
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "mrfpga_globals.h"
|
||||
/* END */
|
||||
|
||||
/* Xifan Tang: include for supporting Direct Parsing */
|
||||
#include "vpr_utils.h"
|
||||
|
||||
static void SetupOperation(INP t_options Options,
|
||||
OUTP enum e_operation *Operation);
|
||||
static void SetupPackerOpts(INP t_options Options, INP boolean TimingEnabled,
|
||||
|
@ -50,6 +53,9 @@ static void SetupFpgaSpiceOpts(t_options Options,
|
|||
t_fpga_spice_opts* fpga_spice_opts,
|
||||
t_arch* arch);
|
||||
/* end */
|
||||
/* Xifan Tang: Parse CLB to CLB direct connections */
|
||||
static void alloc_and_init_globals_clb_to_clb_directs(int num_directs,
|
||||
t_direct_inf* directs);
|
||||
|
||||
/* mrFPGA */
|
||||
static void SetupSwitches_mrFPGA(INP t_arch Arch,
|
||||
|
@ -281,6 +287,9 @@ void SetupVPR(INP t_options *Options, INP boolean TimingEnabled,
|
|||
vpr_printf(TIO_MESSAGE_INFO, "Building complex block graph.\n");
|
||||
alloc_and_load_all_pb_graphs(PowerOpts->do_power);
|
||||
|
||||
/* Xifan Tang: Initialize the clb to clb directs */
|
||||
alloc_and_init_globals_clb_to_clb_directs(Arch->num_directs, Arch->Directs);
|
||||
|
||||
if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_PB_GRAPH)) {
|
||||
echo_pb_graph(getEchoFileName(E_ECHO_PB_GRAPH));
|
||||
}
|
||||
|
@ -1114,6 +1123,16 @@ static void SetupFpgaSpiceOpts(t_options Options,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Initialize the global variables for clb to clb directs */
|
||||
static
|
||||
void alloc_and_init_globals_clb_to_clb_directs(int num_directs,
|
||||
t_direct_inf* directs) {
|
||||
num_clb2clb_directs = num_directs;
|
||||
clb2clb_direct = alloc_and_load_clb_to_clb_directs(directs, num_directs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* mrFPGA : Reshaped by Xifan TANG */
|
||||
static void set_max_pins_per_side() {
|
||||
int i, j, p, q;
|
||||
|
|
|
@ -104,3 +104,7 @@ t_cb** cby_info = NULL;
|
|||
|
||||
/* Xifan TANG: detailed runtime statistics */
|
||||
float pack_route_time = 0.;
|
||||
|
||||
/* Xifan TANG: clb_to_clb_directs*/
|
||||
int num_clb2clb_directs = 0;
|
||||
t_clb_to_clb_directs* clb2clb_direct = NULL;
|
||||
|
|
|
@ -136,5 +136,9 @@ extern t_cb** cby_info;
|
|||
/* Xifan TANG: detailed runtime statistics */
|
||||
extern float pack_route_time;
|
||||
|
||||
/* Xifan TANG: clb_to_clb_directs*/
|
||||
extern int num_clb2clb_directs;
|
||||
extern t_clb_to_clb_directs* clb2clb_direct;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1086,6 +1086,25 @@ enum e_cost_indices {
|
|||
CHANX_COST_INDEX_START
|
||||
};
|
||||
|
||||
/* Xifan Tang: Move this struct from rr_graph.c to here
|
||||
* This is a general representation on clb_to_clb_directs
|
||||
*/
|
||||
typedef struct s_clb_to_clb_directs {
|
||||
t_type_descriptor *from_clb_type;
|
||||
int from_clb_pin_start_index;
|
||||
int from_clb_pin_end_index;
|
||||
t_type_descriptor *to_clb_type;
|
||||
int to_clb_pin_start_index;
|
||||
int to_clb_pin_end_index;
|
||||
/* Xifan Tang: add useful addition info to this struct */
|
||||
int x_offset;
|
||||
int y_offset;
|
||||
int z_offset;
|
||||
t_spice_model* spice_model;
|
||||
char* name;
|
||||
} t_clb_to_clb_directs;
|
||||
|
||||
|
||||
/* Gives the index of the SOURCE, SINK, OPIN, IPIN, etc. member of *
|
||||
* rr_indexed_data. */
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "fpga_spice_utils.h"
|
||||
#include "spice_lut.h"
|
||||
|
||||
#include "fpga_spice_backannotate_utils.h"
|
||||
|
||||
/* Alloc, initialize and free functions for sb_info & cb_info */
|
||||
/* Initialize a SB_info */
|
||||
void init_one_sb_info(t_sb* cur_sb) {
|
||||
|
@ -282,6 +284,8 @@ int is_rr_node_exist_opposite_side_in_sb_info(t_sb cur_sb_info,
|
|||
int oppo_chan_side = -1;
|
||||
int interc, index;
|
||||
|
||||
assert((CHANX == src_rr_node->type) || (CHANY == src_rr_node->type));
|
||||
|
||||
oppo_chan_side = get_opposite_side(chan_side);
|
||||
|
||||
/* See if we can find the same src_rr_node in the opposite chan_side
|
||||
|
@ -297,6 +301,26 @@ int is_rr_node_exist_opposite_side_in_sb_info(t_sb cur_sb_info,
|
|||
return interc;
|
||||
}
|
||||
|
||||
/* Check if the drivers for cur_rr_node imply a short connection in this Switch block
|
||||
*/
|
||||
boolean check_drive_rr_node_imply_short(t_sb cur_sb_info,
|
||||
t_rr_node* src_rr_node,
|
||||
int chan_side) {
|
||||
int inode, index, side;
|
||||
|
||||
assert((CHANX == src_rr_node->type) || (CHANY == src_rr_node->type));
|
||||
|
||||
for (inode = 0; inode < src_rr_node->num_drive_rr_nodes; inode++) {
|
||||
get_rr_node_side_and_index_in_sb_info(src_rr_node->drive_rr_nodes[inode], cur_sb_info, IN_PORT, &side, &index);
|
||||
/* We need to be sure that drive_rr_node is part of the SB */
|
||||
if (((-1 == index)||(-1 == side))
|
||||
&& ((CHANX == src_rr_node->drive_rr_nodes[inode]->type)||(CHANY == src_rr_node->drive_rr_nodes[inode]->type))) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get the side and index of a given rr_node in a SB_info
|
||||
* Return cur_rr_node_side & cur_rr_node_index
|
||||
|
@ -1786,11 +1810,11 @@ void build_one_switch_block_info(t_sb* cur_sb, int sb_x, int sb_y,
|
|||
cur_sb->chan_rr_node_direction[side][itrack] = IN_PORT;
|
||||
}
|
||||
}
|
||||
/* TODO: Include Grid[x][y+1] RIGHT side outputs pins */
|
||||
/* Include Grid[x][y+1] RIGHT side outputs pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x, sb_y + 1, 1,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* TODO: Include Grid[x+1][y+1] Left side output pins */
|
||||
/* Include Grid[x+1][y+1] Left side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x + 1, sb_y + 1, 3,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
|
@ -1834,7 +1858,7 @@ void build_one_switch_block_info(t_sb* cur_sb, int sb_x, int sb_y,
|
|||
/* Side: TOP => 0, RIGHT => 1, BOTTOM => 2, LEFT => 3 */
|
||||
/* Alloc */
|
||||
cur_sb->chan_rr_node[side] = get_chan_rr_nodes(&(cur_sb->chan_width[side]), CHANX, ix, iy,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
cur_sb->chan_rr_node_direction[side] = (enum PORTS*)my_malloc(sizeof(enum PORTS)*cur_sb->chan_width[side]);
|
||||
/* Collect rr_nodes for Tracks for right: chanX[x+1][y] */
|
||||
for (itrack = 0; itrack < cur_sb->chan_width[side]; itrack++) {
|
||||
|
@ -1846,11 +1870,11 @@ void build_one_switch_block_info(t_sb* cur_sb, int sb_x, int sb_y,
|
|||
cur_sb->chan_rr_node_direction[side][itrack] = IN_PORT;
|
||||
}
|
||||
}
|
||||
/* TODO: include Grid[x+1][y+1] Bottom side output pins */
|
||||
/* include Grid[x+1][y+1] Bottom side output pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x + 1, sb_y + 1, 2,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* TODO: include Grid[x+1][y] Top side output pins */
|
||||
/* include Grid[x+1][y] Top side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x + 1, sb_y, 0,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
|
@ -1966,11 +1990,11 @@ void build_one_switch_block_info(t_sb* cur_sb, int sb_x, int sb_y,
|
|||
cur_sb->chan_rr_node_direction[side][itrack] = IN_PORT;
|
||||
}
|
||||
}
|
||||
/* TODO: include Grid[x][y+1] Bottom side outputs pins */
|
||||
/* include Grid[x][y+1] Bottom side outputs pins */
|
||||
temp_opin_rr_node[0] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[0],
|
||||
OPIN, sb_x, sb_y + 1, 2,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
/* TODO: include Grid[x][y] Top side output pins */
|
||||
/* include Grid[x][y] Top side output pins */
|
||||
temp_opin_rr_node[1] = get_grid_side_pin_rr_nodes(&temp_num_opin_rr_nodes[1],
|
||||
OPIN, sb_x, sb_y, 0,
|
||||
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
|
||||
|
|
|
@ -25,6 +25,10 @@ int is_rr_node_exist_opposite_side_in_sb_info(t_sb cur_sb_info,
|
|||
t_rr_node* src_rr_node,
|
||||
int chan_side);
|
||||
|
||||
boolean check_drive_rr_node_imply_short(t_sb cur_sb_info,
|
||||
t_rr_node* src_rr_node,
|
||||
int chan_side);
|
||||
|
||||
void get_rr_node_side_and_index_in_sb_info(t_rr_node* cur_rr_node,
|
||||
t_sb cur_sb_info,
|
||||
enum PORTS rr_node_direction,
|
||||
|
|
|
@ -505,6 +505,38 @@ void init_check_arch_spice_models(t_arch* arch,
|
|||
}
|
||||
}
|
||||
|
||||
/* Step E: Direct connections between CLBs */
|
||||
for (i = 0; i < arch->num_directs; i++) {
|
||||
if (NULL == arch->Directs[i].spice_model_name) {
|
||||
arch->Directs[i].spice_model =
|
||||
get_default_spice_model(SPICE_MODEL_WIRE,
|
||||
arch->spice->num_spice_model,
|
||||
arch->spice->spice_models);
|
||||
continue;
|
||||
} else {
|
||||
arch->Directs[i].spice_model =
|
||||
find_name_matched_spice_model(arch->Directs[i].spice_model_name,
|
||||
arch->spice->num_spice_model,
|
||||
arch->spice->spice_models);
|
||||
}
|
||||
/* Check SPICE model type */
|
||||
if (NULL == arch->Directs[i].spice_model) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(FILE:%s, LINE[%d])Invalid SPICE model name(%s) of CLB to CLB Direct Connection (name=%s) is undefined in SPICE models!\n",
|
||||
__FILE__ ,__LINE__,
|
||||
arch->Directs[i].spice_model_name,
|
||||
arch->Directs[i].name);
|
||||
exit(1);
|
||||
} else if (SPICE_MODEL_CHAN_WIRE != arch->Directs[i].spice_model->type) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(FILE:%s, LINE[%d])Invalid SPICE model(%s) type of CLB to CLB Direct Connection (name=%s)! Should be chan_wire!\n",
|
||||
__FILE__ , __LINE__,
|
||||
arch->Directs[i].spice_model_name,
|
||||
arch->Directs[i].name);
|
||||
exit(1);
|
||||
}
|
||||
/* Copy it to clb2clb_directs */
|
||||
clb2clb_direct[i].spice_model = arch->Directs[i].spice_model;
|
||||
}
|
||||
|
||||
/* 2. Search Complex Blocks (Pb_Types), Link spice_model according to the spice_model_name*/
|
||||
for (i = 0; i < num_types; i++) {
|
||||
if (type_descriptors[i].pb_type) {
|
||||
|
|
|
@ -1422,6 +1422,19 @@ t_spice_model* find_iopad_spice_model(int num_spice_model,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Check if the grid coorindate given is in the range */
|
||||
boolean is_grid_coordinate_in_range(int x_min,
|
||||
int x_max,
|
||||
int grid_x) {
|
||||
/* See if x is in the range */
|
||||
if ((x_min > grid_x)
|
||||
||(x_max < grid_x)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Reach here, means all in the range */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char* generate_string_spice_model_type(enum e_spice_model_type spice_model_type) {
|
||||
char* ret = NULL;
|
||||
|
@ -2713,9 +2726,7 @@ int rr_node_drive_switch_box(t_rr_node* src_rr_node,
|
|||
int chan_side) {
|
||||
|
||||
/* Make sure a valid src_rr_node and des_rr_node */
|
||||
if (NULL == src_rr_node) {
|
||||
assert(NULL != src_rr_node);
|
||||
}
|
||||
assert(NULL != des_rr_node);
|
||||
/* The src_rr_node should be either CHANX or CHANY */
|
||||
assert((CHANX == des_rr_node->type)||(CHANY == des_rr_node->type));
|
||||
|
@ -7011,6 +7022,62 @@ int get_grid_pin_height(int grid_x, int grid_y, int pin_index) {
|
|||
return pin_height;
|
||||
}
|
||||
|
||||
int get_grid_pin_side(int grid_x, int grid_y, int pin_index) {
|
||||
int pin_height, side, pin_side;
|
||||
t_type_ptr grid_type = NULL;
|
||||
|
||||
/* Get type */
|
||||
grid_type = grid[grid_x][grid_y].type;
|
||||
|
||||
/* Return if this is an empty type */
|
||||
if ((NULL == grid_type)
|
||||
||(EMPTY_TYPE == grid_type)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if the pin index is in the range */
|
||||
assert ( ((0 == pin_index) || (0 < pin_index))
|
||||
&&(pin_index < grid_type->num_pins) );
|
||||
|
||||
/* Find the pin_height */
|
||||
pin_height = get_grid_pin_height(grid_x, grid_y, pin_index);
|
||||
|
||||
pin_side = -1;
|
||||
for (side = 0; side < 4; side++) {
|
||||
/* Bypass corner cases */
|
||||
/* Pin can only locate on BOTTOM side, when grid is on TOP border */
|
||||
if ((ny == grid_y)&&(2 != side)) {
|
||||
continue;
|
||||
}
|
||||
/* Pin can only locate on LEFT side, when grid is on RIGHT border */
|
||||
if ((nx == grid_x)&&(3 != side)) {
|
||||
continue;
|
||||
}
|
||||
/* Pin can only locate on the TOP side, when grid is on BOTTOM border */
|
||||
if ((0 == grid_y)&&(0 != side)) {
|
||||
continue;
|
||||
}
|
||||
/* Pin can only locate on the RIGHT side, when grid is on LEFT border */
|
||||
if ((0 == grid_x)&&(1 != side)) {
|
||||
continue;
|
||||
}
|
||||
if (1 == grid_type->pinloc[pin_height][side][pin_index]) {
|
||||
if (-1 != pin_side) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(%s, [LINE%d]) Duplicated pin(index:%d) on two sides: %s and %s of type (name=%s)!\n",
|
||||
__FILE__, __LINE__,
|
||||
pin_index,
|
||||
convert_side_index_to_string(pin_side),
|
||||
convert_side_index_to_string(side),
|
||||
grid_type->name);
|
||||
exit(1);
|
||||
}
|
||||
pin_side = side;
|
||||
}
|
||||
}
|
||||
|
||||
return pin_side;
|
||||
}
|
||||
|
||||
void determine_sb_port_coordinator(t_sb cur_sb_info, int side,
|
||||
int* port_x, int* port_y) {
|
||||
/* Check */
|
||||
|
|
|
@ -117,6 +117,10 @@ void init_spice_net_info(t_spice_net_info* spice_net_info);
|
|||
t_spice_model* find_iopad_spice_model(int num_spice_model,
|
||||
t_spice_model* spice_models);
|
||||
|
||||
boolean is_grid_coordinate_in_range(int x_min,
|
||||
int x_max,
|
||||
int grid_x);
|
||||
|
||||
char* generate_string_spice_model_type(enum e_spice_model_type spice_model_type);
|
||||
|
||||
int determine_io_grid_side(int x,
|
||||
|
@ -588,6 +592,8 @@ t_pb* get_hardlogic_child_pb(t_pb* cur_hardlogic_pb,
|
|||
|
||||
int get_grid_pin_height(int grid_x, int grid_y, int pin_index);
|
||||
|
||||
int get_grid_pin_side(int grid_x, int grid_y, int pin_index);
|
||||
|
||||
void determine_sb_port_coordinator(t_sb cur_sb_info, int side,
|
||||
int* port_x, int* port_y);
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ float power_usage_mux_for_callibration(int num_inputs, float transistor_size) {
|
|||
|
||||
power_usage_mux_multilevel(&power_usage,
|
||||
power_get_mux_arch(num_inputs, transistor_size), prob, dens, 0,
|
||||
FALSE, power_callib_period);
|
||||
FALSE, power_callib_period); /* Xifan: turn output_restore to be true */
|
||||
|
||||
free(dens);
|
||||
free(prob);
|
||||
|
|
|
@ -596,7 +596,9 @@ void power_find_nmos_leakage(t_power_nmos_leakage_inf * nmos_leakage_info,
|
|||
nmos_leakage_info->leakage_pairs,
|
||||
nmos_leakage_info->num_leakage_pairs,
|
||||
sizeof(t_power_nmos_leakage_pair), power_compare_leakage_pair);
|
||||
if (!found) {
|
||||
assert(found);
|
||||
}
|
||||
|
||||
if (found
|
||||
== &nmos_leakage_info->leakage_pairs[nmos_leakage_info->num_leakage_pairs
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "rr_graph2.h"
|
||||
#include "linkedlist.h"
|
||||
|
||||
/*
|
||||
typedef struct s_clb_to_clb_directs {
|
||||
t_type_descriptor *from_clb_type;
|
||||
int from_clb_pin_start_index;
|
||||
|
@ -23,6 +24,7 @@ typedef struct s_clb_to_clb_directs {
|
|||
int to_clb_pin_start_index;
|
||||
int to_clb_pin_end_index;
|
||||
} t_clb_to_clb_directs;
|
||||
*/
|
||||
|
||||
typedef struct s_num_mapped_opins_stats t_num_mapped_opins_stats;
|
||||
struct s_num_mapped_opins_stats{
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef struct s_mux_size_distribution {
|
|||
struct s_mux_size_distribution *next;
|
||||
} t_mux_size_distribution;
|
||||
|
||||
/*
|
||||
typedef struct s_clb_to_clb_directs {
|
||||
t_type_descriptor *from_clb_type;
|
||||
int from_clb_pin_start_index;
|
||||
|
@ -52,6 +53,7 @@ typedef struct s_clb_to_clb_directs {
|
|||
int to_clb_pin_start_index;
|
||||
int to_clb_pin_end_index;
|
||||
} t_clb_to_clb_directs;
|
||||
*/
|
||||
|
||||
/* Xifan TANG: opin_to_cb support */
|
||||
#include "pb_pin_eq_auto_detect.h"
|
||||
|
@ -160,7 +162,9 @@ static void alloc_net_rr_terminals(void);
|
|||
|
||||
static void alloc_and_load_rr_clb_source(t_ivec *** L_rr_node_indices);
|
||||
|
||||
/*
|
||||
static t_clb_to_clb_directs *alloc_and_load_clb_to_clb_directs(INP t_direct_inf *directs, INP int num_directs);
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static void load_uniform_opin_switch_pattern_paired(INP int *Fc_out,
|
||||
|
@ -2771,7 +2775,6 @@ print_distribution(FILE * fptr,
|
|||
* Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure
|
||||
* This data structure supplements the the info in the "directs" data structure
|
||||
* TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one
|
||||
*/
|
||||
static t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs(INP t_direct_inf *directs, INP int num_directs) {
|
||||
int i, j;
|
||||
t_clb_to_clb_directs *clb_to_clb_directs;
|
||||
|
@ -2857,6 +2860,7 @@ static t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs(INP t_direct_inf
|
|||
}
|
||||
return clb_to_clb_directs;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Add all direct clb-pin-to-clb-pin edges to given opin */
|
||||
static int get_opin_direct_connecions(int x, int y, int opin, INOUTP t_linked_edge ** edge_list_ptr, INP t_ivec *** L_rr_node_indices,
|
||||
|
|
|
@ -92,6 +92,7 @@ char* spice_tb_global_config_done_port_name = "gconfig_done";
|
|||
char* spice_tb_global_set_port_name = "gset";
|
||||
char* spice_tb_global_reset_port_name = "greset";
|
||||
char* spice_tb_global_vdd_localrouting_port_name = "gvdd_local_interc";
|
||||
char* spice_tb_global_vdd_direct_port_name = "gvdd_direct_interc";
|
||||
char* spice_tb_global_vdd_io_port_name = "gvdd_io";
|
||||
char* spice_tb_global_vdd_hardlogic_port_name = "gvdd_hardlogic";
|
||||
char* spice_tb_global_vdd_sram_port_name = "gvdd_sram";
|
||||
|
|
|
@ -89,6 +89,7 @@ extern char* spice_tb_global_config_done_port_name;
|
|||
extern char* spice_tb_global_set_port_name;
|
||||
extern char* spice_tb_global_reset_port_name;
|
||||
extern char* spice_tb_global_vdd_localrouting_port_name;
|
||||
extern char* spice_tb_global_vdd_direct_port_name;
|
||||
extern char* spice_tb_global_vdd_io_port_name;
|
||||
extern char* spice_tb_global_vdd_hardlogic_port_name;
|
||||
extern char* spice_tb_global_vdd_sram_port_name;
|
||||
|
|
|
@ -1458,7 +1458,10 @@ int fprint_spice_mux_testbench_sb_one_mux(FILE* fp,
|
|||
*/
|
||||
|
||||
/* Determine if the interc lies inside a channel wire, that is interc between segments */
|
||||
if (1 == is_rr_node_exist_opposite_side_in_sb_info(cur_sb_info, src_rr_node, chan_side)) {
|
||||
/* Check each num_drive_rr_nodes, see if they appear in the cur_sb_info */
|
||||
if (TRUE == check_drive_rr_node_imply_short(cur_sb_info, src_rr_node, chan_side)) {
|
||||
/* Double check if the interc lies inside a channel wire, that is interc between segments */
|
||||
assert(1 == is_rr_node_exist_opposite_side_in_sb_info(cur_sb_info, src_rr_node, chan_side));
|
||||
num_drive_rr_nodes = 0;
|
||||
drive_rr_nodes = NULL;
|
||||
} else {
|
||||
|
|
|
@ -2126,7 +2126,7 @@ void fprint_grid_physical_blocks(FILE* fp,
|
|||
update_spice_models_grid_index_high(ix, iy, arch->spice->num_spice_model, arch->spice->spice_models);
|
||||
return;
|
||||
}
|
||||
capacity= grid[ix][iy].type->capacity;
|
||||
capacity = grid[ix][iy].type->capacity;
|
||||
assert(0 < capacity);
|
||||
|
||||
/* Make the sub-circuit name*/
|
||||
|
|
|
@ -156,7 +156,7 @@ void fprint_routing_chan_subckt(FILE* fp,
|
|||
void fprint_grid_side_pin_with_given_index(FILE* fp,
|
||||
int pin_index, int side,
|
||||
int x, int y) {
|
||||
int height, class_id;
|
||||
int height/*, class_id*/;
|
||||
t_type_ptr type = NULL;
|
||||
|
||||
/* Check the file handler*/
|
||||
|
@ -176,11 +176,11 @@ void fprint_grid_side_pin_with_given_index(FILE* fp,
|
|||
|
||||
/* Output the pins on the side*/
|
||||
height = get_grid_pin_height(x, y, pin_index);
|
||||
class_id = type->pin_class[pin_index];
|
||||
/* class_id = type->pin_class[pin_index]; */
|
||||
if ((1 == type->pinloc[height][side][pin_index])) {
|
||||
/* Not sure if we need to plus a height */
|
||||
/* fprintf(fp, "grid[%d][%d]_pin[%d][%d][%d] ", x, y, height, side, pin_index); */
|
||||
fprintf(fp, "grid[%d][%d]_pin[%d][%d][%d] ", x, y + height, height, side, pin_index);
|
||||
fprintf(fp, "grid[%d][%d]_pin[%d][%d][%d] ", x, y, height, side, pin_index);
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Fail to print a grid pin (x=%d, y=%d, height=%d, side=%d, index=%d)\n",
|
||||
__FILE__, __LINE__, x, y, height, side, pin_index);
|
||||
|
@ -289,7 +289,7 @@ void fprint_switch_box_short_interc(FILE* fp,
|
|||
int actual_fan_in,
|
||||
t_rr_node* drive_rr_node) {
|
||||
int side, index;
|
||||
int grid_x, grid_y, height;
|
||||
int grid_x, grid_y/*, height*/;
|
||||
char* chan_name = NULL;
|
||||
char* des_chan_port_name = NULL;
|
||||
|
||||
|
@ -332,7 +332,7 @@ void fprint_switch_box_short_interc(FILE* fp,
|
|||
/* Find grid_x and grid_y */
|
||||
grid_x = drive_rr_node->xlow;
|
||||
grid_y = drive_rr_node->ylow; /*Plus the offset in function fprint_grid_side_pin_with_given_index */
|
||||
height = grid[grid_x][grid_y].offset;
|
||||
/*height = grid[grid_x][grid_y].offset;*/
|
||||
/* Print a grid pin */
|
||||
fprint_grid_side_pin_with_given_index(fp, drive_rr_node->ptc_num,
|
||||
cur_sb_info.opin_rr_node_grid_side[side][index],
|
||||
|
@ -341,7 +341,15 @@ void fprint_switch_box_short_interc(FILE* fp,
|
|||
case CHANX:
|
||||
case CHANY:
|
||||
/* Should be an input */
|
||||
get_rr_node_side_and_index_in_sb_info(drive_rr_node, cur_sb_info, IN_PORT, &side, &index);
|
||||
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 = get_opposite_side(chan_side);
|
||||
index = get_rr_node_index_in_sb_info(drive_rr_node, cur_sb_info, side, IN_PORT);
|
||||
} else {
|
||||
get_rr_node_side_and_index_in_sb_info(drive_rr_node, cur_sb_info, IN_PORT, &side, &index);
|
||||
}
|
||||
/* We need to be sure that drive_rr_node is part of the SB */
|
||||
assert((-1 != index)&&(-1 != side));
|
||||
fprint_switch_box_chan_port(fp, cur_sb_info, side, drive_rr_node, IN_PORT);
|
||||
|
@ -371,7 +379,7 @@ void fprint_switch_box_mux(FILE* fp,
|
|||
t_rr_node** drive_rr_nodes,
|
||||
int switch_index) {
|
||||
int inode, side, index;
|
||||
int grid_x, grid_y, height;
|
||||
int grid_x, grid_y/*, height*/;
|
||||
t_spice_model* spice_model = NULL;
|
||||
int mux_level, path_id, cur_num_sram, ilevel;
|
||||
int num_mux_sram_bits = 0;
|
||||
|
@ -412,13 +420,11 @@ void fprint_switch_box_mux(FILE* fp,
|
|||
/* Search all the sides of a SB, see this drive_rr_node is an INPUT of this SB */
|
||||
get_rr_node_side_and_index_in_sb_info(drive_rr_nodes[inode], cur_sb_info, IN_PORT, &side, &index);
|
||||
/* We need to be sure that drive_rr_node is part of the SB */
|
||||
if (!((-1 != index)&&(-1 != side))) {
|
||||
assert((-1 != index)&&(-1 != side));
|
||||
}
|
||||
/* Find grid_x and grid_y */
|
||||
grid_x = drive_rr_nodes[inode]->xlow;
|
||||
grid_y = drive_rr_nodes[inode]->ylow; /*Plus the offset in function fprint_grid_side_pin_with_given_index */
|
||||
height = grid[grid_x][grid_y].offset;
|
||||
/* height = grid[grid_x][grid_y].offset; */
|
||||
/* Print a grid pin */
|
||||
fprint_grid_side_pin_with_given_index(fp, drive_rr_nodes[inode]->ptc_num,
|
||||
cur_sb_info.opin_rr_node_grid_side[side][index],
|
||||
|
@ -426,10 +432,12 @@ void fprint_switch_box_mux(FILE* fp,
|
|||
break;
|
||||
case CHANX:
|
||||
case CHANY:
|
||||
/* Should be an input ! */
|
||||
/* Should be an input! */
|
||||
get_rr_node_side_and_index_in_sb_info(drive_rr_nodes[inode], cur_sb_info, IN_PORT, &side, &index);
|
||||
/* We need to be sure that drive_rr_node is part of the SB */
|
||||
if (!((-1 != index)&&(-1 != side))) {
|
||||
assert((-1 != index)&&(-1 != side));
|
||||
}
|
||||
fprint_switch_box_chan_port(fp, cur_sb_info, side, drive_rr_nodes[inode], IN_PORT);
|
||||
break;
|
||||
default: /* IPIN, SINK are invalid*/
|
||||
|
@ -560,13 +568,11 @@ void fprint_switch_box_interc(FILE* fp,
|
|||
/* Check */
|
||||
assert((!(0 > sb_x))&&(!(sb_x > (nx + 1))));
|
||||
assert((!(0 > sb_y))&&(!(sb_y > (ny + 1))));
|
||||
/*
|
||||
find_drive_rr_nodes_switch_box(switch_box_x, switch_box_y, cur_rr_node, chan_side, 0,
|
||||
&num_drive_rr_nodes, &drive_rr_nodes, &switch_index);
|
||||
*/
|
||||
|
||||
/* Determine if the interc lies inside a channel wire, that is interc between segments */
|
||||
if (1 == is_rr_node_exist_opposite_side_in_sb_info(cur_sb_info, cur_rr_node, chan_side)) {
|
||||
/* Check each num_drive_rr_nodes, see if they appear in the cur_sb_info */
|
||||
if (TRUE == check_drive_rr_node_imply_short(cur_sb_info, cur_rr_node, chan_side)) {
|
||||
/* Double check if the interc lies inside a channel wire, that is interc between segments */
|
||||
assert(1 == is_rr_node_exist_opposite_side_in_sb_info(cur_sb_info, cur_rr_node, chan_side));
|
||||
num_drive_rr_nodes = 0;
|
||||
drive_rr_nodes = NULL;
|
||||
} else {
|
||||
|
@ -712,9 +718,10 @@ void fprint_routing_switch_box_subckt(FILE* fp, t_sb cur_sb_info,
|
|||
assert((CHANX == cur_sb_info.chan_rr_node[side][itrack]->type)
|
||||
||(CHANY == cur_sb_info.chan_rr_node[side][itrack]->type));
|
||||
/* We care INC_DIRECTION tracks at this side*/
|
||||
if (OUT_PORT == cur_sb_info.chan_rr_node_direction[side][itrack]) {
|
||||
fprint_switch_box_interc(fp, cur_sb_info, side, cur_sb_info.chan_rr_node[side][itrack]);
|
||||
}
|
||||
if (OUT_PORT != cur_sb_info.chan_rr_node_direction[side][itrack]) {
|
||||
continue;
|
||||
}
|
||||
fprint_switch_box_interc(fp, cur_sb_info, side, cur_sb_info.chan_rr_node[side][itrack]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -815,7 +822,7 @@ void fprint_connection_box_mux(FILE* fp,
|
|||
int num_mux_sram_bits = 0;
|
||||
int* mux_sram_bits = NULL;
|
||||
t_rr_type drive_rr_node_type = NUM_RR_TYPES;
|
||||
int xlow, ylow, offset, side, index;
|
||||
int xlow, ylow, /* offset,*/ side, index;
|
||||
char* sram_vdd_port_name = NULL;
|
||||
|
||||
/* Check the file handler*/
|
||||
|
@ -874,7 +881,7 @@ void fprint_connection_box_mux(FILE* fp,
|
|||
/* output port*/
|
||||
xlow = src_rr_node->xlow;
|
||||
ylow = src_rr_node->ylow;
|
||||
offset = grid[xlow][ylow].offset;
|
||||
/* offset = grid[xlow][ylow].offset; */
|
||||
|
||||
assert(IPIN == src_rr_node->type);
|
||||
/* Search all the sides of a CB, see this drive_rr_node is an INPUT of this SB */
|
||||
|
|
|
@ -169,6 +169,11 @@ void fprint_top_netlist_stimulations(FILE* fp,
|
|||
spice_tb_global_vdd_localrouting_port_name,
|
||||
"vsp");
|
||||
|
||||
fprintf(fp, "***** Global VDD for CLB to CLB direct connection *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_direct_port_name,
|
||||
"vsp");
|
||||
|
||||
fprintf(fp, "***** Global VDD for local routing SRAMs *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_localrouting_sram_port_name,
|
||||
|
@ -573,6 +578,8 @@ void fprint_top_netlist_measurements(FILE* fp,
|
|||
fprintf(fp, ".measure tran leakage_power_io find p(Vgvdd_io) at=0\n");
|
||||
/* Global power of Local Interconnections*/
|
||||
fprintf(fp, ".measure tran leakage_power_local_interc find p(Vgvdd_local_interc) at=0\n");
|
||||
/* Global power of CLB to CLB direct connections*/
|
||||
fprintf(fp, ".measure tran leakage_power_direct_interc find p(Vgvdd_direct_interc) at=0\n");
|
||||
} else {
|
||||
/* Leakage power of SRAMs */
|
||||
fprintf(fp, ".measure tran leakage_power_sram_local_routing avg p(Vgvdd_sram_local_routing) from=0 to='clock_period'\n");
|
||||
|
@ -583,6 +590,8 @@ void fprint_top_netlist_measurements(FILE* fp,
|
|||
fprintf(fp, ".measure tran leakage_power_io avg p(Vgvdd_io) from=0 to='clock_period'\n");
|
||||
/* Global power of Local Interconnections*/
|
||||
fprintf(fp, ".measure tran leakage_power_local_interc avg p(Vgvdd_local_interc) from=0 to='clock_period'\n");
|
||||
/* Global power of CLB to CLB Direct Interconnections*/
|
||||
fprintf(fp, ".measure tran leakage_power_direct_interc avg p(Vgvdd_direct_interc) from=0 to='clock_period'\n");
|
||||
}
|
||||
/* Leakge power of Hard logic */
|
||||
fprint_measure_vdds_spice_model(fp, SPICE_MODEL_HARDLOGIC, SPICE_MEASURE_LEAKAGE_POWER, num_clock_cycle, spice, leakage_only);
|
||||
|
@ -621,6 +630,10 @@ void fprint_top_netlist_measurements(FILE* fp,
|
|||
fprintf(fp, ".measure tran dynamic_power_local_interc avg p(Vgvdd_local_interc) from='clock_period' to='%d*clock_period'\n", num_clock_cycle);
|
||||
fprintf(fp, ".measure tran energy_per_cycle_local_routing \n ");
|
||||
fprintf(fp, "+ param='dynamic_power_local_interc*clock_period'\n");
|
||||
/* Dynamic power of Direct connection */
|
||||
fprintf(fp, ".measure tran dynamic_power_direct_interc avg p(Vgvdd_direct_interc) from='clock_period' to='%d*clock_period'\n", num_clock_cycle);
|
||||
fprintf(fp, ".measure tran energy_per_cycle_direct_interc \n ");
|
||||
fprintf(fp, "+ param='dynamic_power_direct_interc*clock_period'\n");
|
||||
/* Dynamic power of Hard Logic */
|
||||
fprint_measure_vdds_spice_model(fp, SPICE_MODEL_HARDLOGIC, SPICE_MEASURE_DYNAMIC_POWER, num_clock_cycle, spice, leakage_only);
|
||||
/* Dynamic power of LUTs */
|
||||
|
@ -712,6 +725,9 @@ void spice_print_top_netlist(char* circuit_name,
|
|||
/* Quote Routing structures: Switch Boxes */
|
||||
fprint_call_defined_switch_boxes(fp);
|
||||
|
||||
/* Apply CLB to CLB direct connections */
|
||||
fprint_spice_clb2clb_directs(fp, num_clb2clb_directs, clb2clb_direct);
|
||||
|
||||
/* Add stimulations */
|
||||
fprint_top_netlist_stimulations(fp, num_clock, spice);
|
||||
|
||||
|
|
|
@ -1342,6 +1342,161 @@ void fprint_call_defined_switch_boxes(FILE* fp) {
|
|||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_toplevel_one_grid_side_pin_with_given_index(FILE* fp,
|
||||
int pin_index, int side,
|
||||
int x, int y) {
|
||||
t_type_ptr type;
|
||||
int height;
|
||||
|
||||
/* 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 > x))&&(!(x > (nx + 1))));
|
||||
assert((!(0 > y))&&(!(y > (ny + 1))));
|
||||
|
||||
type = grid[x][y].type;
|
||||
assert(NULL != type);
|
||||
|
||||
assert((!(0 > pin_index))&&(pin_index < type->num_pins));
|
||||
assert((!(0 > side))&&(!(side > 3)));
|
||||
|
||||
/* Output the pins on the side*/
|
||||
height = get_grid_pin_height(x, y, pin_index);
|
||||
fprintf(fp, " grid[%d][%d]_pin[%d][%d][%d] ",
|
||||
x, y, height, side, pin_index);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Apply a CLB to CLB direct connection to a SPICE netlist */
|
||||
void fprint_spice_one_clb2clb_direct(FILE* fp,
|
||||
int from_grid_x, int from_grid_y,
|
||||
int to_grid_x, int to_grid_y,
|
||||
t_clb_to_clb_directs* cur_direct) {
|
||||
int ipin, cur_from_clb_pin_index, cur_to_clb_pin_index;
|
||||
int cur_from_clb_pin_side, cur_to_clb_pin_side;
|
||||
|
||||
/* 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 bandwidth match between from_clb and to_clb pins */
|
||||
if (0 != (cur_direct->from_clb_pin_end_index - cur_direct->from_clb_pin_start_index
|
||||
- cur_direct->to_clb_pin_end_index - cur_direct->to_clb_pin_start_index)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(%s, [LINE%d]) Unmatch pin bandwidth in direct connection (name=%s)!\n",
|
||||
__FILE__, __LINE__, cur_direct->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (ipin = 0; ipin < cur_direct->from_clb_pin_end_index - cur_direct->from_clb_pin_start_index; ipin++) {
|
||||
/* Update pin index and get the side of the pins on grids */
|
||||
cur_from_clb_pin_index = cur_direct->from_clb_pin_start_index + ipin;
|
||||
cur_to_clb_pin_index = cur_direct->to_clb_pin_start_index + ipin;
|
||||
cur_from_clb_pin_side = get_grid_pin_side(from_grid_x, from_grid_y, cur_from_clb_pin_index);
|
||||
cur_to_clb_pin_side = get_grid_pin_side(to_grid_x, to_grid_y, cur_to_clb_pin_index);
|
||||
/* Call the subckt that has already been defined before */
|
||||
fprintf(fp, "X%s[%d] ", cur_direct->spice_model->prefix, cur_direct->spice_model->cnt);
|
||||
/* Input: Print the source grid pin */
|
||||
fprint_spice_toplevel_one_grid_side_pin_with_given_index(fp,
|
||||
cur_from_clb_pin_index,
|
||||
cur_from_clb_pin_side,
|
||||
from_grid_x, from_grid_y);
|
||||
/* Output: Print the destination grid pin */
|
||||
fprint_spice_toplevel_one_grid_side_pin_with_given_index(fp,
|
||||
cur_to_clb_pin_index,
|
||||
cur_to_clb_pin_side,
|
||||
to_grid_x, from_grid_y);
|
||||
/* Print Global VDD and GND */
|
||||
fprintf(fp, "%s %s ",
|
||||
spice_tb_global_vdd_direct_port_name,
|
||||
spice_tb_global_gnd_port_name);
|
||||
/* End with spice_model name */
|
||||
fprintf(fp, "%s\n", cur_direct->spice_model->name);
|
||||
|
||||
/* Stats the number of spice_model used*/
|
||||
cur_direct->spice_model->cnt++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Apply CLB to CLB direct connections to a SPICE netlist */
|
||||
void fprint_spice_clb2clb_directs(FILE* fp,
|
||||
int num_directs,
|
||||
t_clb_to_clb_directs* direct) {
|
||||
int ix, iy, idirect;
|
||||
int to_clb_x, to_clb_y;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(fp, "***** BEGIN CLB to CLB Direct Connections *****\n");
|
||||
|
||||
/* Scan the grid, visit each grid and apply direct connections */
|
||||
for (ix = 0; ix < (nx + 1); ix++) {
|
||||
for (iy = 0; iy < (ny + 1); iy++) {
|
||||
/* Bypass EMPTY_TYPE*/
|
||||
if ((NULL == grid[ix][iy].type)
|
||||
|| (EMPTY_TYPE == grid[ix][iy].type)) {
|
||||
continue;
|
||||
}
|
||||
/* Check each clb2clb directs,
|
||||
* see if a match to the type
|
||||
*/
|
||||
for (idirect = 0; idirect < num_directs; idirect++) {
|
||||
/* Bypass unmatch types */
|
||||
if (grid[ix][iy].type != direct[idirect].from_clb_type) {
|
||||
continue;
|
||||
}
|
||||
/* Apply x/y_offset */
|
||||
to_clb_x = ix + direct[idirect].x_offset;
|
||||
to_clb_y = iy + direct[idirect].y_offset;
|
||||
/* see if the destination CLB is in the bound */
|
||||
if ((FALSE == is_grid_coordinate_in_range(0, nx, to_clb_x))
|
||||
||(FALSE == is_grid_coordinate_in_range(0, ny, to_clb_y))) {
|
||||
continue;
|
||||
}
|
||||
/* Check if capacity (z_offset) is in the range
|
||||
if (FALSE == is_grid_coordinate_in_range(0, grid[ix][iy].type->capacity, grid[ix][iy].type->z + direct[idirect].z_offset)) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
/* Check if the to_clb_type matches */
|
||||
if (grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) {
|
||||
continue;
|
||||
}
|
||||
/* Bypass x/y_offset = 1
|
||||
* since it may be addressed in Connection blocks
|
||||
if (1 == (x_offset + y_offset)) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
/* Now we can print a direct connection with the spice models */
|
||||
fprint_spice_one_clb2clb_direct(fp,
|
||||
ix, iy,
|
||||
to_clb_x, to_clb_y,
|
||||
&direct[idirect]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp, "***** END CLB to CLB Direct Connections *****\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print stimulations for floating ports in Grid
|
||||
* Some ports of CLB or I/O Pads is floating.
|
||||
* There are two cases :
|
||||
|
@ -3297,3 +3452,4 @@ t_llist* add_one_spice_tb_info_to_llist(t_llist* cur_head,
|
|||
return new_head;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -106,6 +106,14 @@ void fprint_call_defined_one_switch_box(FILE* fp,
|
|||
|
||||
void fprint_call_defined_switch_boxes(FILE* fp);
|
||||
|
||||
void fprint_spice_toplevel_one_grid_side_pin_with_given_index(FILE* fp,
|
||||
int pin_index, int side,
|
||||
int x, int y);
|
||||
|
||||
void fprint_spice_clb2clb_directs(FILE* fp,
|
||||
int num_directs,
|
||||
t_clb_to_clb_directs* direct);
|
||||
|
||||
void fprint_one_design_param_w_wo_variation(FILE* fp,
|
||||
char* param_name,
|
||||
float avg_val,
|
||||
|
|
|
@ -276,7 +276,7 @@ void dump_verilog_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
|
|||
if (TRUE == dump_port_type) {
|
||||
fprintf(fp, "%s ", verilog_port_type);
|
||||
}
|
||||
fprintf(fp, " grid_%d__%d__pin_%d__%d__%d_", x, y + height, height, side, pin_index);
|
||||
fprintf(fp, " grid_%d__%d__pin_%d__%d__%d_", x, y, height, side, pin_index);
|
||||
if (TRUE == dump_port_type) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
|
@ -331,9 +331,9 @@ void dump_verilog_grid_side_pins(FILE* fp,
|
|||
}
|
||||
|
||||
/* Output the pins on the side*/
|
||||
height = get_grid_pin_height(x, y, ipin);
|
||||
for (ipin = 0; ipin < type->num_pins; ipin++) {
|
||||
class_id = type->pin_class[ipin];
|
||||
height = get_grid_pin_height(x, y, ipin);
|
||||
if ((1 == type->pinloc[height][side][ipin])&&(pin_class_type == type->class_inf[class_id].type)) {
|
||||
if (TRUE == dump_port_type) {
|
||||
fprintf(fp, "%s ", verilog_port_type);
|
||||
|
@ -592,7 +592,15 @@ void dump_verilog_switch_box_short_interc(FILE* fp,
|
|||
case CHANX:
|
||||
case CHANY:
|
||||
/* Should an input */
|
||||
get_rr_node_side_and_index_in_sb_info(drive_rr_node, (*cur_sb_info), IN_PORT, &side, &index);
|
||||
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 = get_opposite_side(chan_side);
|
||||
index = get_rr_node_index_in_sb_info(drive_rr_node, (*cur_sb_info), side, IN_PORT);
|
||||
} else {
|
||||
get_rr_node_side_and_index_in_sb_info(drive_rr_node, (*cur_sb_info), IN_PORT, &side, &index);
|
||||
}
|
||||
/* We need to be sure that drive_rr_node is part of the SB */
|
||||
assert((-1 != index)&&(-1 != side));
|
||||
dump_verilog_switch_box_chan_port(fp, cur_sb_info, side, drive_rr_node, IN_PORT);
|
||||
|
@ -926,13 +934,12 @@ void dump_verilog_switch_box_interc(FILE* fp,
|
|||
/* Check */
|
||||
assert((!(0 > sb_x))&&(!(sb_x > (nx + 1))));
|
||||
assert((!(0 > sb_y))&&(!(sb_y > (ny + 1))));
|
||||
/*
|
||||
find_drive_rr_nodes_switch_box(switch_box_x, switch_box_y, cur_rr_node, chan_side, 0,
|
||||
&num_drive_rr_nodes, &drive_rr_nodes, &switch_index);
|
||||
*/
|
||||
|
||||
/* Determine if the interc lies inside a channel wire, that is interc between segments */
|
||||
if (1 == is_rr_node_exist_opposite_side_in_sb_info(*cur_sb_info, cur_rr_node, chan_side)) {
|
||||
/* Check each num_drive_rr_nodes, see if they appear in the cur_sb_info */
|
||||
if (TRUE == check_drive_rr_node_imply_short(*cur_sb_info, cur_rr_node, chan_side)) {
|
||||
/* Double check if the interc lies inside a channel wire, that is interc between segments */
|
||||
assert(1 == is_rr_node_exist_opposite_side_in_sb_info(*cur_sb_info, cur_rr_node, chan_side));
|
||||
num_drive_rr_nodes = 0;
|
||||
drive_rr_nodes = NULL;
|
||||
} else {
|
||||
|
|
|
@ -571,6 +571,7 @@ void dump_verilog_defined_one_grid(FILE* fp,
|
|||
|
||||
|
||||
/***** Print (call) the defined grids *****/
|
||||
static
|
||||
void dump_verilog_defined_grids(FILE* fp) {
|
||||
int ix, iy;
|
||||
|
||||
|
@ -642,6 +643,7 @@ void dump_verilog_defined_grids(FILE* fp) {
|
|||
/* Call defined channels.
|
||||
* Ensure the port name here is co-herent to other sub-circuits(SB,CB,grid)!!!
|
||||
*/
|
||||
static
|
||||
void dump_verilog_defined_one_channel(FILE* fp,
|
||||
t_rr_type chan_type, int x, int y,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
|
@ -782,6 +784,7 @@ void dump_verilog_defined_one_channel(FILE* fp,
|
|||
}
|
||||
|
||||
/* Call the sub-circuits for channels : Channel X and Channel Y*/
|
||||
static
|
||||
void dump_verilog_defined_channels(FILE* fp,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
|
@ -816,6 +819,7 @@ void dump_verilog_defined_channels(FILE* fp,
|
|||
* spice_routing.c : dump_verilog_conneciton_box_interc
|
||||
* Should be more clever to use the original function
|
||||
*/
|
||||
static
|
||||
void dump_verilog_defined_one_connection_box(FILE* fp,
|
||||
t_cb cur_cb_info) {
|
||||
int itrack, inode, side, x, y;
|
||||
|
@ -944,6 +948,7 @@ void dump_verilog_defined_one_connection_box(FILE* fp,
|
|||
}
|
||||
|
||||
/* Call the sub-circuits for connection boxes */
|
||||
static
|
||||
void dump_verilog_defined_connection_boxes(FILE* fp) {
|
||||
int ix, iy;
|
||||
|
||||
|
@ -980,6 +985,7 @@ void dump_verilog_defined_connection_boxes(FILE* fp) {
|
|||
* TODO: This function is also copied from
|
||||
* spice_routing.c : dump_verilog_routing_switch_box_subckt
|
||||
*/
|
||||
static
|
||||
void dump_verilog_defined_one_switch_box(FILE* fp,
|
||||
t_sb cur_sb_info) {
|
||||
int ix, iy, side, itrack, x, y, inode;
|
||||
|
@ -1074,6 +1080,7 @@ void dump_verilog_defined_one_switch_box(FILE* fp,
|
|||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_defined_switch_boxes(FILE* fp) {
|
||||
int ix, iy;
|
||||
|
||||
|
@ -1093,8 +1100,140 @@ void dump_verilog_defined_switch_boxes(FILE* fp) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Apply a CLB to CLB direct connection to a SPICE netlist
|
||||
*/
|
||||
static
|
||||
void dump_verilog_one_clb2clb_direct(FILE* fp,
|
||||
int from_grid_x, int from_grid_y,
|
||||
int to_grid_x, int to_grid_y,
|
||||
t_clb_to_clb_directs* cur_direct) {
|
||||
int ipin, cur_from_clb_pin_index, cur_to_clb_pin_index;
|
||||
int cur_from_clb_pin_side, cur_to_clb_pin_side;
|
||||
|
||||
/* 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 bandwidth match between from_clb and to_clb pins */
|
||||
if (0 != (cur_direct->from_clb_pin_end_index - cur_direct->from_clb_pin_start_index
|
||||
- cur_direct->to_clb_pin_end_index - cur_direct->to_clb_pin_start_index)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(%s, [LINE%d]) Unmatch pin bandwidth in direct connection (name=%s)!\n",
|
||||
__FILE__, __LINE__, cur_direct->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (ipin = 0; ipin < cur_direct->from_clb_pin_end_index - cur_direct->from_clb_pin_start_index; ipin++) {
|
||||
/* Update pin index and get the side of the pins on grids */
|
||||
cur_from_clb_pin_index = cur_direct->from_clb_pin_start_index + ipin;
|
||||
cur_to_clb_pin_index = cur_direct->to_clb_pin_start_index + ipin;
|
||||
cur_from_clb_pin_side = get_grid_pin_side(from_grid_x, from_grid_y, cur_from_clb_pin_index);
|
||||
cur_to_clb_pin_side = get_grid_pin_side(to_grid_x, to_grid_y, cur_to_clb_pin_index);
|
||||
/* Call the subckt that has already been defined before */
|
||||
fprintf(fp, "%s ", cur_direct->spice_model->name);
|
||||
fprintf(fp, "%s_%d_ (", cur_direct->spice_model->prefix, cur_direct->spice_model->cnt);
|
||||
/* Dump global ports */
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, cur_direct->spice_model, FALSE, FALSE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* Input: Print the source grid pin */
|
||||
dump_verilog_toplevel_one_grid_side_pin_with_given_index(fp, OPIN,
|
||||
cur_from_clb_pin_index,
|
||||
cur_from_clb_pin_side,
|
||||
from_grid_x, from_grid_y,
|
||||
FALSE);
|
||||
fprintf(fp, ", ");
|
||||
/* Output: Print the destination grid pin */
|
||||
dump_verilog_toplevel_one_grid_side_pin_with_given_index(fp, IPIN,
|
||||
cur_to_clb_pin_index,
|
||||
cur_to_clb_pin_side,
|
||||
to_grid_x, from_grid_y,
|
||||
FALSE);
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Stats the number of spice_model used*/
|
||||
cur_direct->spice_model->cnt++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Apply CLB to CLB direct connections to a Verilog netlist
|
||||
*/
|
||||
static
|
||||
void dump_verilog_clb2clb_directs(FILE* fp,
|
||||
int num_directs, t_clb_to_clb_directs* direct) {
|
||||
int ix, iy, idirect;
|
||||
int to_clb_x, to_clb_y;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(fp, "//----- BEGIN CLB to CLB Direct Connections -----\n");
|
||||
|
||||
/* Scan the grid, visit each grid and apply direct connections */
|
||||
for (ix = 0; ix < (nx + 1); ix++) {
|
||||
for (iy = 0; iy < (ny + 1); iy++) {
|
||||
/* Bypass EMPTY_TYPE*/
|
||||
if ((NULL == grid[ix][iy].type)
|
||||
|| (EMPTY_TYPE == grid[ix][iy].type)) {
|
||||
continue;
|
||||
}
|
||||
/* Check each clb2clb directs,
|
||||
* see if a match to the type
|
||||
*/
|
||||
for (idirect = 0; idirect < num_directs; idirect++) {
|
||||
/* Bypass unmatch types */
|
||||
if (grid[ix][iy].type != direct[idirect].from_clb_type) {
|
||||
continue;
|
||||
}
|
||||
/* Apply x/y_offset */
|
||||
to_clb_x = ix + direct[idirect].x_offset;
|
||||
to_clb_y = iy + direct[idirect].y_offset;
|
||||
/* see if the destination CLB is in the bound */
|
||||
if ((FALSE == is_grid_coordinate_in_range(0, nx, to_clb_x))
|
||||
||(FALSE == is_grid_coordinate_in_range(0, ny, to_clb_y))) {
|
||||
continue;
|
||||
}
|
||||
/* Check if capacity (z_offset) is in the range
|
||||
if (FALSE == is_grid_coordinate_in_range(0, grid[ix][iy].type->capacity, grid[ix][iy].type->z + direct[idirect].z_offset)) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
/* Check if the to_clb_type matches */
|
||||
if (grid[to_clb_x][to_clb_y].type != direct[idirect].to_clb_type) {
|
||||
continue;
|
||||
}
|
||||
/* Bypass x/y_offset = 1
|
||||
* since it may be addressed in Connection blocks
|
||||
if (1 == (x_offset + y_offset)) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
/* Now we can print a direct connection with the spice models */
|
||||
dump_verilog_one_clb2clb_direct(fp,
|
||||
ix, iy,
|
||||
to_clb_x, to_clb_y,
|
||||
&direct[idirect]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp, "//----- END CLB to CLB Direct Connections -----\n");
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/** Dump Standalone SRAMs
|
||||
*/
|
||||
static
|
||||
void dump_verilog_configuration_circuits_standalone_srams(FILE* fp) {
|
||||
int i;
|
||||
/* Check */
|
||||
|
@ -1123,6 +1262,7 @@ void dump_verilog_configuration_circuits_standalone_srams(FILE* fp) {
|
|||
|
||||
/** Dump scan-chains
|
||||
*/
|
||||
static
|
||||
void dump_verilog_configuration_circuits_scan_chains(FILE* fp) {
|
||||
int i;
|
||||
/* Check */
|
||||
|
@ -1151,6 +1291,7 @@ void dump_verilog_configuration_circuits_scan_chains(FILE* fp) {
|
|||
}
|
||||
|
||||
/* Dump a memory bank to configure all the Bit lines and Word lines */
|
||||
static
|
||||
void dump_verilog_configuration_circuits_memory_bank(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info) {
|
||||
int bl_decoder_size, wl_decoder_size;
|
||||
|
@ -1226,6 +1367,7 @@ void dump_verilog_configuration_circuits_memory_bank(FILE* fp,
|
|||
* 2. Memory banks
|
||||
* 3. Standalone SRAMs
|
||||
*/
|
||||
static
|
||||
void dump_verilog_configuration_circuits(FILE* fp) {
|
||||
switch(sram_verilog_orgz_info->type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
|
@ -1534,6 +1676,7 @@ void dump_verilog_top_testbench_call_top_module(FILE* fp,
|
|||
* (2) BL = 1 && WL = 1;
|
||||
* (3) BL = 1 && WL = 0 with a paired conf_bit;
|
||||
*/
|
||||
static
|
||||
int dump_verilog_top_testbench_find_num_config_clock_cycles(t_llist* head) {
|
||||
int cnt = 0;
|
||||
t_llist* temp = head;
|
||||
|
@ -2601,6 +2744,9 @@ void dump_verilog_top_netlist(char* circuit_name,
|
|||
/* Quote Routing structures: Switch Boxes */
|
||||
dump_verilog_defined_switch_boxes(fp);
|
||||
|
||||
/* Apply CLB to CLB direct connections */
|
||||
dump_verilog_clb2clb_directs(fp, num_clb2clb_directs, clb2clb_direct);
|
||||
|
||||
/* Dump configuration circuits */
|
||||
dump_verilog_configuration_circuits(fp);
|
||||
|
||||
|
|
|
@ -2019,3 +2019,63 @@ void dump_verilog_sram_config_bus_internal_wires(FILE* fp, t_sram_orgz_info* cur
|
|||
return;
|
||||
}
|
||||
|
||||
void dump_verilog_toplevel_one_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
|
||||
int pin_index, int side,
|
||||
int x, int y,
|
||||
boolean dump_port_type) {
|
||||
int height;
|
||||
t_type_ptr type = NULL;
|
||||
char* verilog_port_type = 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 */
|
||||
assert((!(0 > x))&&(!(x > (nx + 1))));
|
||||
assert((!(0 > y))&&(!(y > (ny + 1))));
|
||||
type = grid[x][y].type;
|
||||
assert(NULL != type);
|
||||
|
||||
assert((!(0 > pin_index))&&(pin_index < type->num_pins));
|
||||
assert((!(0 > side))&&(!(side > 3)));
|
||||
|
||||
/* Assign the type of PIN*/
|
||||
switch (pin_type) {
|
||||
case IPIN:
|
||||
/* case SINK: */
|
||||
verilog_port_type = "output";
|
||||
break;
|
||||
/* case SOURCE: */
|
||||
case OPIN:
|
||||
verilog_port_type = "input";
|
||||
break;
|
||||
/* SINK and SOURCE are hypothesis nodes */
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid pin_type!\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Output the pins on the side*/
|
||||
height = get_grid_pin_height(x, y, pin_index);
|
||||
if (1 == type->pinloc[height][side][pin_index]) {
|
||||
/* Not sure if we need to plus a height */
|
||||
/* fprintf(fp, "grid_%d__%d__pin_%d__%d__%d_ ", x, y, height, side, pin_index); */
|
||||
if (TRUE == dump_port_type) {
|
||||
fprintf(fp, "%s ", verilog_port_type);
|
||||
}
|
||||
fprintf(fp, " grid_%d__%d__pin_%d__%d__%d_", x, y, height, side, pin_index);
|
||||
if (TRUE == dump_port_type) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Fail to print a grid pin (x=%d, y=%d, height=%d, side=%d, index=%d)\n",
|
||||
__FILE__, __LINE__, x, y, height, side, pin_index);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,3 +138,8 @@ void dump_verilog_grid_common_port(FILE* fp, t_spice_model* cur_verilog_model,
|
|||
|
||||
void dump_verilog_sram_config_bus_internal_wires(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int lsb, int msb);
|
||||
|
||||
void dump_verilog_toplevel_one_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
|
||||
int pin_index, int side,
|
||||
int x, int y,
|
||||
boolean dump_port_type);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1154,3 +1154,103 @@ void alloc_and_load_idirect_from_blk_pin(t_direct_inf* directs, int num_directs,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Xifan Tang: Move this function from rr_graph.c
|
||||
* since it is useful and general to parse clb to clb directs
|
||||
* Parse out which CLB pins should connect directly to which other CLB pins then store that in a clb_to_clb_directs data structure
|
||||
* This data structure supplements the the info in the "directs" data structure
|
||||
* TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one
|
||||
*/
|
||||
t_clb_to_clb_directs * alloc_and_load_clb_to_clb_directs(INP t_direct_inf *directs,
|
||||
INP int num_directs) {
|
||||
int i, j;
|
||||
t_clb_to_clb_directs *clb_to_clb_directs;
|
||||
char *pb_type_name, *port_name;
|
||||
int start_pin_index, end_pin_index;
|
||||
t_pb_type *pb_type;
|
||||
|
||||
clb_to_clb_directs = (t_clb_to_clb_directs*)my_calloc(num_directs, sizeof(t_clb_to_clb_directs));
|
||||
|
||||
pb_type_name = NULL;
|
||||
port_name = NULL;
|
||||
|
||||
for(i = 0; i < num_directs; i++) {
|
||||
pb_type_name = (char*)my_malloc((strlen(directs[i].from_pin) + strlen(directs[i].to_pin)) * sizeof(char));
|
||||
port_name = (char*)my_malloc((strlen(directs[i].from_pin) + strlen(directs[i].to_pin)) * sizeof(char));
|
||||
|
||||
// Load from pins
|
||||
// Parse out the pb_type name, port name, and pin range
|
||||
parse_direct_pin_name(directs[i].from_pin, directs[i].line, &start_pin_index, &end_pin_index, pb_type_name, port_name);
|
||||
|
||||
// Figure out which type, port, and pin is used
|
||||
for(j = 0; j < num_types; j++) {
|
||||
if(strcmp(type_descriptors[j].name, pb_type_name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(j < num_types);
|
||||
clb_to_clb_directs[i].from_clb_type = &type_descriptors[j];
|
||||
pb_type = clb_to_clb_directs[i].from_clb_type->pb_type;
|
||||
|
||||
for(j = 0; j < pb_type->num_ports; j++) {
|
||||
if(strcmp(pb_type->ports[j].name, port_name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(j < pb_type->num_ports);
|
||||
|
||||
if(start_pin_index == OPEN) {
|
||||
assert(start_pin_index == end_pin_index);
|
||||
start_pin_index = 0;
|
||||
end_pin_index = pb_type->ports[j].num_pins - 1;
|
||||
}
|
||||
get_blk_pin_from_port_pin(clb_to_clb_directs[i].from_clb_type->index, j, start_pin_index, &clb_to_clb_directs[i].from_clb_pin_start_index);
|
||||
get_blk_pin_from_port_pin(clb_to_clb_directs[i].from_clb_type->index, j, end_pin_index, &clb_to_clb_directs[i].from_clb_pin_end_index);
|
||||
|
||||
// Load to pins
|
||||
// Parse out the pb_type name, port name, and pin range
|
||||
parse_direct_pin_name(directs[i].to_pin, directs[i].line, &start_pin_index, &end_pin_index, pb_type_name, port_name);
|
||||
|
||||
// Figure out which type, port, and pin is used
|
||||
for(j = 0; j < num_types; j++) {
|
||||
if(strcmp(type_descriptors[j].name, pb_type_name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(j < num_types);
|
||||
clb_to_clb_directs[i].to_clb_type = &type_descriptors[j];
|
||||
pb_type = clb_to_clb_directs[i].to_clb_type->pb_type;
|
||||
|
||||
for(j = 0; j < pb_type->num_ports; j++) {
|
||||
if(strcmp(pb_type->ports[j].name, port_name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(j < pb_type->num_ports);
|
||||
|
||||
if(start_pin_index == OPEN) {
|
||||
assert(start_pin_index == end_pin_index);
|
||||
start_pin_index = 0;
|
||||
end_pin_index = pb_type->ports[j].num_pins - 1;
|
||||
}
|
||||
|
||||
get_blk_pin_from_port_pin(clb_to_clb_directs[i].to_clb_type->index, j, start_pin_index, &clb_to_clb_directs[i].to_clb_pin_start_index);
|
||||
get_blk_pin_from_port_pin(clb_to_clb_directs[i].to_clb_type->index, j, end_pin_index, &clb_to_clb_directs[i].to_clb_pin_end_index);
|
||||
|
||||
if(abs(clb_to_clb_directs[i].from_clb_pin_start_index - clb_to_clb_directs[i].from_clb_pin_end_index) != abs(clb_to_clb_directs[i].to_clb_pin_start_index - clb_to_clb_directs[i].to_clb_pin_end_index)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "[LINE %d] Range mismatch from %s to %s.\n", directs[i].line, directs[i].from_pin, directs[i].to_pin);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Xifan Tang: assign values to x,y,z_offset */
|
||||
clb_to_clb_directs[i].x_offset = directs[i].x_offset;
|
||||
clb_to_clb_directs[i].y_offset = directs[i].y_offset;
|
||||
clb_to_clb_directs[i].z_offset = directs[i].z_offset;
|
||||
/* Xifan Tang: give the name */
|
||||
clb_to_clb_directs[i].name = my_strdup(directs[i].name);
|
||||
|
||||
free(pb_type_name);
|
||||
free(port_name);
|
||||
}
|
||||
return clb_to_clb_directs;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ void alloc_and_load_idirect_from_blk_pin(t_direct_inf* directs, int num_directs,
|
|||
void parse_direct_pin_name(char * src_string, int line, int * start_pin_index,
|
||||
int * end_pin_index, char * pb_type_name, char * port_name);
|
||||
|
||||
t_clb_to_clb_directs *alloc_and_load_clb_to_clb_directs(INP t_direct_inf *directs, INP int num_directs);
|
||||
|
||||
|
||||
void free_cb(t_pb *pb);
|
||||
void free_pb_stats(t_pb *pb);
|
||||
|
|
Loading…
Reference in New Issue