Merge branch 'multimode_clb' of https://github.com/LNIS-Projects/OpenFPGA into multimode_clb
This commit is contained in:
commit
b48a27acf0
|
@ -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")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
*/
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"}
|
||||
};
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue