Merge branch 'multimode_clb' of https://github.com/LNIS-Projects/OpenFPGA into multimode_clb

This commit is contained in:
Baudouin Chauviere 2019-05-13 14:45:57 -06:00
commit b48a27acf0
36 changed files with 1635 additions and 1811 deletions

View File

@ -192,5 +192,12 @@ set_target_properties(libvpr vpr
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/vpr7_x2p/vpr"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/vpr7_x2p/vpr")
set_target_properties(libvpr vpr_shell
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/vpr7_x2p/vpr"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/vpr7_x2p/vpr"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/vpr7_x2p/vpr")

View File

@ -92,7 +92,7 @@
<port name="inpad"/>
</output_ports>
</model>
<!--model name="multiply">
<model name="multiply">
<input_ports>
<port name="a"/>
<port name="b"/>
@ -102,7 +102,7 @@
</output_ports>
</model>
<model name="single_port_ram">
<!--model name="single_port_ram">
<input_ports>
<port name="we"/--> <!-- control -->
<!--port name="addr"/--> <!-- address lines -->
@ -645,7 +645,7 @@
area associated with our DSP block is four times that of a logic tile, where the routing area of a logic tile was calculated above (at W = 300)
as 30481 MWTAs. Hence the (core, non-routing) area our DSP block is approximately 518,000 - 4 * 30,481 = 396,000 MWTUs.
-->
<!--pb_type name="mult_36" height="4" area="396000">
<pb_type name="mult_36" height="4" area="396000">
<input name="a" num_pins="36"/>
<input name="b" num_pins="36"/>
@ -655,18 +655,18 @@
<pb_type name="divisible_mult_18x18" num_pb="2">
<input name="a" num_pins="18"/>
<input name="b" num_pins="18"/>
<output name="out" num_pins="36"/-->
<output name="out" num_pins="36"/>
<!-- Model 9x9 delay and 18x18 delay as the same. 9x9 could be faster, but in Stratix IV
isn't, presumably because the multiplier layout is really optimized for 18x18.
-->
<!--mode name="two_mult_9x9">
<mode name="two_mult_9x9">
<pb_type name="mult_9x9_slice" num_pb="2">
<input name="A_cfg" num_pins="9"/>
<input name="B_cfg" num_pins="9"/>
<output name="OUT_cfg" num_pins="18"/>
<pb_type name="mult_9x9" blif_model=".subckt multiply" num_pb="1">
<pb_type name="mult_9x9" blif_model=".subckt multiply9" num_pb="1">
<input name="a" num_pins="9"/>
<input name="b" num_pins="9"/>
<output name="out" num_pins="18"/>
@ -705,7 +705,7 @@
<input name="B_cfg" num_pins="18"/>
<output name="OUT_cfg" num_pins="36"/>
<pb_type name="mult_18x18" blif_model=".subckt multiply" num_pb="1" >
<pb_type name="mult_18x18" blif_model=".subckt multiply18" num_pb="1" >
<input name="a" num_pins="18"/>
<input name="b" num_pins="18"/>
<output name="out" num_pins="36"/>
@ -739,11 +739,11 @@
<power method="sum-of-children"/>
</pb_type>
<interconnect-->
<interconnect>
<!-- Stratix IV input delay of 207ps is conservative for this architecture because this architecture does not have an input crossbar in the multiplier.
Subtract 72.5 ps delay, which is already in the connection block input mux, leading
-->
<!--direct name="a2a" input="mult_36.a" output="divisible_mult_18x18[1:0].a">
<direct name="a2a" input="mult_36.a" output="divisible_mult_18x18[1:0].a">
<delay_constant max="134e-12" in_port="mult_36.a" out_port="divisible_mult_18x18[1:0].a"/>
</direct>
<direct name="b2b" input="mult_36.b" output="divisible_mult_18x18[1:0].b">
@ -761,7 +761,7 @@
<input name="B_cfg" num_pins="36"/>
<output name="OUT_cfg" num_pins="72"/>
<pb_type name="mult_36x36" blif_model=".subckt multiply" num_pb="1">
<pb_type name="mult_36x36" blif_model=".subckt multiply36" num_pb="1">
<input name="a" num_pins="36"/>
<input name="b" num_pins="36"/>
<output name="out" num_pins="72"/>
@ -784,12 +784,12 @@
<static_power power_per_instance="0.0"/>
</power>
</pb_type>
<interconnect-->
<interconnect>
<!-- Stratix IV input delay of 207ps is conservative for this architecture because this architecture does not have an input crossbar in the multiplier.
Subtract 72.5 ps delay, which is already in the connection block input mux, leading
to a 134 ps delay.
-->
<!--direct name="a2a" input="mult_36.a" output="mult_36x36_slice.A_cfg">
<direct name="a2a" input="mult_36.a" output="mult_36x36_slice.A_cfg">
<delay_constant max="134e-12" in_port="mult_36.a" out_port="mult_36x36_slice.A_cfg"/>
</direct>
<direct name="b2b" input="mult_36.b" output="mult_36x36_slice.B_cfg">
@ -803,14 +803,14 @@
</mode>
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.10"/>
<pinlocations pattern="spread"/-->
<pinlocations pattern="spread"/>
<!-- Place this multiplier block every 8 columns from (and including) the sixth column -->
<!--gridlocations>
<gridlocations>
<loc type="col" start="6" repeat="8" priority="2"/>
</gridlocations>
<power method="sum-of-children"/>
</pb_type-->
</pb_type>
<!-- Define fracturable multiplier end -->
<!-- Define fracturable memory begin -->

View File

@ -31,7 +31,7 @@ find_package(Readline REQUIRED)
#Collect the source files
file(GLOB_RECURSE EXEC_SOURCES SRC/main.c)
file(GLOB_RECURSE EXEC_SOURCES_SHELL SRC/shell_main.c)
file(GLOB_RECURSE LIB_SOURCES SRC/*/*.c SRC/*/*/*.c)
file(GLOB_RECURSE LIB_SOURCES SRC/*/*.c SRC/*/*/*.c SRC/*/*.cpp SRC/*/*/*.cpp)
file(GLOB_RECURSE LIB_HEADERS SRC/*/*.h SRC/*/*/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)

View File

@ -61,6 +61,7 @@ struct s_TokenPair OptionBaseTokenList[] = {
{ "fpga_x2p_rename_illegal_port", OT_FPGA_X2P_RENAME_ILLEGAL_PORT }, /* Xifan TANG: rename illegal port names */
{ "fpga_x2p_signal_density_weight", OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT }, /* The weight of signal density */
{ "fpga_x2p_sim_window_size", OT_FPGA_X2P_SIM_WINDOW_SIZE }, /* Window size in determining number of clock cycles in simulation */
{ "fpga_x2p_compact_routing_hierarchy", OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY }, /* use a compact routing hierarchy in SPICE/Verilog generation */
/* Xifan TANG: FPGA SPICE Support */
{ "fpga_spice", OT_FPGA_SPICE },/* Xifan TANG: SPICE Model Support, turn on the functionality*/
{ "fpga_spice_dir", OT_FPGA_SPICE_DIR },/* Xifan TANG: SPICE Model Support, directory of spice netlists*/

View File

@ -78,6 +78,7 @@ enum e_OptionBaseToken {
OT_FPGA_X2P_RENAME_ILLEGAL_PORT,
OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT, /* The weight of signal density in determining number of clock cycles in simulation */
OT_FPGA_X2P_SIM_WINDOW_SIZE, /* Window size in determining number of clock cycles in simulation */
OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY, /* use a compact routing hierarchy in SPICE/Verilog generation */
/* Xifan TANG: FPGA SPICE Support */
OT_FPGA_SPICE, /* Xifan TANG: FPGA SPICE Model Support */
OT_FPGA_SPICE_DIR, /* Xifan TANG: FPGA SPICE Model Support */

View File

@ -481,6 +481,9 @@ ProcessOption(INP char **Args, INOUTP t_options * Options) {
return ReadFloat(Args, &Options->fpga_spice_signal_density_weight);
case OT_FPGA_X2P_SIM_WINDOW_SIZE:
return ReadFloat(Args, &Options->fpga_spice_sim_window_size);
case OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY:
/* use a compact routing hierarchy in SPICE/Verilog generation */
return Args;
/* Xifan TANG: FPGA SPICE Model Options*/
case OT_FPGA_SPICE:
return Args;

View File

@ -1235,6 +1235,12 @@ static void SetupFpgaSpiceOpts(t_options Options,
fpga_spice_opts->sim_window_size = Options.fpga_spice_sim_window_size;
}
/* Check if user wants to use a compact routing hierarchy */
fpga_spice_opts->compact_routing_hierarchy = FALSE;
if (Options.Count[OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY]) {
fpga_spice_opts->compact_routing_hierarchy = TRUE;
}
/* Decide if we need to do FPGA-SPICE */
fpga_spice_opts->do_fpga_spice = FALSE;
if (( TRUE == fpga_spice_opts->SpiceOpts.do_spice)

View File

@ -170,6 +170,7 @@ void vpr_print_usage(void) {
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_rename_illegal_port\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_signal_density_weight <float>\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_sim_window_size <float>\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_compact_routing_hierarchy\n");
vpr_printf(TIO_MESSAGE_INFO, "SPICE Support Options:\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_spice\n");
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_spice_dir <directory_path_output_spice_netlists>\n");

View File

@ -1153,6 +1153,18 @@ struct s_sb {
int num_reserved_conf_bits; /* number of reserved configuration bits */
int conf_bits_lsb; /* LSB of configuration bits */
int conf_bits_msb; /* MSB of configuration bits */
/* For identical SBs */
t_sb* mirror; /* an exact mirror of this switch block, with same connection & switches */
/* an rotatable mirror of this switch block,
* the two switch blocks will be same in terms of connection & switches
* by applying an offset to the connection & switches
*/
t_sb* rotatable;
/* Offset to be applied for each side of nodes */
int* offset_ipin; /* [0, ..., num_sides-1]*/
int* offset_opin; /* [0, ..., num_sides-1]*/
int* offset_chan; /* [0, ..., num_sides-1]*/
};
/* Information for each conneciton block */
@ -1188,6 +1200,18 @@ struct s_cb {
int num_reserved_conf_bits; /* number of reserved configuration bits */
int conf_bits_lsb; /* LSB of configuration bits */
int conf_bits_msb; /* MSB of configuration bits */
/* For identical SBs */
t_cb* mirror; /* an exact mirror of this connection block, with same connection & switches */
/* an rotatable mirror of this connection block,
* the two connection blocks will be same in terms of connection & switches
* by applying an offset to the connection & switches
*/
t_cb* rotatable;
/* Offset to be applied for each side of nodes */
int* offset_ipin; /* [0, ..., num_sides-1]*/
int* offset_opin; /* [0, ..., num_sides-1]*/
int* offset_chan; /* [0, ..., num_sides-1]*/
};
/* Xifan TANG: SPICE Support*/
@ -1255,6 +1279,8 @@ struct s_fpga_spice_opts {
t_syn_verilog_opts SynVerilogOpts; /* Xifan TANG: Synthesizable verilog dumping*/
t_bitstream_gen_opts BitstreamGenOpts; /* Xifan Bitsteam Generator */
boolean compact_routing_hierarchy; /* use compact routing hierarchy */
/* Signal Density */
float signal_density_weight;
float sim_window_size;

View File

@ -206,6 +206,12 @@ void init_one_sb_info(t_sb* cur_sb) {
cur_sb->conf_bits_lsb = 0;
cur_sb->conf_bits_msb = 0;
cur_sb->mirror = NULL;
cur_sb->rotatable = NULL;
cur_sb->offset_ipin = NULL;
cur_sb->offset_opin = NULL;
cur_sb->offset_chan = NULL;
return;
}
@ -237,6 +243,10 @@ void free_one_sb_info(t_sb* cur_sb) {
my_free(cur_sb->opin_rr_node);
my_free(cur_sb->opin_rr_node_grid_side);
my_free(cur_sb->offset_ipin);
my_free(cur_sb->offset_opin);
my_free(cur_sb->offset_chan);
return;
}
@ -299,6 +309,12 @@ void init_one_cb_info(t_cb* cur_cb) {
cur_cb->conf_bits_lsb = 0;
cur_cb->conf_bits_msb = 0;
cur_cb->mirror = NULL;
cur_cb->rotatable = NULL;
cur_cb->offset_ipin = NULL;
cur_cb->offset_opin = NULL;
cur_cb->offset_chan = NULL;
return;
}
@ -330,6 +346,10 @@ void free_one_cb_info(t_cb* cur_cb) {
my_free(cur_cb->opin_rr_node);
my_free(cur_cb->opin_rr_node_grid_side);
my_free(cur_cb->offset_ipin);
my_free(cur_cb->offset_opin);
my_free(cur_cb->offset_chan);
return;
}

View File

@ -0,0 +1,709 @@
/***********************************/
/* SPICE Modeling for VPR */
/* Xifan TANG, EPFL/LSI */
/***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
/* Include vpr structs*/
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph_util.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "vpr_utils.h"
#include "path_delay.h"
#include "stats.h"
#include "route_common.h"
/* Include spice support headers*/
#include "read_xml_spice_util.h"
#include "linkedlist.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_globals.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_backannotate_utils.h"
#include "fpga_x2p_identify_routing.h"
/***** subroutines declaration *****/
void assign_switch_block_mirror(t_sb* src, t_sb* des);
void assign_connection_block_mirror(t_cb* src, t_cb* des);
boolean is_two_sb_rr_nodes_mirror(t_sb* src_sb, t_sb* des_sb, int side,
t_rr_node* src_rr_node, t_rr_node* des_rr_node);
boolean is_two_cb_rr_nodes_mirror(t_cb* src_cb, t_cb* des_cb,
t_rr_node* src_rr_node, t_rr_node* des_rr_node);
boolean is_two_switch_blocks_mirror(t_sb* src, t_sb* des);
boolean is_two_connection_blocks_mirror(t_cb* src, t_cb* des);
void assign_mirror_switch_blocks();
void assign_mirror_connection_blocks();
boolean validate_one_switch_block_mirror(t_sb* cur_sb);
boolean validate_one_connection_block_mirror(t_cb* cur_cb);
void update_one_switch_block_mirror(t_sb* cur_sb);
void update_one_connection_block_mirror(t_cb* cur_cb);
boolean validate_mirror_switch_blocks();
boolean validate_mirror_connection_blocks();
void update_mirror_switch_blocks();
void update_mirror_connection_blocks();
void print_mirror_switch_block_stats();
void print_mirror_connection_block_stats();
/***** subroutines *****/
void assign_switch_block_mirror(t_sb* src, t_sb* des) {
assert ( (NULL != src) && (NULL != des) );
/* check if the mirror of the first SB is assigned */
if (NULL != src->mirror) {
/* Assign mirror of the first SB to the second SB */
/* traceback to the upstream */
t_sb* temp = src->mirror;
while (NULL != temp->mirror) {
/* go to the next */
temp = temp->mirror;
}
/* We reach the upstream, ensure its mirror is empty */
assert(NULL == temp->mirror);
des->mirror = temp;
} else {
/* Assign the first SB as the mirror to the second SB */
des->mirror = src;
}
return;
}
void assign_connection_block_mirror(t_cb* src, t_cb* des) {
assert ( (NULL != src) && (NULL != des) );
/* check if the mirror of the first SB is assigned */
if (NULL != src->mirror) {
/* Assign mirror of the first SB to the second SB */
/* traceback to the upstream */
t_cb* temp = src->mirror;
while (NULL != temp->mirror) {
/* go to the next */
temp = temp->mirror;
}
/* We reach the upstream, ensure its mirror is empty */
assert(NULL == temp->mirror);
des->mirror = temp;
} else {
/* Assign the first SB as the mirror to the second SB */
des->mirror = src;
}
return;
}
/* check if two rr_nodes have a similar set of drive_rr_nodes
* for each drive_rr_node:
* 1. CHANX or CHANY: should have the same side and index
* 2. OPIN or IPIN: should have the same side and index
* 3. each drive_rr_switch should be the same
*/
boolean is_two_sb_rr_nodes_mirror(t_sb* src_sb, t_sb* des_sb, int side,
t_rr_node* src_rr_node, t_rr_node* des_rr_node) {
/* Ensure rr_nodes are either the output of short-connection or multiplexer */
if ( check_drive_rr_node_imply_short(*src_sb, src_rr_node, side)
!= check_drive_rr_node_imply_short(*des_sb, des_rr_node, side)) {
return FALSE;
}
/* Find the driving rr_node in this sb */
if (TRUE == check_drive_rr_node_imply_short(*src_sb, src_rr_node, side)) {
/* Ensure we have the same track id for the driving nodes */
if ( is_rr_node_exist_opposite_side_in_sb_info(*src_sb, src_rr_node, side)
!= is_rr_node_exist_opposite_side_in_sb_info(*des_sb, des_rr_node, side)) {
return FALSE;
}
} else { /* check driving rr_nodes */
if ( src_rr_node->num_drive_rr_nodes != des_rr_node->num_drive_rr_nodes ) {
return FALSE;
}
for (int inode = 0; inode < src_rr_node->num_drive_rr_nodes; ++inode) {
/* node type should be the same */
if ( src_rr_node->drive_rr_nodes[inode]->type
!= des_rr_node->drive_rr_nodes[inode]->type) {
return FALSE;
}
/* switch type should be the same */
if ( src_rr_node->drive_switches[inode]
!= des_rr_node->drive_switches[inode]) {
return FALSE;
}
int src_node_id, des_node_id;
int src_node_side, des_node_side;
get_rr_node_side_and_index_in_sb_info(src_rr_node->drive_rr_nodes[inode], *src_sb, OUT_PORT, &src_node_side, &src_node_id);
get_rr_node_side_and_index_in_sb_info(des_rr_node->drive_rr_nodes[inode], *des_sb, OUT_PORT, &des_node_side, &des_node_id);
if (src_node_id != des_node_id) {
return FALSE;
}
if (src_node_side != des_node_side) {
return FALSE;
}
}
}
return TRUE;
}
/* check if two rr_nodes have a similar set of drive_rr_nodes
* for each drive_rr_node:
* 1. CHANX or CHANY: should have the same side and index
* 2. OPIN or IPIN: should have the same side and index
* 3. each drive_rr_switch should be the same
*/
boolean is_two_cb_rr_nodes_mirror(t_cb* src_cb, t_cb* des_cb,
t_rr_node* src_rr_node, t_rr_node* des_rr_node) {
/* check driving rr_nodes */
if ( src_rr_node->num_drive_rr_nodes != des_rr_node->num_drive_rr_nodes ) {
return FALSE;
}
for (int inode = 0; inode < src_rr_node->num_drive_rr_nodes; ++inode) {
/* node type should be the same */
if ( src_rr_node->drive_rr_nodes[inode]->type
!= des_rr_node->drive_rr_nodes[inode]->type) {
return FALSE;
}
/* switch type should be the same */
if ( src_rr_node->drive_switches[inode]
!= des_rr_node->drive_switches[inode]) {
return FALSE;
}
int src_node_id, des_node_id;
int src_node_side, des_node_side;
get_rr_node_side_and_index_in_cb_info(src_rr_node->drive_rr_nodes[inode], *src_cb, OUT_PORT, &src_node_side, &src_node_id);
get_rr_node_side_and_index_in_cb_info(des_rr_node->drive_rr_nodes[inode], *des_cb, OUT_PORT, &des_node_side, &des_node_id);
if (src_node_id != des_node_id) {
return FALSE;
}
if (src_node_side != des_node_side) {
return FALSE;
}
}
return TRUE;
}
/* Idenify mirror Switch blocks
* Check each two switch blocks:
* 1. Number of channel/opin/ipin rr_nodes are same
* For channel rr_nodes
* 2. check if their track_ids (ptc_num) are same
* 3. Check if the switches (ids) are same
* For opin/ipin rr_nodes,
* 4. check if their parent type_descriptors same,
* 5. check if pin class id and pin id are same
* If all above are satisfied, the two switch blocks are mirrors!
*/
boolean is_two_switch_blocks_mirror(t_sb* src, t_sb* des) {
/* check the numbers of sides */
if (src->num_sides != des->num_sides) {
return FALSE;
}
/* check the numbers/directionality of channel rr_nodes */
for (int side = 0; side < src->num_sides; ++side) {
/* Ensure we have the same channel width on this side */
if (src->chan_width[side] != des->chan_width[side]) {
return FALSE;
}
for (int itrack = 0; itrack < src->chan_width[side]; ++itrack) {
/* Check the directionality of each node */
if (src->chan_rr_node_direction[side][itrack] != des->chan_rr_node_direction[side][itrack]) {
return FALSE;
}
/* Check the track_id of each node */
if (src->chan_rr_node[side][itrack]->ptc_num != des->chan_rr_node[side][itrack]->ptc_num) {
return FALSE;
}
/* For OUT_PORT rr_node, we need to check fan-in */
if (OUT_PORT != src->chan_rr_node_direction[side][itrack]) {
continue; /* skip IN_PORT */
}
if (FALSE == is_two_sb_rr_nodes_mirror(src, des, side,
src->chan_rr_node[side][itrack],
des->chan_rr_node[side][itrack])) {
return FALSE;
}
}
}
/* check the numbers of opin_rr_nodes */
for (int side = 0; side < src->num_sides; ++side) {
if (src->num_ipin_rr_nodes[side] != des->num_ipin_rr_nodes[side]) {
return FALSE;
}
}
/* Make sure the number of conf bits are the same */
if ( (src->conf_bits_msb - src->conf_bits_lsb)
!= (des->conf_bits_msb - des->conf_bits_lsb)) {
return FALSE;
}
return TRUE;
}
/* Walk through all the switch blocks,
* Make one-to-one comparison,
* If we have a pair, update the 1st SB to be the base and label the 2nd as a mirror
* If the 1st SB is already a mirror to another, we will trace back to the upstream base and update the 2nd SB
*/
void assign_mirror_switch_blocks() {
/* Walkthrough each column, and find mirrors */
for (int ix = 0; ix < (nx + 1); ++ix) {
for (int iy = 0; iy < (ny + 1); ++iy) {
for (int jy = iy; jy < (ny + 1); ++jy) {
/* bypass the same one */
if (iy == jy) {
continue;
}
/* Do one-to-one comparison */
if (FALSE == is_two_switch_blocks_mirror(&(sb_info[ix][iy]), &(sb_info[ix][jy]))) {
/* Nothing to do if the two switch blocks are not equivalent */
continue;
}
/* configure the mirror of the second switch block */
assign_switch_block_mirror(&(sb_info[ix][iy]), &(sb_info[ix][jy]));
}
}
}
/* Now mirror switch blocks in each column has been annotated */
/* Walkthrough each row, and find mirrors */
for (int iy = 0; iy < (ny + 1); ++iy) {
for (int ix = 0; ix < (nx + 1); ++ix) {
for (int jx = ix; jx < (nx + 1); ++jx) {
/* bypass the same one */
if (ix == jx) {
continue;
}
/* Do one-to-one comparison */
if (FALSE == is_two_switch_blocks_mirror(&(sb_info[ix][iy]), &(sb_info[jx][iy]))) {
/* Nothing to do if the two switch blocks are not equivalent */
continue;
}
/* configure the mirror of the second switch block */
assign_switch_block_mirror(&(sb_info[ix][iy]), &(sb_info[jx][iy]));
}
}
}
return;
}
/* Validate the mirror of a switch block is the upstream
* with NULL mirror
*/
boolean validate_one_switch_block_mirror(t_sb* cur_sb) {
if (NULL == cur_sb->mirror) {
/* This is the upstream */
return TRUE;
}
/* If the upstream has a mirror, there is a bug */
if (NULL != cur_sb->mirror->mirror) {
return FALSE;
}
return TRUE;
}
/* Validate the mirror of a switch block is the upstream
* with NULL mirror
*/
boolean validate_one_connection_block_mirror(t_cb* cur_cb) {
if (NULL == cur_cb->mirror) {
/* This is the upstream */
return TRUE;
}
/* If the upstream has a mirror, there is a bug */
if (NULL != cur_cb->mirror->mirror) {
return FALSE;
}
return TRUE;
}
/* update the mirror of each switch block */
void update_one_switch_block_mirror(t_sb* cur_sb) {
if (NULL == cur_sb->mirror) {
/* This is the upstream */
return;
}
/* Assign mirror of the first SB to the second SB */
/* traceback to the upstream */
t_sb* temp = cur_sb->mirror;
while (NULL != temp->mirror) {
/* go to the next */
temp = temp->mirror;
}
/* We reach the upstream, ensure its mirror is empty */
assert(NULL == temp->mirror);
cur_sb->mirror = temp;
return;
}
/* update the mirror of each switch block */
void update_one_connection_block_mirror(t_cb* cur_cb) {
if (NULL == cur_cb->mirror) {
/* This is the upstream */
return;
}
/* Assign mirror of the first SB to the second SB */
/* traceback to the upstream */
t_cb* temp = cur_cb->mirror;
while (NULL != temp->mirror) {
/* go to the next */
temp = temp->mirror;
}
/* We reach the upstream, ensure its mirror is empty */
assert(NULL == temp->mirror);
cur_cb->mirror = temp;
return;
}
/* Validate the mirror of each switch block is the upstream */
boolean validate_mirror_switch_blocks() {
boolean ret = TRUE;
/* Walkthrough each column, and find mirrors */
for (int ix = 0; ix < (nx + 1); ++ix) {
for (int iy = 0; iy < (ny + 1); ++iy) {
if (FALSE == validate_one_switch_block_mirror(&(sb_info[ix][iy]))) {
ret = FALSE;
}
}
}
return ret;
}
/* Validate the mirror of each connection block is the upstream */
boolean validate_mirror_connection_blocks() {
boolean ret = TRUE;
/* X - channels [1...nx][0..ny]*/
for (int iy = 0; iy < (ny + 1); iy++) {
for (int ix = 1; ix < (nx + 1); ix++) {
if (FALSE == validate_one_connection_block_mirror(&(cbx_info[ix][iy]))) {
ret = FALSE;
}
}
}
/* Y - channels [1...ny][0..nx]*/
for (int ix = 0; ix < (nx + 1); ix++) {
for (int iy = 1; iy < (ny + 1); iy++) {
if (FALSE == validate_one_connection_block_mirror(&(cby_info[ix][iy]))) {
ret = FALSE;
}
}
}
return ret;
}
/* Validate the mirror of each switch block is the upstream */
void update_mirror_switch_blocks() {
/* Walkthrough each column, and find mirrors */
for (int ix = 0; ix < (nx + 1); ++ix) {
for (int iy = 0; iy < (ny + 1); ++iy) {
update_one_switch_block_mirror(&(sb_info[ix][iy]));
}
}
return;
}
/* Validate the mirror of each connection block is the upstream */
void update_mirror_connection_blocks() {
/* X - channels [1...nx][0..ny]*/
for (int iy = 0; iy < (ny + 1); iy++) {
for (int ix = 1; ix < (nx + 1); ix++) {
update_one_connection_block_mirror(&(cbx_info[ix][iy]));
}
}
/* Y - channels [1...ny][0..nx]*/
for (int ix = 0; ix < (nx + 1); ix++) {
for (int iy = 1; iy < (ny + 1); iy++) {
update_one_connection_block_mirror(&(cby_info[ix][iy]));
}
}
return;
}
void print_mirror_switch_block_stats() {
int num_mirror_sb = 0;
/* Walkthrough each column, and find mirrors */
for (int ix = 0; ix < (nx + 1); ++ix) {
for (int iy = 0; iy < (ny + 1); ++iy) {
if (NULL == sb_info[ix][iy].mirror) {
num_mirror_sb++;
}
}
}
/* Print stats */
vpr_printf(TIO_MESSAGE_INFO,
"Detect %d independent switch blocks from %d switch blocks.\n",
num_mirror_sb, (nx + 1) * (ny + 1) );
return;
}
void print_mirror_connection_block_stats() {
int num_mirror_cbx = 0;
int num_mirror_cby = 0;
/* X - channels [1...nx][0..ny]*/
for (int iy = 0; iy < (ny + 1); iy++) {
for (int ix = 1; ix < (nx + 1); ix++) {
if (NULL == cbx_info[ix][iy].mirror) {
num_mirror_cbx++;
}
}
}
/* Y - channels [1...ny][0..nx]*/
for (int ix = 0; ix < (nx + 1); ix++) {
for (int iy = 1; iy < (ny + 1); iy++) {
if (NULL == cby_info[ix][iy].mirror) {
num_mirror_cby++;
}
}
}
/* Print stats */
vpr_printf(TIO_MESSAGE_INFO,
"Detect %d independent connection blocks from %d X-channel connection blocks.\n",
num_mirror_cbx, (nx + 0) * (ny + 1) );
vpr_printf(TIO_MESSAGE_INFO,
"Detect %d independent connection blocks from %d Y-channel connection blocks.\n",
num_mirror_cby, (nx + 1) * (ny + 0) );
return;
}
void identify_mirror_switch_blocks() {
/* Assign the mirror of each switch block */
assign_mirror_switch_blocks();
/* Ensure all the mirror are the upstream */
update_mirror_switch_blocks();
/* Validate the mirror of switch blocks, everyone should be the upstream */
assert(TRUE == validate_mirror_switch_blocks());
/* print the stats */
print_mirror_switch_block_stats();
return;
}
/* Idenify mirror connection blocks
* Check each two connection blocks:
* 1. Number of channel/opin/ipin rr_nodes are same
* For channel rr_nodes
* 2. check if their track_ids (ptc_num) are same
* 3. Check if the switches (ids) are same
* For opin/ipin rr_nodes,
* 4. check if their parent type_descriptors same,
* 5. check if pin class id and pin id are same
* If all above are satisfied, the two switch blocks are mirrors!
*/
boolean is_two_connection_blocks_mirror(t_cb* src, t_cb* des) {
/* check the numbers of sides */
if (src->num_sides != des->num_sides) {
return FALSE;
}
/* check the numbers/directionality of channel rr_nodes */
for (int side = 0; side < src->num_sides; ++side) {
/* Ensure we have the same channel width on this side */
if (src->chan_width[side] != des->chan_width[side]) {
return FALSE;
}
for (int itrack = 0; itrack < src->chan_width[side]; ++itrack) {
/* Check the directionality of each node */
if (src->chan_rr_node_direction[side][itrack] != des->chan_rr_node_direction[side][itrack]) {
return FALSE;
}
/* Check the track_id of each node */
if (src->chan_rr_node[side][itrack]->ptc_num != des->chan_rr_node[side][itrack]->ptc_num) {
return FALSE;
}
}
}
/* check the equivalence of ipins */
for (int side = 0; side < src->num_sides; ++side) {
/* Ensure we have the same number of IPINs on this side */
if (src->num_ipin_rr_nodes[side] != des->num_ipin_rr_nodes[side]) {
return FALSE;
}
for (int inode = 0; inode < src->num_ipin_rr_nodes[side]; ++inode) {
if (FALSE == is_two_cb_rr_nodes_mirror(src, des,
src->ipin_rr_node[side][inode],
des->ipin_rr_node[side][inode])) {
return FALSE;
}
}
}
/* Make sure the number of conf bits are the same */
if ( (src->conf_bits_msb - src->conf_bits_lsb)
!= (des->conf_bits_msb - des->conf_bits_lsb)) {
return FALSE;
}
return TRUE;
}
void assign_mirror_connection_blocks() {
/* X - channels [1...nx][0..ny]*/
for (int iy = 0; iy < (ny + 1); iy++) {
for (int ix = 1; ix < (nx + 1); ix++) {
for (int jx = ix; jx < (nx + 1); jx++) {
/* bypass the same one */
if (ix == jx) {
continue;
}
/* Do one-to-one comparison */
if (FALSE == is_two_connection_blocks_mirror(&(cbx_info[ix][iy]), &(cbx_info[jx][iy]))) {
/* Nothing to do if the two switch blocks are not equivalent */
continue;
}
/* configure the mirror of the second switch block */
assign_connection_block_mirror(&(cbx_info[ix][iy]), &(cbx_info[jx][iy]));
}
}
}
for (int ix = 1; ix < (nx + 1); ix++) {
for (int iy = 0; iy < (ny + 1); iy++) {
for (int jy = iy; jy < (ny + 1); jy++) {
/* bypass the same one */
if (iy == jy) {
continue;
}
/* Do one-to-one comparison */
if (FALSE == is_two_connection_blocks_mirror(&(cbx_info[ix][iy]), &(cbx_info[ix][jy]))) {
/* Nothing to do if the two switch blocks are not equivalent */
continue;
}
/* configure the mirror of the second switch block */
assign_connection_block_mirror(&(cbx_info[ix][iy]), &(cbx_info[ix][jy]));
}
}
}
/* Y - channels [1...ny][0..nx]*/
for (int ix = 0; ix < (nx + 1); ix++) {
for (int iy = 1; iy < (ny + 1); iy++) {
for (int jy = iy; jy < (ny + 1); jy++) {
/* bypass the same one */
if (iy == jy) {
continue;
}
/* Do one-to-one comparison */
if (FALSE == is_two_connection_blocks_mirror(&(cby_info[ix][iy]), &(cby_info[ix][jy]))) {
/* Nothing to do if the two switch blocks are not equivalent */
continue;
}
/* configure the mirror of the second switch block */
assign_connection_block_mirror(&(cby_info[ix][iy]), &(cby_info[ix][jy]));
}
}
}
for (int iy = 1; iy < (ny + 1); iy++) {
for (int ix = 0; ix < (nx + 1); ix++) {
for (int jx = ix; jx < (nx + 1); jx++) {
/* bypass the same one */
if (ix == jx) {
continue;
}
/* Do one-to-one comparison */
if (FALSE == is_two_connection_blocks_mirror(&(cby_info[ix][iy]), &(cby_info[jx][iy]))) {
/* Nothing to do if the two switch blocks are not equivalent */
continue;
}
/* configure the mirror of the second switch block */
assign_connection_block_mirror(&(cby_info[ix][iy]), &(cby_info[jx][iy]));
}
}
}
return;
}
/* Idenify mirror Connection blocks */
void identify_mirror_connection_blocks() {
/* Assign the mirror of each switch block */
assign_mirror_connection_blocks();
/* Ensure all the mirror are the upstream */
update_mirror_connection_blocks();
/* Validate the mirror of switch blocks, everyone should be the upstream */
assert(TRUE == validate_mirror_connection_blocks());
/* print the stats */
print_mirror_connection_block_stats();
return;
}
/* Rotatable will be done in the next step
void identify_rotatable_switch_blocks();
void identify_rotatable_connection_blocks();
*/

View File

@ -0,0 +1,13 @@
/* Avoid repeated header inclusion */
#ifndef FPGA_X2P_IDENTIFY_ROUTING
#define FPGA_X2P_IDENTIFY_ROUTING
void identify_mirror_switch_blocks();
void identify_mirror_connection_blocks();
/* Rotatable will be done in the next step
identify_rotatable_switch_blocks();
identify_rotatable_connection_blocks();
*/
#endif

View File

@ -113,8 +113,6 @@ t_pb* get_child_pb_for_phy_pb_graph_node(t_pb* cur_pb, int ipb, int jpb);
t_phy_pb* get_phy_child_pb_for_phy_pb_graph_node(t_phy_pb* cur_phy_pb, int ipb, int jpb);
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin) ;
t_spice_model* find_pb_graph_pin_in_edges_interc_model(t_pb_graph_pin pb_graph_pin) ;
void find_interc_fan_in_des_pb_graph_pin(t_pb_graph_pin* des_pb_graph_pin,
@ -210,8 +208,6 @@ t_phy_pb* rec_get_phy_pb_by_name(t_phy_pb* cur_phy_pb,
int get_pb_graph_node_wired_lut_logical_block_index(t_pb_graph_node* cur_pb_graph_node,
t_rr_node* op_pb_rr_graph);
void rec_reset_pb_graph_node_rr_node_index_physical_pb(t_pb_graph_node* cur_pb_graph_node);
void sync_wired_lut_to_one_phy_pb(t_pb_graph_node* cur_pb_graph_node,
t_phy_pb* cur_phy_pb,
t_rr_node* op_pb_rr_graph);

View File

@ -31,6 +31,7 @@
#include "fpga_x2p_backannotate_utils.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "verilog_api.h"
#include "fpga_x2p_identify_routing.h"
#include "fpga_x2p_setup.h"
/***** Subroutines Declarations *****/
@ -1307,7 +1308,7 @@ void fpga_x2p_free(t_arch* Arch) {
/* Top-level function of FPGA-SPICE setup */
void fpga_x2p_setup(t_vpr_setup vpr_setup,
t_arch* Arch) {
t_arch* Arch) {
int num_rename_violation = 0;
int num_clocks = 0;
float vpr_crit_path_delay = 0.;
@ -1391,6 +1392,17 @@ void fpga_x2p_setup(t_vpr_setup vpr_setup,
vpr_setup.FPGA_SPICE_Opts.read_act_file,
vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_parasitic_net_estimation);
/* Try to use mirror SBs/CBs if enabled by user */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy) {
/* Idenify mirror and rotatable Switch blocks and Connection blocks */
identify_mirror_switch_blocks();
identify_mirror_connection_blocks();
/* Rotatable will be done in the next step
identify_rotatable_switch_blocks();
identify_rotatable_connection_blocks();
*/
}
/* Not should be done when read_act_file is disabled */
if (FALSE == vpr_setup.FPGA_SPICE_Opts.read_act_file) {
return;

View File

@ -1,3 +1,6 @@
#ifndef FPGA_X2P_UTILS_H
#define FPGA_X2P_UTILS_H
void my_free(void* ptr);
char* my_gettime();
@ -66,15 +69,8 @@ char* chomp_spice_node_prefix(char* spice_node_prefix);
char* format_spice_node_prefix(char* spice_node_prefix);
char* format_spice_node_prefix(char* spice_node_prefix);
t_block* search_mapped_block(int x, int y, int z);
char** fpga_spice_strtok(char* str,
char* delims,
int* len);
@ -409,3 +405,5 @@ void get_fpga_x2p_global_op_clock_ports(t_llist* head,
void get_fpga_x2p_global_all_clock_ports(t_llist* head,
int* num_clock_ports,
t_spice_model_port*** clock_port);
#endif

View File

@ -0,0 +1,270 @@
#include <cassert>
#include "rr_chan.h"
/* Member Functions of Class RRChan */
/* accessors */
t_rr_type RRChan::get_type() const {
return type_;
}
/* get the number of tracks in this channel */
size_t RRChan::get_chan_width() const {
return nodes_.size();
}
/* get the track_id of a node */
int RRChan::get_node_track_id(t_rr_node* node) const {
/* if the given node is NULL, we return an invalid id */
if (NULL == node) {
return -1; /* FIXME: use a strong id!!! */
}
/* check each member and return if we find a match in content */
for (size_t inode = 0; inode < nodes_.size(); ++inode) {
if (node == nodes_[inode]) {
return inode;
}
}
return -1;
}
/* get the rr_node with the track_id */
t_rr_node* RRChan::get_node(size_t track_num) const {
if ( false == valid_node_id(track_num) ) {
return NULL;
}
return nodes_[track_num];
}
/* get the segment id of a node */
int RRChan::get_node_segment(t_rr_node* node) const {
int node_id = get_node_track_id(node);
if ( false == valid_node_id(node_id)) {
return -1;
}
return get_node_segment(node_id);
}
/* get the segment id of a node */
int RRChan::get_node_segment(size_t track_num) const {
if ( false == valid_node_id(track_num)) {
return -1;
}
return node_segments_[track_num];
}
/* evaluate if two RRChan is mirror to each other */
bool RRChan::is_mirror(RRChan& cand) const {
/* If any following element does not match, it is not mirror */
/* 1. type */
if (this->get_type() != cand.get_type()) {
return false;
}
/* 2. track_width */
if (this->get_chan_width() != cand.get_chan_width()) {
return false;
}
/* 3. for each node */
for (size_t inode = 0; inode < this->get_chan_width(); ++inode) {
/* 3.1 check node type */
if (this->get_node(inode)->type != cand.get_node(inode)->type) {
return false;
}
/* 3.2 check node directionality */
if (this->get_node(inode)->direction != cand.get_node(inode)->direction) {
return false;
}
/* 3.3 check node segment */
if (this->get_node_segment(inode) != cand.get_node_segment(inode)) {
return false;
}
}
return true;
}
/* Mutators */
/* modify type */
void RRChan::set_type(t_rr_type type) {
assert(valid_type(type));
type_ = type;
return;
}
/* add a node to the array */
void RRChan::add_node(t_rr_node* node, size_t node_segment) {
/* resize the array if needed, node is placed in the sequence of node->ptc_num */
if (size_t(node->ptc_num) > (nodes_.size() + 1)) {
nodes_.resize(node->ptc_num + 1); /* resize to the maximum */
node_segments_.resize(node->ptc_num + 1); /* resize to the maximum */
}
/* fill the dedicated element in the vector */
nodes_[node->ptc_num] = node;
node_segments_[node->ptc_num] = node_segment;
return;
}
/* Clear content */
void RRChan::clear() {
nodes_.clear();
node_segments_.clear();
return;
}
/* Internal functions */
/* for type, only valid type is CHANX and CHANY */
bool RRChan::valid_type(t_rr_type type) const {
if ((CHANX == type) && (CHANY == type)) {
return true;
}
return false;
}
/* check if the node id is valid */
bool RRChan::valid_node_id(size_t node_id) const {
if ( (size_t(-1) < node_id) && (node_id < nodes_.size()) ) {
return true;
}
return false;
}
/* Member Functions of Class DeviceRRChan */
/* accessors */
RRChan DeviceRRChan::get_module(t_rr_type chan_type, size_t module_id) const {
assert(valid_module_id(chan_type, module_id));
if (CHANX == chan_type) {
return chanx_modules_[module_id];
} else if (CHANY == chan_type) {
return chany_modules_[module_id];
}
}
void DeviceRRChan::init_module_ids(size_t device_width, size_t device_height) {
init_chan_module_ids(CHANX, device_width, device_height);
init_chan_module_ids(CHANY, device_width, device_height);
return;
}
void DeviceRRChan::init_chan_module_ids(t_rr_type chan_type, size_t device_width, size_t device_height) {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
chanx_module_ids_.resize(device_width);
for (size_t x = 0; x < chanx_module_ids_.size(); ++x) {
chanx_module_ids_[x].resize(device_height);
}
} else if (CHANY == chan_type) {
chany_module_ids_.resize(device_width);
for (size_t x = 0; x < chany_module_ids_.size(); ++x) {
chany_module_ids_[x].resize(device_height);
}
}
return;
}
void DeviceRRChan::add_one_chan_module(t_rr_type chan_type, size_t x, size_t y, RRChan rr_chan) {
assert(valid_coordinator(chan_type, x, y));
if (CHANX == chan_type) {
/* Find if the module is unique */
for (size_t i = 0; i < chanx_modules_.size(); ++i) {
if ( true == chanx_modules_[i].is_mirror(rr_chan)) {
/* Find a mirror in the list, assign ids and return */
chanx_module_ids_[x][y] = i;
return;
}
}
/* Reach here, it means this is a unique module */
/* add to the module list */
chanx_modules_.push_back(rr_chan);
chanx_module_ids_[x][y] = chanx_modules_.size() - 1;
} else if (CHANY == chan_type) {
/* Find if the module is unique */
for (size_t i = 0; i < chany_modules_.size(); ++i) {
if ( true == chany_modules_[i].is_mirror(rr_chan)) {
/* Find a mirror in the list, assign ids and return */
chany_module_ids_[x][y] = i;
return;
}
}
/* Reach here, it means this is a unique module */
/* add to the module list */
chany_modules_.push_back(rr_chan);
chany_module_ids_[x][y] = chany_modules_.size() - 1;
}
return;
}
void DeviceRRChan::clear() {
clear_chan(CHANX);
clear_chan(CHANY);
}
void DeviceRRChan::clear_chan(t_rr_type chan_type) {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
chanx_modules_.clear();
} else if (CHANY == chan_type) {
chany_modules_.clear();
}
return;
}
/* for type, only valid type is CHANX and CHANY */
bool DeviceRRChan::valid_chan_type(t_rr_type chan_type) const {
if ((CHANX == chan_type) && (CHANY == chan_type)) {
return true;
}
return false;
}
/* check if the coordinator is in range */
bool DeviceRRChan::valid_coordinator(t_rr_type chan_type, size_t x, size_t y) const {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
if (!( (size_t(-1) < x) && (x < chanx_module_ids_.size()) )) {
return false;
}
if (!( (size_t(-1) < y) && (y < chanx_module_ids_[x].size()) )) {
return false;
}
} else if (CHANY == chan_type) {
if (!( (size_t(-1) < x) && (x < chany_module_ids_.size()) )) {
return false;
}
if (!( (size_t(-1) < y) && (y < chany_module_ids_[x].size()) )) {
return false;
}
}
return true;
}
/* check if the node id is valid */
bool DeviceRRChan::valid_module_id(t_rr_type chan_type, size_t module_id) const {
assert(valid_chan_type(chan_type));
if (CHANX == chan_type) {
if ( (size_t(-1) < module_id) && (module_id < chanx_modules_.size()) ) {
return true;
}
} else if (CHANY == chan_type) {
if ( (size_t(-1) < module_id) && (module_id < chany_modules_.size()) ) {
return true;
}
}
return false;
}

View File

@ -0,0 +1,74 @@
/* IMPORTANT:
* The following preprocessing flags are added to
* avoid compilation error when this headers are included in more than 1 times
*/
#ifndef RR_CHAN_H
#define RR_CHAN_H
/*
* Notes in include header files in a head file
* Only include the neccessary header files
* that is required by the data types in the function/class declarations!
*/
/* Header files should be included in a sequence */
/* Standard header files required go first */
#include <vector>
#include "vpr_types.h"
/* RRChan coordinator class */
/* Object of a channel in a routing resource graph */
class RRChan {
public: /* Accessors */
t_rr_type get_type() const;
size_t get_chan_width() const; /* get the number of tracks in this channel */
int get_node_track_id(t_rr_node* node) const; /* get the track_id of a node */
t_rr_node* get_node(size_t track_num) const; /* get the rr_node with the track_id */
int get_node_segment(t_rr_node* node) const;
int get_node_segment(size_t track_num) const;
bool is_mirror(RRChan& cand) const; /* evaluate if two RR_chan is mirror to each other */
public: /* Mutators */
void set_type(t_rr_type type); /* modify type */
void add_node(t_rr_node* node, size_t node_segment); /* add a node to the array */
void clear(); /* clear the content */
private: /* internal functions */
bool valid_type(t_rr_type type) const;
bool valid_node_id(size_t node_id) const;
private: /* Internal Data */
t_rr_type type_; /* channel type: CHANX or CHANY */
std::vector<t_rr_node*> nodes_; /* rr nodes of each track in the channel */
std::vector<size_t> node_segments_; /* segment of each track */
};
/* Object including all the RR channels in a device,
* 1. the RR channels will be in an 2D array
* 2. Unique Module Name for each channel
* 3. Instance name for each channel
* 4. Detailed internal structure of each channel
* Considering RR channels may share the same structure
* To be memory efficient, we build a list of unique structures
* and link each RR channel to
*/
class DeviceRRChan {
public: /* Accessors */
RRChan get_module(t_rr_type chan_type, size_t module_id) const;
public: /* Mutators */
void init_module_ids(size_t device_height, size_t device_width);
void add_one_chan_module(t_rr_type chan_type, size_t x, size_t y, RRChan rr_chan); /* Add a new unique module of RRChan*/
void clear();
private: /* internal functions */
void clear_chan(t_rr_type chan_type);
void init_chan_module_ids(t_rr_type chan_type, size_t device_width, size_t device_height);
bool valid_chan_type(t_rr_type chan_type) const;
bool valid_coordinator(t_rr_type chan_type, size_t x, size_t y) const;
bool valid_module_id(t_rr_type chan_type, size_t module_id) const;
private: /* Internal Data */
std::vector< std::vector<size_t> > chanx_module_ids_; /* Module id in modules_ for each X-direction rr_channel */
std::vector< std::vector<size_t> > chany_module_ids_; /* Module id in modules_ for each Y-direction rr_channel */
std::vector<RRChan> chanx_modules_; /* Detailed internal structure of each unique module */
std::vector<RRChan> chany_modules_; /* Detailed internal structure of each unique module */
};
#endif

View File

@ -31,6 +31,7 @@ boolean shell_setup_fpga_x2p_setup(t_shell_env* env, t_opt_info* opts) {
env->vpr_setup.FPGA_SPICE_Opts.rename_illegal_port = is_opt_set(opts, "rename_illegal_port", FALSE);
env->vpr_setup.FPGA_SPICE_Opts.signal_density_weight = get_opt_float_val(opts, "signal_density_weight", 1.);
env->vpr_setup.FPGA_SPICE_Opts.sim_window_size = get_opt_float_val(opts, "sim_window_size", 0.5);
env->vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy = is_opt_set(opts, "compact_routing_hierarchy", FALSE);
return TRUE;
}

View File

@ -6,6 +6,7 @@ t_opt_info fpga_x2p_setup_opts[] = {
{"rename_illegal_port", "-rip,--rename_illegal_port", 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Rename illegal ports that violates Verilog syntax"},
{"signal_density_weight", "-sdw,--signal_density_weight", 0, OPT_WITHVAL, OPT_FLOAT, OPT_OPT, OPT_NONDEF, "Specify the signal density weight when doing the average number"},
{"sim_window_size", "-sws,--sim_window_size", 0, OPT_WITHVAL, OPT_FLOAT, OPT_OPT, OPT_NONDEF, "Specify the size of window when doing simulation"},
{"compact_routing_hierarchy", "-crh,--compact_routing_hierarchy", 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Specify if use a compact routing hierarchy in SPIC/Verilog generation"},
{HELP_OPT_TAG, HELP_OPT_NAME, 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Launch help desk"},
{LAST_OPT_TAG, LAST_OPT_NAME, 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Launch help desk"}
};

View File

@ -10,7 +10,7 @@ t_shell_cmd shell_cmd[] = {
{"fpga_bitstream", PRODUCTION_CMD, fpga_bitstream_opts, &shell_execute_fpga_bitstream },
{"help", BASIC_CMD, help_opts, &shell_execute_help },
{"exit", BASIC_CMD, exit_opts, &shell_execute_exit },
{"quit", BASIC_CMD, NULL, &shell_execute_exit },
{"quit", BASIC_CMD, exit_opts, &shell_execute_exit },
{LAST_CMD_NAME, BASIC_CMD, NULL, NULL}
};

View File

@ -281,7 +281,7 @@ void vpr_fpga_spice(t_vpr_setup vpr_setup,
spice_print_headers(include_dir_path, vpr_crit_path_delay, num_clocks, *(Arch.spice));
/* Generate sub circuits: Inverter, Buffer, Transmission Gate, LUT, DFF, SRAM, MUX*/
generate_spice_subckts(subckt_dir_path, &Arch ,&vpr_setup.RoutingArch);
generate_spice_subckts(subckt_dir_path, &Arch ,&vpr_setup.RoutingArch, vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
/* Print MUX testbench if needed */
if (vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_print_pb_mux_testbench) {

View File

@ -632,7 +632,8 @@ void fprint_switch_box_interc(FILE* fp,
void fprint_routing_switch_box_subckt(char* subckt_dir,
t_sb cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy) {
int itrack, inode, side, ix, iy, x, y;
FILE* fp = NULL;
char* fname = NULL;
@ -998,7 +999,9 @@ void fprint_connection_box_interc(FILE* fp,
void fprint_routing_connection_box_subckt(char* subckt_dir,
t_cb cur_cb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy) {
int itrack, inode, side, x, y;
int side_cnt = 0;
FILE* fp = NULL;
@ -1170,7 +1173,8 @@ void generate_spice_routing_resources(char* subckt_dir,
t_arch arch,
t_det_routing_arch* routing_arch,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices) {
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy) {
int ix, iy;
assert(UNI_DIRECTIONAL == routing_arch->directionality);
@ -1218,7 +1222,8 @@ void generate_spice_routing_resources(char* subckt_dir,
for (iy = 0; iy < (ny + 1); iy++) {
update_spice_models_routing_index_low(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
fprint_routing_switch_box_subckt(subckt_dir, sb_info[ix][iy],
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
compact_routing_hierarchy);
update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
}
}
@ -1233,7 +1238,8 @@ void generate_spice_routing_resources(char* subckt_dir,
if ((TRUE == is_cb_exist(CHANX, ix, iy))
&&(0 < count_cb_info_num_ipin_rr_nodes(cbx_info[ix][iy]))) {
fprint_routing_connection_box_subckt(subckt_dir, cbx_info[ix][iy],
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
compact_routing_hierarchy);
}
update_spice_models_routing_index_high(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models);
}
@ -1246,7 +1252,8 @@ void generate_spice_routing_resources(char* subckt_dir,
if ((TRUE == is_cb_exist(CHANY, ix, iy))
&&(0 < count_cb_info_num_ipin_rr_nodes(cby_info[ix][iy]))) {
fprint_routing_connection_box_subckt(subckt_dir, cby_info[ix][iy],
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
compact_routing_hierarchy);
}
update_spice_models_routing_index_high(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models);
}

View File

@ -43,7 +43,8 @@ void fprint_switch_box_interc(FILE* fp,
void fprint_routing_switch_box_subckt(FILE* fp, t_sb cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy);
void fprint_connection_box_short_interc(FILE* fp,
t_cb cur_cb_info,
@ -59,11 +60,13 @@ void fprint_connection_box_interc(FILE* fp,
void fprint_routing_connection_box_subckt(FILE* fp, t_cb cur_cb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy);
void generate_spice_routing_resources(char* subckt_dir,
t_arch arch,
t_det_routing_arch* routing_arch,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices);
t_ivec*** LL_rr_node_indices,
boolean compact_routing_hierarchy);

View File

@ -706,7 +706,8 @@ void generate_spice_wires(char* subckt_dir,
*/
void generate_spice_subckts(char* subckt_dir,
t_arch* arch,
t_det_routing_arch* routing_arch) {
t_det_routing_arch* routing_arch,
boolean compact_routing_hierarchy) {
/* 1.Generate NMOS, PMOS and transmission gate */
vpr_printf(TIO_MESSAGE_INFO,"Writing SPICE NMOS and PMOS...\n");
generate_spice_nmos_pmos(subckt_dir, arch->spice->tech_lib);
@ -736,7 +737,8 @@ void generate_spice_subckts(char* subckt_dir,
/* 6. Generate Routing architecture*/
vpr_printf(TIO_MESSAGE_INFO, "Writing Routing Resources....\n");
generate_spice_routing_resources(subckt_dir, (*arch), routing_arch,
num_rr_nodes, rr_node, rr_node_indices);
num_rr_nodes, rr_node, rr_node_indices,
compact_routing_hierarchy);
/* 7. Generate Logic Blocks */
vpr_printf(TIO_MESSAGE_INFO,"Writing Logic Blocks...\n");

View File

@ -10,4 +10,5 @@ void generate_spice_subckt_tapbuf(FILE* fp,
void generate_spice_subckts(char* subckt_dir,
t_arch* arch,
t_det_routing_arch* routing_arch);
t_det_routing_arch* routing_arch,
boolean compact_routing_hierarchy);

View File

@ -253,7 +253,7 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
/* Dump routing resources: switch blocks, connection blocks and channel tracks */
dump_verilog_routing_resources(sram_verilog_orgz_info, src_dir_path, rr_dir_path, Arch, &vpr_setup.RoutingArch,
num_rr_nodes, rr_node, rr_node_indices, rr_indexed_data,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
/* Dump logic blocks
* Branches to go:
@ -274,6 +274,7 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
num_rr_nodes, rr_node, rr_node_indices,
num_clocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy,
*(Arch.spice));
/* Dump SDC constraints */

View File

@ -272,7 +272,7 @@ void dump_verilog_timeout_and_vcd(FILE * fp,
fprintf(fp, " // Begin Icarus requirement\n");
fprintf(fp, "`ifdef %s\n", icarus_simulator_flag);
fprintf(fp, " initial begin\n");
fprintf(fp, " $dumpfile(%s_autochecked.vcd);\n", circuit_name);
fprintf(fp, " $dumpfile(\"%s_autochecked.vcd\");\n", circuit_name);
fprintf(fp, " $dumpvars(1, %s%s);\n", circuit_name,
modelsim_autocheck_testbench_module_postfix);
fprintf(fp, " end\n\n");

View File

@ -35,6 +35,7 @@
#include "verilog_utils.h"
#include "verilog_primitives.h"
#include "verilog_pbtypes.h"
#include "verilog_routing.h"
#include "verilog_top_netlist_utils.h"
/* ONLY for compact Verilog netlists:
@ -739,6 +740,311 @@ void dump_compact_verilog_defined_grids(t_sram_orgz_info* cur_sram_orgz_info,
return;
}
/* Call the defined switch box sub-circuit
* TODO: This function is also copied from
* spice_routing.c : dump_verilog_routing_switch_box_subckt
*/
static
void dump_compact_verilog_defined_one_switch_box(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
t_sb cur_sb_info) {
int ix, iy, side, itrack, x, y, inode;
/* 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 > cur_sb_info.x))&&(!(cur_sb_info.x > (nx + 1))));
assert((!(0 > cur_sb_info.y))&&(!(cur_sb_info.y > (ny + 1))));
x = cur_sb_info.x;
y = cur_sb_info.y;
/* Comment lines */
fprintf(fp, "//----- BEGIN call module Switch blocks [%d][%d] -----\n",
cur_sb_info.x, cur_sb_info.y);
/* Print module*/
/* If we have an mirror SB, we should the module name of the mirror !!! */
if (NULL != cur_sb_info.mirror) {
fprintf(fp, "%s ", gen_verilog_one_sb_module_name(cur_sb_info.mirror));
} else {
fprintf(fp, "%s ", gen_verilog_one_sb_module_name(&cur_sb_info));
}
fprintf(fp, "%s ", gen_verilog_one_sb_instance_name(&cur_sb_info));
fprintf(fp, "(");
fprintf(fp, "\n");
/* dump global ports */
if (0 < dump_verilog_global_ports(fp, global_ports_head, FALSE)) {
fprintf(fp, ",\n");
}
for (side = 0; side < cur_sb_info.num_sides; side++) {
determine_sb_port_coordinator(cur_sb_info, side, &ix, &iy);
fprintf(fp, "//----- %s side channel ports-----\n", convert_side_index_to_string(side));
for (itrack = 0; itrack < cur_sb_info.chan_width[side]; itrack++) {
fprintf(fp, "%s,\n",
gen_verilog_routing_channel_one_pin_name(cur_sb_info.chan_rr_node[side][itrack],
ix, iy, itrack,
cur_sb_info.chan_rr_node_direction[side][itrack]));
}
fprintf(fp, "//----- %s side inputs: CLB output pins -----\n", convert_side_index_to_string(side));
/* Dump OPINs of adjacent CLBs */
for (inode = 0; inode < cur_sb_info.num_opin_rr_nodes[side]; inode++) {
dump_verilog_grid_side_pin_with_given_index(fp, IPIN,
cur_sb_info.opin_rr_node[side][inode]->ptc_num,
cur_sb_info.opin_rr_node_grid_side[side][inode],
cur_sb_info.opin_rr_node[side][inode]->xlow,
cur_sb_info.opin_rr_node[side][inode]->ylow,
FALSE); /* Do not specify the direction of port */
fprintf(fp, ", ");
}
fprintf(fp, "\n");
}
/* Configuration ports */
/* output of each configuration bit */
/* Reserved sram ports */
if (0 < (cur_sb_info.num_reserved_conf_bits)) {
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
0, cur_sb_info.num_reserved_conf_bits - 1,
VERILOG_PORT_CONKT);
fprintf(fp, ",\n");
}
/* Normal sram ports */
if (0 < (cur_sb_info.conf_bits_msb - cur_sb_info.conf_bits_lsb)) {
dump_verilog_sram_local_ports(fp, cur_sram_orgz_info,
cur_sb_info.conf_bits_lsb,
cur_sb_info.conf_bits_msb - 1,
VERILOG_PORT_CONKT);
}
/* Dump ports only visible during formal verification*/
if (0 < (cur_sb_info.conf_bits_msb - 1 - cur_sb_info.conf_bits_lsb)) {
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,
cur_sb_info.conf_bits_lsb,
cur_sb_info.conf_bits_msb - 1,
VERILOG_PORT_CONKT);
fprintf(fp, "\n");
fprintf(fp, "`endif\n");
}
fprintf(fp, ");\n");
/* Comment lines */
fprintf(fp, "//----- END call module Switch blocks [%d][%d] -----\n\n", x, y);
/* Free */
return;
}
void dump_compact_verilog_defined_switch_boxes(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp) {
int ix, iy;
/* Check the file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
__FILE__, __LINE__);
exit(1);
}
for (ix = 0; ix < (nx + 1); ix++) {
for (iy = 0; iy < (ny + 1); iy++) {
dump_compact_verilog_defined_one_switch_box(cur_sram_orgz_info, fp, sb_info[ix][iy]);
}
}
return;
}
/* Call the defined sub-circuit of connection box
* TODO: actually most of this function is copied from
* spice_routing.c : dump_verilog_conneciton_box_interc
* Should be more clever to use the original function
*/
static
void dump_compact_verilog_defined_one_connection_box(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
t_cb cur_cb_info) {
int itrack, inode, side, x, y;
int side_cnt = 0;
/* 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 > cur_cb_info.x))&&(!(cur_cb_info.x > (nx + 1))));
assert((!(0 > cur_cb_info.y))&&(!(cur_cb_info.y > (ny + 1))));
x = cur_cb_info.x;
y = cur_cb_info.y;
/* Comment lines */
fprintf(fp,
"//----- BEGIN Call Connection Box for %s direction [%d][%d] module -----\n",
convert_chan_type_to_string(cur_cb_info.type),
x, y);
/* Print module */
/* If we have an mirror SB, we should the module name of the mirror !!! */
if (NULL != cur_cb_info.mirror) {
fprintf(fp, "%s ", gen_verilog_one_cb_module_name(cur_cb_info.mirror));
} else {
fprintf(fp, "%s ", gen_verilog_one_cb_module_name(&cur_cb_info));
}
fprintf(fp, "%s ", gen_verilog_one_cb_instance_name(&cur_cb_info));
fprintf(fp, "(");
fprintf(fp, "\n");
/* dump global ports */
if (0 < dump_verilog_global_ports(fp, global_ports_head, FALSE)) {
fprintf(fp, ",\n");
}
/* Print the ports of channels*/
/* connect to the mid point of a track*/
side_cnt = 0;
for (side = 0; side < cur_cb_info.num_sides; side++) {
/* Bypass side with zero channel width */
if (0 == cur_cb_info.chan_width[side]) {
continue;
}
assert (0 < cur_cb_info.chan_width[side]);
side_cnt++;
fprintf(fp, "//----- %s side inputs: channel track middle outputs -----\n", convert_side_index_to_string(side));
for (itrack = 0; itrack < cur_cb_info.chan_width[side]; itrack++) {
fprintf(fp, "%s, ",
gen_verilog_routing_channel_one_midout_name(&cur_cb_info, itrack));
fprintf(fp, "\n");
}
}
/*check side_cnt */
assert(1 == side_cnt);
side_cnt = 0;
/* Print the ports of grids*/
for (side = 0; side < cur_cb_info.num_sides; side++) {
/* Bypass side with zero IPINs*/
if (0 == cur_cb_info.num_ipin_rr_nodes[side]) {
continue;
}
side_cnt++;
assert(0 < cur_cb_info.num_ipin_rr_nodes[side]);
assert(NULL != cur_cb_info.ipin_rr_node[side]);
fprintf(fp, "//----- %s side outputs: CLB input pins -----\n", convert_side_index_to_string(side));
for (inode = 0; inode < cur_cb_info.num_ipin_rr_nodes[side]; inode++) {
/* Print each INPUT Pins of a grid */
dump_verilog_grid_side_pin_with_given_index(fp, OPIN,
cur_cb_info.ipin_rr_node[side][inode]->ptc_num,
cur_cb_info.ipin_rr_node_grid_side[side][inode],
cur_cb_info.ipin_rr_node[side][inode]->xlow,
cur_cb_info.ipin_rr_node[side][inode]->ylow,
FALSE); /* Do not specify direction of port */
fprintf(fp, ", \n");
}
}
/* Make sure only 2 sides of IPINs are printed */
assert((1 == side_cnt)||(2 == side_cnt));
/* Configuration ports */
/* Reserved sram ports */
if (0 < (cur_cb_info.num_reserved_conf_bits)) {
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
0, cur_cb_info.num_reserved_conf_bits - 1,
VERILOG_PORT_CONKT);
fprintf(fp, ",\n");
}
/* Normal sram ports */
if (0 < (cur_cb_info.conf_bits_msb - cur_cb_info.conf_bits_lsb)) {
dump_verilog_sram_local_ports(fp, cur_sram_orgz_info,
cur_cb_info.conf_bits_lsb, cur_cb_info.conf_bits_msb - 1,
VERILOG_PORT_CONKT);
}
/* Dump ports only visible during formal verification*/
if (0 < (cur_cb_info.conf_bits_msb - 1 - cur_cb_info.conf_bits_lsb)) {
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,
cur_cb_info.conf_bits_lsb,
cur_cb_info.conf_bits_msb - 1,
VERILOG_PORT_CONKT);
fprintf(fp, "\n");
fprintf(fp, "`endif\n");
}
fprintf(fp, ");\n");
/* Comment lines */
switch(cur_cb_info.type) {
case CHANX:
fprintf(fp, "//----- END call Connection Box-X direction [%d][%d] module -----\n\n", x, y);
break;
case CHANY:
fprintf(fp, "//----- END call Connection Box-Y direction [%d][%d] module -----\n\n", x, y);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid type of channel!\n", __FILE__, __LINE__);
exit(1);
}
/* Check */
assert((1 == side_cnt)||(2 == side_cnt));
return;
}
/* Call the sub-circuits for connection boxes */
void dump_compact_verilog_defined_connection_boxes(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp) {
int ix, iy;
/* Check the file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* X - channels [1...nx][0..ny]*/
for (iy = 0; iy < (ny + 1); iy++) {
for (ix = 1; ix < (nx + 1); ix++) {
if ((TRUE == is_cb_exist(CHANX, ix, iy))
&&(0 < count_cb_info_num_ipin_rr_nodes(cbx_info[ix][iy]))) {
dump_compact_verilog_defined_one_connection_box(cur_sram_orgz_info, fp, cbx_info[ix][iy]);
}
}
}
/* Y - channels [1...ny][0..nx]*/
for (ix = 0; ix < (nx + 1); ix++) {
for (iy = 1; iy < (ny + 1); iy++) {
if ((TRUE == is_cb_exist(CHANY, ix, iy))
&&(0 < count_cb_info_num_ipin_rr_nodes(cby_info[ix][iy]))) {
dump_compact_verilog_defined_one_connection_box(cur_sram_orgz_info, fp, cby_info[ix][iy]);
}
}
}
return;
}
/** Print Top-level SPICE netlist in a compact way
* Instance unique submodules (I/O, CLB, Heterogeneous block) for the full grids
*/
@ -754,6 +1060,7 @@ void dump_compact_verilog_top_netlist(t_sram_orgz_info* cur_sram_orgz_info,
t_ivec*** LL_rr_node_indices,
int num_clock,
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy,
t_spice verilog) {
FILE* fp = NULL;
char* formatted_dir_path = NULL;
@ -809,10 +1116,18 @@ void dump_compact_verilog_top_netlist(t_sram_orgz_info* cur_sram_orgz_info,
dump_verilog_defined_channels(fp, LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices);
/* Quote Routing structures: Switch Boxes */
dump_verilog_defined_switch_boxes(cur_sram_orgz_info, fp);
if (TRUE == compact_routing_hierarchy ) {
dump_compact_verilog_defined_switch_boxes(cur_sram_orgz_info, fp);
} else {
dump_verilog_defined_switch_boxes(cur_sram_orgz_info, fp);
}
/* Quote Routing structures: Connection Boxes */
dump_verilog_defined_connection_boxes(cur_sram_orgz_info, fp);
if (TRUE == compact_routing_hierarchy ) {
dump_compact_verilog_defined_connection_boxes(cur_sram_orgz_info, fp);
} else {
dump_verilog_defined_connection_boxes(cur_sram_orgz_info, fp);
}
/* Quote defined Logic blocks subckts (Grids) */
dump_compact_verilog_defined_grids(cur_sram_orgz_info, fp);

View File

@ -24,5 +24,6 @@ void dump_compact_verilog_top_netlist(t_sram_orgz_info* cur_sram_orgz_info,
t_ivec*** LL_rr_node_indices,
int num_clock,
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy,
t_spice verilog);

View File

@ -186,9 +186,9 @@ void dump_verilog_timeout_and_vcd(FILE * fp,
fprintf(fp, " // Begin Icarus requirement\n");
fprintf(fp, "`ifdef %s\n", icarus_simulator_flag);
fprintf(fp, " initial begin\n");
fprintf(fp, " $dumpfile(%s_autochecked.vcd);\n", circuit_name);
fprintf(fp, " $dumpfile(\"%s_formal.vcd\");\n", circuit_name);
fprintf(fp, " $dumpvars(1, %s%s);\n", circuit_name,
modelsim_autocheck_testbench_module_postfix);
formal_random_top_tb_postfix);
fprintf(fp, " end\n\n");
fprintf(fp, " initial begin\n");
fprintf(fp, " $display(\"Simulation start\");\n");

View File

@ -1107,7 +1107,8 @@ void dump_verilog_routing_switch_box_subckt(t_sram_orgz_info* cur_sram_orgz_info
t_sb* cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_syn_verilog_opts fpga_verilog_opts) {
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy) {
int itrack, inode, side, ix, iy, x, y;
int cur_num_sram, num_conf_bits, num_reserved_conf_bits, esti_sram_cnt;
FILE* fp = NULL;
@ -1131,6 +1132,20 @@ void dump_verilog_routing_switch_box_subckt(t_sram_orgz_info* cur_sram_orgz_info
cur_sb_info->num_reserved_conf_bits = num_reserved_conf_bits;
cur_sb_info->conf_bits_lsb = cur_num_sram;
cur_sb_info->conf_bits_msb = cur_num_sram + num_conf_bits;
/* Handle mirror switch blocks:
* For mirrors, no need to output a file
* Just update the counter
*/
if ( (TRUE == compact_routing_hierarchy)
&& (NULL != cur_sb_info->mirror) ) {
/* Again ensure the conf_bits should match !!! */
/* Count the number of configuration bits of the mirror */
int mirror_num_conf_bits = count_verilog_switch_box_conf_bits(cur_sram_orgz_info, cur_sb_info->mirror);
assert( mirror_num_conf_bits == num_conf_bits );
/* return directly */
return;
}
/* Create file handler */
fp = verilog_create_one_subckt_file(subckt_dir, "Switch Block ", sb_verilog_file_name_prefix, cur_sb_info->x, cur_sb_info->y, &fname);
@ -1755,7 +1770,8 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
t_cb* cur_cb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_syn_verilog_opts fpga_verilog_opts) {
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy) {
int itrack, inode, side, x, y;
int side_cnt = 0;
FILE* fp = NULL;
@ -1768,7 +1784,34 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
x= cur_cb_info->x;
y= cur_cb_info->y;
/* Count the number of configuration bits */
/* Count the number of configuration bits to be consumed by this Switch block */
num_conf_bits = count_verilog_connection_box_conf_bits(cur_sram_orgz_info, cur_cb_info);
/* Count the number of reserved configuration bits to be consumed by this Switch block */
num_reserved_conf_bits = count_verilog_connection_box_reserved_conf_bits(cur_sram_orgz_info, cur_cb_info);
/* Estimate the sram_verilog_model->cnt */
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
esti_sram_cnt = cur_num_sram + num_conf_bits;
/* Record index */
cur_cb_info->num_reserved_conf_bits = num_reserved_conf_bits;
cur_cb_info->conf_bits_lsb = cur_num_sram;
cur_cb_info->conf_bits_msb = cur_num_sram + num_conf_bits;
/* Handle mirror switch blocks:
* For mirrors, no need to output a file
* Just update the counter
*/
if ( (TRUE == compact_routing_hierarchy)
&& (NULL != cur_cb_info->mirror) ) {
/* Again ensure the conf_bits should match !!! */
/* Count the number of configuration bits of the mirror */
int mirror_num_conf_bits = count_verilog_connection_box_conf_bits(cur_sram_orgz_info, cur_cb_info->mirror);
assert( mirror_num_conf_bits == num_conf_bits );
/* return directly */
return;
}
/* Print the definition of subckt*/
/* Identify the type of connection box */
switch(cur_cb_info->type) {
@ -1850,18 +1893,6 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
/* Make sure only 2 sides of IPINs are printed */
assert((1 == side_cnt)||(2 == side_cnt));
/* Count the number of configuration bits */
/* Count the number of configuration bits to be consumed by this Switch block */
num_conf_bits = count_verilog_connection_box_conf_bits(cur_sram_orgz_info, cur_cb_info);
/* Count the number of reserved configuration bits to be consumed by this Switch block */
num_reserved_conf_bits = count_verilog_connection_box_reserved_conf_bits(cur_sram_orgz_info, cur_cb_info);
/* Estimate the sram_verilog_model->cnt */
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
esti_sram_cnt = cur_num_sram + num_conf_bits;
/* Record index */
cur_cb_info->num_reserved_conf_bits = num_reserved_conf_bits;
cur_cb_info->conf_bits_lsb = cur_num_sram;
cur_cb_info->conf_bits_msb = cur_num_sram + num_conf_bits;
/* Put down configuration port */
/* output of each configuration bit */
@ -1956,7 +1987,8 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_rr_indexed_data* LL_rr_indexed_data,
t_syn_verilog_opts fpga_verilog_opts) {
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy) {
int ix, iy;
assert(UNI_DIRECTIONAL == routing_arch->directionality);
@ -2005,7 +2037,7 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
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);
fpga_verilog_opts, compact_routing_hierarchy);
update_spice_models_routing_index_high(ix, iy, SOURCE, arch.spice->num_spice_model, arch.spice->spice_models);
}
}
@ -2020,7 +2052,7 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
&&(0 < count_cb_info_num_ipin_rr_nodes(cbx_info[ix][iy]))) {
dump_verilog_routing_connection_box_subckt(cur_sram_orgz_info, verilog_dir, subckt_dir, &(cbx_info[ix][iy]),
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
fpga_verilog_opts);
fpga_verilog_opts, compact_routing_hierarchy);
}
update_spice_models_routing_index_high(ix, iy, CHANX, arch.spice->num_spice_model, arch.spice->spice_models);
}
@ -2034,7 +2066,7 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
&&(0 < count_cb_info_num_ipin_rr_nodes(cby_info[ix][iy]))) {
dump_verilog_routing_connection_box_subckt(cur_sram_orgz_info, verilog_dir, subckt_dir, &(cby_info[ix][iy]),
LL_num_rr_nodes, LL_rr_node, LL_rr_node_indices,
fpga_verilog_opts);
fpga_verilog_opts, compact_routing_hierarchy);
}
update_spice_models_routing_index_high(ix, iy, CHANY, arch.spice->num_spice_model, arch.spice->spice_models);
}

View File

@ -67,7 +67,8 @@ void dump_verilog_routing_switch_box_subckt(t_sram_orgz_info* cur_sram_orgz_info
t_sb* cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_syn_verilog_opts fpga_verilog_opts);
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy);
void dump_verilog_connection_box_short_interc(t_sram_orgz_info* cur_sram_orgz_info,
@ -111,7 +112,8 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
t_cb* cur_cb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_syn_verilog_opts fpga_verilog_opts);
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy);
void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
@ -122,5 +124,6 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_rr_indexed_data* LL_rr_indexed_data,
t_syn_verilog_opts fpga_verilog_opts);
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy);

File diff suppressed because it is too large Load Diff

View File

@ -8,12 +8,12 @@ input [0:0] cin, // Input cin
output [0:0] cout, // Output carry
output [0:0] sumout // Output sum
);
wire[1:0] int_calc;
//wire[1:0] int_calc;
assign int_calc = a + b + cin;
assign cout = int_calc[1];
assign sumout = int_calc[0];
// assign sumout = a ^ b ^ cin;
// assign cout = a & b + a & cin + b & cin;
//assign int_calc = a + b + cin;
//assign cout = int_calc[1];
//assign sumout = int_calc[0];
assign sumout = a ^ b ^ cin;
assign cout = (a & b) | (a & cin) | (b & cin);
endmodule

View File

@ -2,7 +2,7 @@
//------ Verilog file: io.v -----//
//------ Author: Xifan TANG -----//
module iopad(
input zin, // Set output to be Z
//input zin, // Set output to be Z
input dout, // Data output
output din, // Data input
inout pad, // bi-directional pad

View File

@ -3,13 +3,14 @@
# Set variables
# For FPGA-Verilog ONLY
set verilog_output_dirname = OpenFPGA_Branch
set verilog_output_dirpath = /var/tmp/AA_simu/
set benchmark = s298_prevpr
set verilog_output_dirname = ${benchmark}_Verilog
set verilog_output_dirpath = $PWD
set modelsim_ini_file = /uusoc/facility/cad_tools/Mentor/modelsim10.7b/modeltech/modelsim.ini
# VPR critical inputs
#set arch_xml_file = ARCH/k6_N10_MD_tsmc40nm_chain_TT.xml
#set arch_xml_file = ARCH/k8_N10_SC_tsmc40nm_chain_TT_stratixIV_lookalike.xml
set arch_xml_file = ARCH/k8_N10_sram_chain_FC_tsmc40_stratix4_auto.xml
set arch_xml_file = ARCH/k6_N10_sram_chain_HC_template.xml
#set arch_xml_file = ARCH/ed_stdcell.xml
#set arch_xml_file = ARCH/k6_N10_sram_chain_FC_tsmc40.xml
#set arch_xml_file = ARCH/k6_N10_SC_tsmc40nm_chain_TT.xml
@ -18,9 +19,9 @@ set arch_xml_file = ARCH/k8_N10_sram_chain_FC_tsmc40_stratix4_auto.xml
#set verilog_reference = ${PWD}/Circuits/alu4_K6_N10_ace.v
#set blif_file = Circuits/shiftReg.blif
#set act_file = Circuits/shiftReg.act
set blif_file = Circuits/s298_prevpr.blif
set act_file = Circuits/s298_prevpr.act
set verilog_reference = ${PWD}/Circuits/s298_prevpr.v
set blif_file = Circuits/$benchmark.blif
set act_file = Circuits/$benchmark.act
set verilog_reference = ${PWD}/Circuits/$benchmark.v
#set blif_file = Circuits/frisc.blif
#set act_file = Circuits/frisc.act
#set blif_file = Circuits/elliptic.blif
@ -36,7 +37,7 @@ rm -rf $verilog_output_dirpath/$verilog_output_dirname
# Run VPR
#valgrind
./vpr $arch_xml_file $blif_file --full_stats --nodisp --activity_file $act_file --fpga_verilog --fpga_verilog_dir $verilog_output_dirpath/$verilog_output_dirname --fpga_x2p_rename_illegal_port --fpga_bitstream_generator --fpga_verilog_print_top_testbench --fpga_verilog_print_input_blif_testbench --fpga_verilog_include_timing --fpga_verilog_include_signal_init --fpga_verilog_print_modelsim_autodeck $modelsim_ini_file --fpga_verilog_print_formal_verification_top_netlist --fpga_verilog_print_autocheck_top_testbench $verilog_reference --fpga_verilog_print_user_defined_template --route_chan_width $vpr_route_chan_width --fpga_verilog_print_sdc_pnr --fpga_verilog_print_sdc_analysis #--fpga_verilog_print_report_timing_tcl
echo "./vpr $arch_xml_file $blif_file --full_stats --nodisp --activity_file $act_file --fpga_verilog --fpga_verilog_dir $verilog_output_dirpath/$verilog_output_dirname --fpga_x2p_rename_illegal_port --fpga_bitstream_generator --fpga_verilog_print_top_testbench --fpga_verilog_print_input_blif_testbench --fpga_verilog_include_timing --fpga_verilog_include_signal_init --fpga_verilog_print_modelsim_autodeck $modelsim_ini_file --fpga_verilog_print_formal_verification_top_netlist --fpga_verilog_print_autocheck_top_testbench $verilog_reference --fpga_verilog_print_user_defined_template --route_chan_width $vpr_route_chan_width --fpga_x2p_compact_routing_hierarchy #--fpga_verilog_print_sdc_pnr --fpga_verilog_print_sdc_analysis --fpga_verilog_print_report_timing_tcl "