remove legacy codes in FPGA-Verilog: routing block generation
This commit is contained in:
parent
95ea513339
commit
a176c253ee
|
@ -1,751 +0,0 @@
|
||||||
/***********************************/
|
|
||||||
/* Synthesizable Verilog Dumping */
|
|
||||||
/* 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.h"
|
|
||||||
#include "vpr_utils.h"
|
|
||||||
#include "path_delay.h"
|
|
||||||
#include "stats.h"
|
|
||||||
|
|
||||||
/* Include FPGA-SPICE utils */
|
|
||||||
#include "linkedlist.h"
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
#include "fpga_x2p_bitstream_utils.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
|
|
||||||
/* Include verilog utils */
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
|
|
||||||
#include "verilog_decoder.h"
|
|
||||||
|
|
||||||
/***** Subroutines *****/
|
|
||||||
void dump_verilog_decoder_memory_bank_ports(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
enum e_dump_verilog_port_type dump_port_type) {
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
int num_array_bl, num_array_wl;
|
|
||||||
int bl_decoder_size, wl_decoder_size;
|
|
||||||
char split_sign;
|
|
||||||
|
|
||||||
split_sign = determine_verilog_generic_port_split_sign(dump_port_type);
|
|
||||||
|
|
||||||
/* Only accept two types of dump_port_type here! */
|
|
||||||
assert((VERILOG_PORT_INPUT == dump_port_type)||(VERILOG_PORT_CONKT == dump_port_type));
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert (cur_sram_orgz_info->type == SPICE_SRAM_MEMORY_BANK);
|
|
||||||
|
|
||||||
/* A valid file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Depending on the memory technology*/
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
assert(NULL != mem_model);
|
|
||||||
|
|
||||||
determine_blwl_decoder_size(cur_sram_orgz_info,
|
|
||||||
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
|
|
||||||
|
|
||||||
/* Depend on the memory technology */
|
|
||||||
switch (mem_model->design_tech) {
|
|
||||||
case SPICE_MODEL_DESIGN_CMOS:
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_bl_enable_port_name, 0, 0);
|
|
||||||
fprintf(fp, "%c //--- BL enable port \n", split_sign);
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_wl_enable_port_name, 0, 0);
|
|
||||||
fprintf(fp, "%c //--- WL enable port \n", split_sign);
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_bl_data_in_port_name, 0, 0);
|
|
||||||
fprintf(fp, "%c //--- BL data input port \n", split_sign);
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_DESIGN_RRAM:
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_bl_enable_port_name, 0, 0);
|
|
||||||
fprintf(fp, "%c //--- BL enable port \n", split_sign);
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_wl_enable_port_name, 0, 0);
|
|
||||||
fprintf(fp, "%c //--- WL enable port \n", split_sign);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_addr_bl_port_name, bl_decoder_size - 1, 0);
|
|
||||||
fprintf(fp, "%c //--- Address of bit lines \n", split_sign);
|
|
||||||
dump_verilog_generic_port(fp, dump_port_type,
|
|
||||||
top_netlist_addr_wl_port_name, wl_decoder_size - 1, 0);
|
|
||||||
fprintf(fp, " //--- Address of word lines \n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_decoder(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info) {
|
|
||||||
int num_array_bl, num_array_wl;
|
|
||||||
int bl_decoder_size, wl_decoder_size;
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
boolean bl_inverted = FALSE;
|
|
||||||
boolean wl_inverted = FALSE;
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert(SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type);
|
|
||||||
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid file handler!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get number of BLs,WLs and decoder sizes */
|
|
||||||
determine_blwl_decoder_size(cur_sram_orgz_info,
|
|
||||||
&num_array_bl, &num_array_wl,
|
|
||||||
&bl_decoder_size, &wl_decoder_size);
|
|
||||||
|
|
||||||
/* Different design technology requires different BL decoder logic */
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
/* Find if we need an inversion of the BL */
|
|
||||||
check_mem_model_blwl_inverted(mem_model, SPICE_MODEL_PORT_BL, &bl_inverted);
|
|
||||||
check_mem_model_blwl_inverted(mem_model, SPICE_MODEL_PORT_WL, &wl_inverted);
|
|
||||||
|
|
||||||
switch (mem_model->design_tech) {
|
|
||||||
case SPICE_MODEL_DESIGN_CMOS: /* CMOS SRAM*/
|
|
||||||
/* SRAM technology requires its BL decoder has an additional input called data_in
|
|
||||||
* only the selected BL will be set to the value of data_in, other BLs will be in high-resistance state
|
|
||||||
*/
|
|
||||||
/* Start the BL decoder module definition */
|
|
||||||
fprintf(fp, "//----- BL Decoder convert %d bits to binary %d bits -----\n",
|
|
||||||
bl_decoder_size, num_array_bl);
|
|
||||||
fprintf(fp, "module bl_decoder%dto%d (\n",
|
|
||||||
bl_decoder_size, num_array_bl);
|
|
||||||
fprintf(fp, "input wire enable,\n");
|
|
||||||
fprintf(fp, "input wire [%d:0] addr_in,\n",
|
|
||||||
bl_decoder_size - 1);
|
|
||||||
fprintf(fp, "input wire data_in,\n");
|
|
||||||
fprintf(fp, "output reg [0:%d] addr_out\n",
|
|
||||||
num_array_bl - 1);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Wee need to know the default value of bl port and wl port */
|
|
||||||
|
|
||||||
/* Internal logics */
|
|
||||||
|
|
||||||
fprintf(fp, "always@(addr_out,addr_in,enable, data_in)\n");
|
|
||||||
fprintf(fp, "begin\n");
|
|
||||||
fprintf(fp, "\taddr_out = %d'bz;\n", num_array_bl);
|
|
||||||
fprintf(fp, "\tif (1'b1 == enable) begin\n");
|
|
||||||
fprintf(fp, "\t\taddr_out[addr_in] = data_in;\n");
|
|
||||||
fprintf(fp, "\tend\n");
|
|
||||||
fprintf(fp, "end\n");
|
|
||||||
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_DESIGN_RRAM: /* RRAM */
|
|
||||||
/* For RRAM technology, BL decoder should be same as the WL decoder */
|
|
||||||
/* Start the BL decoder module definition */
|
|
||||||
fprintf(fp, "//----- BL Decoder convert %d bits to binary %d bits -----\n",
|
|
||||||
bl_decoder_size, num_array_bl);
|
|
||||||
fprintf(fp, "module bl_decoder%dto%d (\n",
|
|
||||||
bl_decoder_size, num_array_bl);
|
|
||||||
fprintf(fp, "input wire enable,\n");
|
|
||||||
fprintf(fp, "input wire [%d:0] addr_in,\n",
|
|
||||||
bl_decoder_size-1);
|
|
||||||
fprintf(fp, "output reg [0:%d] addr_out\n",
|
|
||||||
num_array_bl-1);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Internal logics */
|
|
||||||
fprintf(fp, "always@(addr_out,addr_in,enable)\n");
|
|
||||||
fprintf(fp, "begin\n");
|
|
||||||
if (TRUE == bl_inverted) {
|
|
||||||
fprintf(fp, "\taddr_out = %d'b1;\n", num_array_bl);
|
|
||||||
} else {
|
|
||||||
assert (FALSE == bl_inverted);
|
|
||||||
fprintf(fp, "\taddr_out = %d'b0;\n", num_array_bl);
|
|
||||||
}
|
|
||||||
fprintf(fp, "\tif (1'b1 == enable) begin\n");
|
|
||||||
if (TRUE == bl_inverted) {
|
|
||||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b0;\n");
|
|
||||||
} else {
|
|
||||||
assert (FALSE == bl_inverted);
|
|
||||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b1;\n");
|
|
||||||
}
|
|
||||||
fprintf(fp, "\tend\n");
|
|
||||||
fprintf(fp, "end\n");
|
|
||||||
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology [CMOS|RRAM] for memory technology!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WL decoder logic is the same whatever SRAM or RRAM technology is considered */
|
|
||||||
/* Start the WL module definition */
|
|
||||||
fprintf(fp, "//----- WL Decoder convert %d bits to binary %d bits -----\n",
|
|
||||||
wl_decoder_size, num_array_wl);
|
|
||||||
fprintf(fp, "module wl_decoder%dto%d (\n",
|
|
||||||
wl_decoder_size, num_array_wl);
|
|
||||||
fprintf(fp, "input wire enable,\n");
|
|
||||||
fprintf(fp, "input wire [%d:0] addr_in,\n",
|
|
||||||
wl_decoder_size-1);
|
|
||||||
fprintf(fp, "output reg [0:%d] addr_out\n",
|
|
||||||
num_array_bl-1);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Internal logics */
|
|
||||||
fprintf(fp, "always@(addr_out,addr_in,enable)\n");
|
|
||||||
fprintf(fp, "begin\n");
|
|
||||||
if (TRUE == wl_inverted) {
|
|
||||||
fprintf(fp, "\taddr_out = %d'b1;\n", num_array_wl);
|
|
||||||
} else {
|
|
||||||
assert (FALSE == wl_inverted);
|
|
||||||
fprintf(fp, "\taddr_out = %d'b0;\n", num_array_wl);
|
|
||||||
}
|
|
||||||
fprintf(fp, "\tif (1'b1 == enable) begin\n");
|
|
||||||
if (TRUE == wl_inverted) {
|
|
||||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b0;\n");
|
|
||||||
} else {
|
|
||||||
assert (FALSE == wl_inverted);
|
|
||||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b1;\n");
|
|
||||||
}
|
|
||||||
fprintf(fp, "\tend\n");
|
|
||||||
fprintf(fp, "end\n");
|
|
||||||
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For standalone-SRAM configuration organization:
|
|
||||||
* Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
void dump_verilog_standalone_sram_config_module(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info) {
|
|
||||||
int i, num_mem_bits;
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert(SPICE_SRAM_STANDALONE == cur_sram_orgz_info->type);
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File handler!",__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the total memory bits */
|
|
||||||
num_mem_bits = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
|
|
||||||
/* Dump each SRAM */
|
|
||||||
fprintf(fp, "//------ Configuration Peripheral for Standalone SRAMs -----\n");
|
|
||||||
fprintf(fp, "module %s (\n",
|
|
||||||
verilog_config_peripheral_prefix);
|
|
||||||
/* Dump port map*/
|
|
||||||
fprintf(fp, "input %s_in[%d:%d],\n",
|
|
||||||
sram_verilog_model->prefix,
|
|
||||||
0, num_mem_bits - 1);
|
|
||||||
fprintf(fp, "output %s_out[%d:%d],\n",
|
|
||||||
sram_verilog_model->prefix,
|
|
||||||
0, num_mem_bits - 1);
|
|
||||||
fprintf(fp, "output %s_outb[%d:%d]);\n",
|
|
||||||
sram_verilog_model->prefix,
|
|
||||||
0, num_mem_bits - 1);
|
|
||||||
|
|
||||||
for (i = 0; i < num_mem_bits; i++) {
|
|
||||||
/* Input and 2 outputs */
|
|
||||||
fprintf(fp, "assign %s_out[%d] = %s_in[%d];\n",
|
|
||||||
sram_verilog_model->prefix, i,
|
|
||||||
sram_verilog_model->prefix, i);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
}
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
fprintf(fp, "//------ END Standalone SRAMs -----\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* For scan-chain configuration organization:
|
|
||||||
* Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
void dump_verilog_scan_chain_config_module(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info) {
|
|
||||||
int num_mem_bits;
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert(SPICE_SRAM_SCAN_CHAIN == cur_sram_orgz_info->type);
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid file handler!",__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the total memory bits */
|
|
||||||
num_mem_bits = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
|
|
||||||
/* Dump each Scan-chain FF */
|
|
||||||
fprintf(fp, "//------ Configuration Peripheral for Scan-chain FFs -----\n");
|
|
||||||
fprintf(fp, "module %s (\n",
|
|
||||||
verilog_config_peripheral_prefix);
|
|
||||||
/* Port map definition */
|
|
||||||
/* Scan-chain input*/
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_INPUT,
|
|
||||||
top_netlist_scan_chain_head_prefix, 0, 0);
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
/* Scan-chain regular inputs */
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, num_mem_bits - 1, -1, VERILOG_PORT_OUTPUT);
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
fprintf(fp, "input ");
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, num_mem_bits - 1, 0, VERILOG_PORT_WIRE);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Connect scan-chain input to the first scan-chain input */
|
|
||||||
fprintf(fp, " ");
|
|
||||||
fprintf(fp, "assign ");
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, 0, -1, VERILOG_PORT_CONKT);
|
|
||||||
fprintf(fp, " = ");
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_CONKT,
|
|
||||||
top_netlist_scan_chain_head_prefix, 0, 0);
|
|
||||||
fprintf(fp, ";\n");
|
|
||||||
|
|
||||||
/* Verilog Module body */
|
|
||||||
/* Connect the head of current ccff to the tail of previous ccff*/
|
|
||||||
fprintf(fp, " ");
|
|
||||||
fprintf(fp, "assign ");
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 1, num_mem_bits - 1, -1, VERILOG_PORT_CONKT);
|
|
||||||
fprintf(fp, " = ");
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, num_mem_bits - 2, 0, VERILOG_PORT_CONKT);
|
|
||||||
fprintf(fp, ";\n");
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
fprintf(fp, "//------ END Scan-chain FFs -----\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Output a inverter module for inverting a BL/WL line
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
void dump_verilog_membank_one_inv_module(FILE* fp,
|
|
||||||
const t_spice_model* inv_spice_model,
|
|
||||||
const char* instance_tag,
|
|
||||||
const char* in_port_name,
|
|
||||||
const char* out_port_name,
|
|
||||||
int inv_index) {
|
|
||||||
/* A valid file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
assert(NULL != instance_tag);
|
|
||||||
assert(NULL != in_port_name);
|
|
||||||
assert(NULL != out_port_name);
|
|
||||||
|
|
||||||
/* Find the input port, output port, and sram port*/
|
|
||||||
int num_buf_input_port;
|
|
||||||
int num_buf_output_port;
|
|
||||||
t_spice_model_port** buf_input_port = find_spice_model_ports(inv_spice_model, SPICE_MODEL_PORT_INPUT, &num_buf_input_port, TRUE);
|
|
||||||
t_spice_model_port** buf_output_port = find_spice_model_ports(inv_spice_model, SPICE_MODEL_PORT_OUTPUT, &num_buf_output_port, TRUE);
|
|
||||||
/* Instanciate an inverter module */
|
|
||||||
fprintf(fp, " %s %s_%s_%d (",
|
|
||||||
inv_spice_model->name, inv_spice_model->prefix,
|
|
||||||
instance_tag, inv_index);
|
|
||||||
/* Dump global ports */
|
|
||||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, inv_spice_model, FALSE, FALSE, inv_spice_model->dump_explicit_port_map, TRUE)) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
/* Dump explicit port map if required */
|
|
||||||
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
|
|
||||||
fprintf(fp, ".%s(",
|
|
||||||
buf_input_port[0]->lib_name);
|
|
||||||
}
|
|
||||||
fprintf(fp, "%s[%d]",
|
|
||||||
in_port_name, inv_index);
|
|
||||||
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
|
|
||||||
fprintf(fp, ".%s(",
|
|
||||||
buf_output_port[0]->lib_name);
|
|
||||||
}
|
|
||||||
fprintf(fp, "%s[%d]",
|
|
||||||
out_port_name, inv_index);
|
|
||||||
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Free */
|
|
||||||
my_free(buf_input_port);
|
|
||||||
my_free(buf_output_port);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For Memory-bank configuration organization:
|
|
||||||
* Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
void dump_verilog_membank_config_module(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info) {
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
int iinv, icol, irow;
|
|
||||||
int num_bl, num_wl;
|
|
||||||
int num_array_bl, num_array_wl;
|
|
||||||
int num_reserved_bl, num_reserved_wl;
|
|
||||||
int cur_bl_lsb, cur_wl_lsb;
|
|
||||||
int cur_bl_msb, cur_wl_msb;
|
|
||||||
int bl_decoder_size, wl_decoder_size;
|
|
||||||
int num_blb_ports, num_wlb_ports;
|
|
||||||
t_spice_model_port** blb_port = NULL;
|
|
||||||
t_spice_model_port** wlb_port = NULL;
|
|
||||||
t_spice_model* blb_inv_spice_model = NULL;
|
|
||||||
t_spice_model* wlb_inv_spice_model = NULL;
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert(SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type);
|
|
||||||
assert(NULL != cur_sram_orgz_info->mem_bank_info);
|
|
||||||
|
|
||||||
/* A valid file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Depending on the memory technology*/
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
assert(NULL != mem_model);
|
|
||||||
|
|
||||||
/* Get the total number of BLs and WLs */
|
|
||||||
get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &num_bl, &num_wl);
|
|
||||||
/* Get the reserved BLs and WLs */
|
|
||||||
get_sram_orgz_info_reserved_blwl(cur_sram_orgz_info, &num_reserved_bl, &num_reserved_wl);
|
|
||||||
|
|
||||||
determine_blwl_decoder_size(cur_sram_orgz_info,
|
|
||||||
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
|
|
||||||
|
|
||||||
/* Get BLB and WLB ports */
|
|
||||||
find_blb_wlb_ports_spice_model(mem_model, &num_blb_ports, &blb_port,
|
|
||||||
&num_wlb_ports, &wlb_port);
|
|
||||||
/* Get inverter spice_model */
|
|
||||||
|
|
||||||
/* Dump each SRAM */
|
|
||||||
fprintf(fp, "//------ Configuration Peripheral for Memory-bank -----\n");
|
|
||||||
fprintf(fp, "module %s (\n",
|
|
||||||
verilog_config_peripheral_prefix);
|
|
||||||
/* Port map */
|
|
||||||
/* Ports for memory decoders */
|
|
||||||
dump_verilog_decoder_memory_bank_ports(cur_sram_orgz_info, fp, VERILOG_PORT_INPUT);
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
/* Ports for all the SRAM cells */
|
|
||||||
switch (mem_model->design_tech) {
|
|
||||||
case SPICE_MODEL_DESIGN_CMOS:
|
|
||||||
assert( 0 == num_reserved_bl );
|
|
||||||
assert( 0 == num_reserved_wl );
|
|
||||||
|
|
||||||
/* Declare normal BL / WL inputs */
|
|
||||||
fprintf(fp, " output wire [%d:%d] %s%s",
|
|
||||||
0, num_bl - 1, mem_model->prefix, top_netlist_normal_bl_port_postfix);
|
|
||||||
fprintf(fp, ", //---- Normal Bit lines \n");
|
|
||||||
|
|
||||||
fprintf(fp, " output wire [%d:%d] %s%s",
|
|
||||||
0, num_wl - 1, mem_model->prefix, top_netlist_normal_wl_port_postfix);
|
|
||||||
/* Declare inverted wires if needed */
|
|
||||||
if (1 == num_blb_ports) {
|
|
||||||
fprintf(fp, ", //---- Normal Word lines \n");
|
|
||||||
} else {
|
|
||||||
fprintf(fp, " //---- Normal Word lines\n");
|
|
||||||
}
|
|
||||||
if (1 == num_blb_ports) {
|
|
||||||
fprintf(fp, " output wire [%d:%d] %s%s",
|
|
||||||
0, num_bl - 1, mem_model->prefix, top_netlist_normal_blb_port_postfix);
|
|
||||||
}
|
|
||||||
if (1 == num_wlb_ports) {
|
|
||||||
fprintf(fp, ", //---- Inverted Normal Bit lines \n");
|
|
||||||
} else {
|
|
||||||
fprintf(fp, " //---- Inverted Normal Bit lines \n");
|
|
||||||
}
|
|
||||||
if (1 == num_wlb_ports) {
|
|
||||||
fprintf(fp, " output wire [%d:%d] %s%s //---- Inverted Normal Word lines \n",
|
|
||||||
0, num_wl - 1, mem_model->prefix, top_netlist_normal_wlb_port_postfix);
|
|
||||||
}
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_DESIGN_RRAM:
|
|
||||||
/* Check: there should be reserved BLs and WLs */
|
|
||||||
assert( 0 < num_reserved_bl );
|
|
||||||
assert( 0 < num_reserved_wl );
|
|
||||||
/* Declare reserved and normal conf_bits ports */
|
|
||||||
fprintf(fp, " input wire [0:%d] %s%s, //---- Reserved Bit lines \n",
|
|
||||||
num_reserved_bl - 1, mem_model->prefix, top_netlist_reserved_bl_port_postfix);
|
|
||||||
fprintf(fp, " input wire [0:%d] %s%s, //---- Reserved Word lines \n",
|
|
||||||
num_reserved_wl - 1, mem_model->prefix, top_netlist_reserved_wl_port_postfix);
|
|
||||||
fprintf(fp, " input wire [%d:%d] %s%s, //---- Normal Bit lines \n",
|
|
||||||
num_reserved_bl, num_array_bl - 1, mem_model->prefix, top_netlist_normal_bl_port_postfix);
|
|
||||||
fprintf(fp, " input wire [%d:%d] %s%s); //---- Normal Word lines \n",
|
|
||||||
num_reserved_wl, num_array_wl - 1, mem_model->prefix, top_netlist_normal_wl_port_postfix);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Important!!!:
|
|
||||||
* BL/WL should always start from LSB to MSB!
|
|
||||||
* In order to follow this convention in primitive nodes.
|
|
||||||
*/
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
/* No. of BLs and WLs in the array */
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_array_bl_port_name, 0, num_array_bl - 1);
|
|
||||||
fprintf(fp, "; //--- Array Bit lines bus \n");
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_array_wl_port_name, 0, num_array_wl - 1);
|
|
||||||
fprintf(fp, "; //--- Array Bit lines bus \n");
|
|
||||||
if (1 == num_blb_ports) {
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_array_blb_port_name, 0, num_array_bl - 1);
|
|
||||||
fprintf(fp, "; //--- Inverted Array Bit lines bus \n");
|
|
||||||
}
|
|
||||||
if (1 == num_wlb_ports) {
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_array_wlb_port_name, 0, num_array_wl - 1);
|
|
||||||
fprintf(fp, "; //--- Inverted Array Word lines bus \n");
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
switch (mem_model->design_tech) {
|
|
||||||
case SPICE_MODEL_DESIGN_CMOS:
|
|
||||||
assert( 0 == num_reserved_bl );
|
|
||||||
assert( 0 == num_reserved_wl );
|
|
||||||
/* SRAMs are place in an array
|
|
||||||
* BLs of SRAMs in the same column are connected to a common BL
|
|
||||||
* BLs of SRAMs in the same row are connected to a common WL
|
|
||||||
*/
|
|
||||||
/* Declare inverted wires if needed */
|
|
||||||
if (1 == num_blb_ports) {
|
|
||||||
/* get inv_spice_model */
|
|
||||||
blb_inv_spice_model = blb_port[0]->inv_spice_model;
|
|
||||||
/* Make an inversion of the BL */
|
|
||||||
for (iinv = 0; iinv < num_array_bl; iinv++) {
|
|
||||||
dump_verilog_membank_one_inv_module(fp, blb_inv_spice_model, "blb",
|
|
||||||
top_netlist_array_bl_port_name,
|
|
||||||
top_netlist_array_blb_port_name,
|
|
||||||
iinv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (1 == num_wlb_ports) {
|
|
||||||
/* get inv_spice_model */
|
|
||||||
wlb_inv_spice_model = wlb_port[0]->inv_spice_model;
|
|
||||||
/* Make an inversion of the WL */
|
|
||||||
for (iinv = 0; iinv < num_array_wl; iinv++) {
|
|
||||||
dump_verilog_membank_one_inv_module(fp, wlb_inv_spice_model, "wlb",
|
|
||||||
top_netlist_array_wl_port_name,
|
|
||||||
top_netlist_array_wlb_port_name,
|
|
||||||
iinv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connections for columns */
|
|
||||||
for (icol = 0; icol < num_array_bl; icol++) {
|
|
||||||
cur_bl_lsb = icol * num_array_bl;
|
|
||||||
cur_bl_msb = (icol + 1) * num_array_bl - 1;
|
|
||||||
/* Check if the msb exceeds the upbound of num_bl */
|
|
||||||
if (cur_bl_msb > num_bl - 1) {
|
|
||||||
cur_bl_msb = num_bl - 1;
|
|
||||||
}
|
|
||||||
/* connect to the BLs of all the SRAMs in the column */
|
|
||||||
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_normal_bl_port_postfix, cur_bl_lsb, cur_bl_msb,
|
|
||||||
top_netlist_array_bl_port_name, 0, cur_bl_msb - cur_bl_lsb);
|
|
||||||
if (1 == num_blb_ports) {
|
|
||||||
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_normal_blb_port_postfix, cur_bl_lsb, cur_bl_msb,
|
|
||||||
top_netlist_array_blb_port_name, 0, cur_bl_msb - cur_bl_lsb);
|
|
||||||
}
|
|
||||||
/* Finish if MSB meets the upbound */
|
|
||||||
if (cur_bl_msb == num_bl - 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Connections for rows */
|
|
||||||
for (irow = 0; irow < num_array_wl; irow++) {
|
|
||||||
cur_wl_lsb = irow * num_array_wl;
|
|
||||||
cur_wl_msb = (irow + 1) * num_array_wl - 1;
|
|
||||||
/* Check if the msb exceeds the upbound of num_bl */
|
|
||||||
if (cur_wl_msb > num_wl - 1) {
|
|
||||||
cur_wl_msb = num_wl - 1;
|
|
||||||
}
|
|
||||||
/* connect to the BLs of all the SRAMs in the column */
|
|
||||||
for (icol = cur_wl_lsb; icol < cur_wl_msb + 1; icol++) {
|
|
||||||
fprintf(fp, " assign %s%s[%d] = %s[%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_normal_wl_port_postfix, icol,
|
|
||||||
top_netlist_array_wl_port_name, irow);
|
|
||||||
if (1 == num_wlb_ports) {
|
|
||||||
fprintf(fp, " assign %s%s[%d] = %s[%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_normal_wlb_port_postfix, icol,
|
|
||||||
top_netlist_array_wlb_port_name, irow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Finish if MSB meets the upbound */
|
|
||||||
if (cur_wl_msb == num_wl - 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_DESIGN_RRAM:
|
|
||||||
/* Check: there should be reserved BLs and WLs */
|
|
||||||
assert( 0 < num_reserved_bl );
|
|
||||||
assert( 0 < num_reserved_wl );
|
|
||||||
/* Declare reserved and normal conf_bits ports */
|
|
||||||
fprintf(fp, " wire [0:%d] %s%s; //---- Reserved Bit lines \n",
|
|
||||||
num_reserved_bl - 1, mem_model->prefix, top_netlist_reserved_bl_port_postfix);
|
|
||||||
fprintf(fp, " wire [0:%d] %s%s; //---- Reserved Word lines \n",
|
|
||||||
num_reserved_wl - 1, mem_model->prefix, top_netlist_reserved_wl_port_postfix);
|
|
||||||
fprintf(fp, " wire [%d:%d] %s%s; //---- Normal Bit lines \n",
|
|
||||||
num_reserved_bl, num_array_bl - 1, mem_model->prefix, top_netlist_normal_bl_port_postfix);
|
|
||||||
fprintf(fp, " wire [%d:%d] %s%s; //---- Normal Word lines \n",
|
|
||||||
num_reserved_wl, num_array_wl - 1, mem_model->prefix, top_netlist_normal_wl_port_postfix);
|
|
||||||
/* Connect reserved conf_bits and normal conf_bits to the bus */
|
|
||||||
fprintf(fp, " assign %s%s[0:%d] = %s[0:%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_reserved_bl_port_postfix, num_reserved_bl - 1,
|
|
||||||
top_netlist_array_bl_port_name, num_reserved_bl - 1);
|
|
||||||
fprintf(fp, " assign %s%s[0:%d] = %s[0:%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_reserved_wl_port_postfix, num_reserved_wl - 1,
|
|
||||||
top_netlist_array_wl_port_name, num_reserved_wl - 1);
|
|
||||||
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_normal_bl_port_postfix, num_reserved_bl, num_array_bl - 1,
|
|
||||||
top_netlist_array_bl_port_name, num_reserved_bl, num_array_bl - 1);
|
|
||||||
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
|
|
||||||
mem_model->prefix, top_netlist_normal_wl_port_postfix, num_reserved_wl, num_array_wl - 1,
|
|
||||||
top_netlist_array_wl_port_name, num_reserved_wl, num_array_wl - 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Comment lines */
|
|
||||||
fprintf(fp, "//----- BEGIN call decoders for memory bank controller -----\n");
|
|
||||||
|
|
||||||
/* Dump Decoders for Bit lines and Word lines */
|
|
||||||
/* Two huge decoders
|
|
||||||
* TODO: divide to a number of small decoders ?
|
|
||||||
*/
|
|
||||||
/* Bit lines decoder */
|
|
||||||
fprintf(fp, " ");
|
|
||||||
fprintf(fp, "bl_decoder%dto%d mem_bank_bl_decoder (",
|
|
||||||
bl_decoder_size, num_array_bl);
|
|
||||||
/* Prefix of BL & WL is fixed, in order to simplify grouping nets */
|
|
||||||
fprintf(fp, "%s, %s[%d:0], ",
|
|
||||||
top_netlist_bl_enable_port_name,
|
|
||||||
top_netlist_addr_bl_port_name, bl_decoder_size - 1);
|
|
||||||
/* Port map depends on the memory technology */
|
|
||||||
switch (mem_model->design_tech) {
|
|
||||||
case SPICE_MODEL_DESIGN_CMOS:
|
|
||||||
/* Data input port of BL decoder, only required by SRAM array */
|
|
||||||
fprintf(fp, "%s, ",
|
|
||||||
top_netlist_bl_data_in_port_name);
|
|
||||||
break;
|
|
||||||
case SPICE_MODEL_DESIGN_RRAM:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
fprintf(fp, "%s[0:%d]",
|
|
||||||
top_netlist_array_bl_port_name, num_array_bl - 1);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Word lines decoder is the same for both technology */
|
|
||||||
fprintf(fp, " ");
|
|
||||||
fprintf(fp, "wl_decoder%dto%d mem_bank_wl_decoder (",
|
|
||||||
wl_decoder_size, num_array_wl);
|
|
||||||
fprintf(fp, "%s, %s[%d:0], ",
|
|
||||||
top_netlist_wl_enable_port_name,
|
|
||||||
top_netlist_addr_wl_port_name, wl_decoder_size - 1);
|
|
||||||
fprintf(fp, "%s[0:%d]",
|
|
||||||
top_netlist_array_wl_port_name, num_array_wl - 1);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
fprintf(fp, "//----- END call decoders for memory bank controller -----\n\n");
|
|
||||||
|
|
||||||
/* Comment lines */
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
fprintf(fp, "//----- END configuration peripheral for memory-bank -----\n\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Top-level function */
|
|
||||||
void dump_verilog_config_peripherals(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir_path,
|
|
||||||
char* submodule_dir_path) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
|
|
||||||
char* verilog_name = my_strcat(submodule_dir_path, config_peripheral_verilog_file_name);
|
|
||||||
|
|
||||||
/* Open file and file handler */
|
|
||||||
fp = fopen(verilog_name, "w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create decoder SPICE netlist %s",
|
|
||||||
__FILE__, __LINE__, verilog_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* Generate file header*/
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "Writing configuration peripheral verilog netlist...\n");
|
|
||||||
|
|
||||||
/* Generate the descriptions*/
|
|
||||||
dump_verilog_file_header(fp, " Verilog Configuration Peripheral");
|
|
||||||
|
|
||||||
verilog_include_defines_preproc_file(fp, verilog_dir_path);
|
|
||||||
|
|
||||||
switch(cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
dump_verilog_scan_chain_config_module(fp, cur_sram_orgz_info);
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* Dump verilog decoder */
|
|
||||||
dump_verilog_decoder(fp, cur_sram_orgz_info);
|
|
||||||
dump_verilog_membank_config_module(fp, cur_sram_orgz_info);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the file*/
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/* Add fname to the linked list */
|
|
||||||
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_name);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef VERILOG_DECODER_H
|
|
||||||
#define VERILOG_DECODER_H
|
|
||||||
|
|
||||||
void dump_verilog_decoder_memory_bank_ports(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
enum e_dump_verilog_port_type dump_port_type);
|
|
||||||
|
|
||||||
void dump_verilog_config_peripherals(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir_path,
|
|
||||||
char* submodule_dir);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,315 +0,0 @@
|
||||||
/***********************************/
|
|
||||||
/* 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>
|
|
||||||
#define MINI_CASE_SENSITIVE
|
|
||||||
#include "ini.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 "route_common.h"
|
|
||||||
#include "vpr_utils.h"
|
|
||||||
|
|
||||||
/* Include SPICE support headers*/
|
|
||||||
#include "linkedlist.h"
|
|
||||||
#include "fpga_x2p_types.h"
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
#include "fpga_x2p_backannotate_utils.h"
|
|
||||||
#include "fpga_x2p_mux_utils.h"
|
|
||||||
#include "fpga_x2p_pbtypes_utils.h"
|
|
||||||
#include "fpga_x2p_bitstream_utils.h"
|
|
||||||
#include "fpga_x2p_rr_graph_utils.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
|
|
||||||
/* Include Verilog support headers*/
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
#include "verilog_routing.h"
|
|
||||||
#include "verilog_tcl_utils.h"
|
|
||||||
|
|
||||||
mINI::INIStructure ini;
|
|
||||||
|
|
||||||
static void searching_used_latch(FILE *fp, t_pb * pb, int pb_index, char* chomped_circuit_name, char* inst_name){
|
|
||||||
int i, j;
|
|
||||||
char WriteBuffer[200];
|
|
||||||
char INI_lbl[100];
|
|
||||||
// char* tmp = NULL;
|
|
||||||
const t_pb_type *pb_type;
|
|
||||||
t_mode *mode;
|
|
||||||
t_pb_graph_node * node;
|
|
||||||
// char* index = NULL;
|
|
||||||
|
|
||||||
pb_type = pb->pb_graph_node->pb_type;
|
|
||||||
node = pb->pb_graph_node->physical_pb_graph_node;
|
|
||||||
mode = &pb_type->modes[pb->mode];
|
|
||||||
|
|
||||||
// tmp = (char*) my_malloc(sizeof(1 + (strlen(ff_hierarchy) + 1 + strlen(my_strcat(pb_type->name, index)))));
|
|
||||||
// tmp = ff_hierarchy;
|
|
||||||
// index = my_strcat("_", my_strcat(my_itoa(pb_index), "_"));
|
|
||||||
|
|
||||||
if (pb_type->num_modes > 0) {
|
|
||||||
for (i = 0; i < mode->num_pb_type_children; i++) {
|
|
||||||
for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
|
|
||||||
// if(strcmp(pb_type->name, mode->name) != 0)
|
|
||||||
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->name, index)));
|
|
||||||
if(pb->child_pbs[i][j].name != NULL)
|
|
||||||
searching_used_latch(fp, &pb->child_pbs[i][j], j, chomped_circuit_name, inst_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if((pb_type->class_type == LATCH_CLASS) && (pb->name)){
|
|
||||||
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->physical_pb_type_name, my_strcat(index, "/dff_0_"))));
|
|
||||||
fprintf(fp, "set_user_match r:/WORK/%s/%s_reg i:/WORK/%s/%sdff_0 -type cell -noninverted\n", chomped_circuit_name,
|
|
||||||
pb->name,
|
|
||||||
inst_name,
|
|
||||||
gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node) );
|
|
||||||
sprintf(WriteBuffer, "%s/%sdff_0 ",
|
|
||||||
inst_name, gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node));
|
|
||||||
|
|
||||||
sprintf(INI_lbl, "%s_reg", pb->name);
|
|
||||||
ini["REGISTER_MATCH"][INI_lbl] = WriteBuffer;
|
|
||||||
}
|
|
||||||
//free(tmp); //Looks like is the cause of a double free, once free executated next iteration as no value in tmp
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clb_iteration(FILE *fp, char* chomped_circuit_name, int h){
|
|
||||||
t_pb* pb;
|
|
||||||
char* inst_name = NULL;
|
|
||||||
const t_pb_type *pb_type;
|
|
||||||
t_mode *mode;
|
|
||||||
int i, j, x_pos, y_pos;
|
|
||||||
char* grid_x = NULL;
|
|
||||||
char* grid_y = NULL;
|
|
||||||
|
|
||||||
x_pos = block[h].x;
|
|
||||||
y_pos = block[h].y;
|
|
||||||
|
|
||||||
pb = (t_pb*) block[h].pb;
|
|
||||||
|
|
||||||
pb_type = pb->pb_graph_node->pb_type;
|
|
||||||
mode = &pb_type->modes[pb->mode];
|
|
||||||
|
|
||||||
grid_x = my_strcat("_", my_strcat(my_itoa(x_pos), "_"));
|
|
||||||
grid_y = my_strcat("_", my_strcat(my_itoa(y_pos), "_"));
|
|
||||||
|
|
||||||
|
|
||||||
if (strcmp(pb_type->name, FILL_TYPE->name) == 0) {
|
|
||||||
inst_name = my_strcat(chomped_circuit_name, my_strcat(formal_verification_top_postfix, my_strcat("/", my_strcat(formal_verification_top_module_uut_name, my_strcat("/grid",my_strcat(grid_x, my_strcat(grid_y, "/" )))))));
|
|
||||||
if (pb_type->num_modes > 0) {
|
|
||||||
for (i = 0; i < mode->num_pb_type_children; i++) {
|
|
||||||
inst_name = my_strcat(inst_name, my_strcat("grid_", my_strcat(pb_type->name, my_strcat("_", my_strcat(my_itoa(i), "_")))));
|
|
||||||
for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
|
|
||||||
/* If child pb is not used but routing is used, I must print things differently */
|
|
||||||
if ((pb->child_pbs[i] != NULL)
|
|
||||||
&& (pb->child_pbs[i][j].name != NULL)) {
|
|
||||||
searching_used_latch(fp, &pb->child_pbs[i][j], j, chomped_circuit_name, inst_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void match_registers(FILE *fp, char* chomped_circuit_name) {
|
|
||||||
int h;
|
|
||||||
|
|
||||||
for(h = 0; h < copy_nb_clusters; h++)
|
|
||||||
clb_iteration(fp, chomped_circuit_name, h);
|
|
||||||
/* for(h = 0; h < copy_nb_clusters; h++){
|
|
||||||
free_cb(copy_clb[h].pb);
|
|
||||||
free(copy_clb[h].name);
|
|
||||||
free(copy_clb[h].nets);
|
|
||||||
free(copy_clb[h].pb);
|
|
||||||
}*/
|
|
||||||
// free(copy_clb);
|
|
||||||
// free(block);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void formality_include_user_defined_verilog_netlists(FILE* fp,
|
|
||||||
t_spice spice) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* A valid file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(File:%s, [LINE%d])Invalid File Handler!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Include user-defined sub-circuit netlist */
|
|
||||||
for (i = 0; i < spice.num_include_netlist; i++) {
|
|
||||||
if (0 == spice.include_netlists[i].included) {
|
|
||||||
assert(NULL != spice.include_netlists[i].path);
|
|
||||||
fprintf(fp, "%s ", spice.include_netlists[i].path);
|
|
||||||
spice.include_netlists[i].included = 1;
|
|
||||||
} else {
|
|
||||||
assert(1 == spice.include_netlists[i].included);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_formality_script (t_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
char* fm_dir_formatted,
|
|
||||||
char* src_dir_formatted,
|
|
||||||
char* chomped_circuit_name,
|
|
||||||
t_spice spice){
|
|
||||||
int iblock, i, FileCounter=0;
|
|
||||||
char* formality_script_file_name = NULL;
|
|
||||||
char* benchmark_path = NULL;
|
|
||||||
char* original_output_name = NULL;
|
|
||||||
char WriteBuffer[4096];
|
|
||||||
char INI_lbl[4096];
|
|
||||||
/* int output_length; */
|
|
||||||
/* int pos; */
|
|
||||||
FILE* fp = NULL;
|
|
||||||
|
|
||||||
if(TRUE == fpga_verilog_opts.print_autocheck_top_testbench)
|
|
||||||
benchmark_path = fpga_verilog_opts.reference_verilog_benchmark_file;
|
|
||||||
else
|
|
||||||
benchmark_path = "Insert verilog benchmark path";
|
|
||||||
|
|
||||||
formality_script_file_name = my_strcat(fm_dir_formatted, my_strcat(chomped_circuit_name, formality_script_name_postfix));
|
|
||||||
fp = fopen(formality_script_file_name, "w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Failure in create formality script %s",
|
|
||||||
__FILE__, __LINE__, formality_script_file_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load Verilog benchmark as reference */
|
|
||||||
fprintf(fp, "read_verilog -container r -libname WORK -05 { %s }\n", benchmark_path);
|
|
||||||
ini["BENCHMARK_INFO"]["benchmark_netlist "] = benchmark_path;
|
|
||||||
|
|
||||||
/* Set reference top */
|
|
||||||
fprintf(fp, "set_top r:/WORK/%s\n", chomped_circuit_name);
|
|
||||||
ini["BENCHMARK_INFO"]["src_top_module "] = chomped_circuit_name;
|
|
||||||
|
|
||||||
/* Load generated verilog as implemnetation */
|
|
||||||
fprintf(fp, "read_verilog -container i -libname WORK -05 { ");
|
|
||||||
fprintf(fp, "%s%s%s ", src_dir_formatted,
|
|
||||||
chomped_circuit_name,
|
|
||||||
verilog_top_postfix);
|
|
||||||
sprintf(WriteBuffer, "%s%s%s", src_dir_formatted, chomped_circuit_name,
|
|
||||||
verilog_top_postfix);
|
|
||||||
sprintf(INI_lbl, "impl_netlist_%02d",FileCounter++);
|
|
||||||
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
|
|
||||||
|
|
||||||
fprintf(fp, "%s%s%s ", src_dir_formatted,
|
|
||||||
chomped_circuit_name,
|
|
||||||
formal_verification_verilog_file_postfix);
|
|
||||||
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
|
|
||||||
chomped_circuit_name, formal_verification_verilog_file_postfix);
|
|
||||||
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
|
|
||||||
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
|
|
||||||
|
|
||||||
init_include_user_defined_verilog_netlists(spice);
|
|
||||||
// formality_include_user_defined_verilog_netlists(fp, spice);
|
|
||||||
|
|
||||||
/* Include user-defined sub-circuit netlist */
|
|
||||||
for (i = 0; i < spice.num_include_netlist; i++) {
|
|
||||||
if (0 == spice.include_netlists[i].included) {
|
|
||||||
assert(NULL != spice.include_netlists[i].path);
|
|
||||||
fprintf(fp, "%s ", spice.include_netlists[i].path);
|
|
||||||
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
|
|
||||||
ini["FPGA_INFO"][INI_lbl] = spice.include_netlists[i].path;
|
|
||||||
spice.include_netlists[i].included = 1;
|
|
||||||
} else {
|
|
||||||
assert(1 == spice.include_netlists[i].included);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "%s%s%s ", src_dir_formatted,
|
|
||||||
default_rr_dir_name,
|
|
||||||
routing_verilog_file_name);
|
|
||||||
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
|
|
||||||
default_rr_dir_name,
|
|
||||||
routing_verilog_file_name);
|
|
||||||
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
|
|
||||||
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
fprintf(fp, "%s%s%s ", src_dir_formatted,
|
|
||||||
default_lb_dir_name,
|
|
||||||
logic_block_verilog_file_name);
|
|
||||||
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
|
|
||||||
default_lb_dir_name,
|
|
||||||
logic_block_verilog_file_name);
|
|
||||||
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
|
|
||||||
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
fprintf(fp, "%s%s%s ", src_dir_formatted,
|
|
||||||
default_submodule_dir_name,
|
|
||||||
submodule_verilog_file_name);
|
|
||||||
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
|
|
||||||
default_submodule_dir_name,
|
|
||||||
submodule_verilog_file_name);
|
|
||||||
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
|
|
||||||
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
/* Set implementation top */
|
|
||||||
fprintf(fp, "set_top i:/WORK/%s\n", my_strcat(chomped_circuit_name,
|
|
||||||
formal_verification_top_postfix));
|
|
||||||
sprintf(WriteBuffer, "%s", my_strcat(chomped_circuit_name,
|
|
||||||
formal_verification_top_postfix));
|
|
||||||
ini["FPGA_INFO"]["impl_top_module"] = WriteBuffer;
|
|
||||||
|
|
||||||
/* Run matching */
|
|
||||||
fprintf(fp, "match\n");
|
|
||||||
/* Add manual matching for the outputs */
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
original_output_name = NULL;
|
|
||||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
|
||||||
/* Make sure We find the correct logical block !*/
|
|
||||||
assert((VPACK_INPAD == logical_block[iblock].type)
|
|
||||||
||(VPACK_OUTPAD == logical_block[iblock].type));
|
|
||||||
if(VPACK_OUTPAD == logical_block[iblock].type){
|
|
||||||
/* output_length = strlen(logical_block[iblock].name); */
|
|
||||||
original_output_name = logical_block[iblock].name + 4;
|
|
||||||
/* printf("%s", original_output_name); */
|
|
||||||
fprintf(fp, "set_user_match r:/WORK/%s/%s i:/WORK/%s/%s[0] -type port -noninverted\n",
|
|
||||||
chomped_circuit_name,
|
|
||||||
original_output_name,
|
|
||||||
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
|
|
||||||
my_strcat(logical_block[iblock].name,
|
|
||||||
formal_verification_top_module_port_postfix));
|
|
||||||
|
|
||||||
sprintf(WriteBuffer, "%s/%s[0]",
|
|
||||||
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
|
|
||||||
my_strcat(logical_block[iblock].name, formal_verification_top_module_port_postfix));
|
|
||||||
|
|
||||||
sprintf(INI_lbl, "%s", original_output_name);
|
|
||||||
ini["PORT_MATCHING"][INI_lbl] = WriteBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match_registers(fp, chomped_circuit_name);
|
|
||||||
/* Run verification */
|
|
||||||
fprintf(fp, "verify\n");
|
|
||||||
/* Script END */
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
mINI::INIFile file(my_strcat(formality_script_file_name,".ini"));
|
|
||||||
file.generate(ini, true);
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
void write_formality_script (t_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
char* fm_dir_formatted,
|
|
||||||
char* src_dir_formatted,
|
|
||||||
char* chomped_circuit_name,
|
|
||||||
t_spice spice);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,150 +9,6 @@
|
||||||
#include "module_manager.h"
|
#include "module_manager.h"
|
||||||
#include "rr_blocks.h"
|
#include "rr_blocks.h"
|
||||||
|
|
||||||
void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir,
|
|
||||||
char* subckt_dir,
|
|
||||||
int x, int y,
|
|
||||||
t_rr_type chan_type,
|
|
||||||
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,
|
|
||||||
int num_segment, t_segment_inf* segments,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts);
|
|
||||||
|
|
||||||
void dump_verilog_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
|
|
||||||
int pin_index, int side,
|
|
||||||
int x, int y,
|
|
||||||
int unique_x, int unique_y, /* If explicit, needs the coordinates of the mirror*/
|
|
||||||
boolean dump_port_type,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_grid_side_pins(FILE* fp,
|
|
||||||
t_rr_type pin_type, int x, int y, int side,
|
|
||||||
boolean dump_port_type);
|
|
||||||
|
|
||||||
void dump_verilog_switch_box_chan_port(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
int chan_side,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
enum PORTS cur_rr_node_direction);
|
|
||||||
|
|
||||||
void dump_verilog_switch_box_short_interc(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
int chan_side,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
int actual_fan_in,
|
|
||||||
t_rr_node* drive_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_switch_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
int chan_side,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
int mux_size,
|
|
||||||
t_rr_node** drive_rr_nodes,
|
|
||||||
int switch_index,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
int count_verilog_switch_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_sb cur_sb_info, int chan_side,
|
|
||||||
t_rr_node* cur_rr_node);
|
|
||||||
|
|
||||||
int count_verilog_switch_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_sb cur_sb_info, int chan_side,
|
|
||||||
t_rr_node* cur_rr_node);
|
|
||||||
|
|
||||||
void dump_verilog_switch_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
int chan_side,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
int count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_sb cur_sb_info);
|
|
||||||
|
|
||||||
int count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_sb cur_sb_info);
|
|
||||||
|
|
||||||
void dump_verilog_routing_switch_box_subckt(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir, 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_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
boolean compact_routing_hierarchy,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
|
|
||||||
void dump_verilog_connection_box_short_interc(FILE* fp,
|
|
||||||
t_cb* cur_cb_info,
|
|
||||||
t_rr_node* src_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_connection_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
t_cb* cur_cb_info,
|
|
||||||
t_rr_node* src_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_connection_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
t_cb* cur_cb_info,
|
|
||||||
t_rr_node* src_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
|
|
||||||
int count_verilog_connection_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_rr_node* cur_rr_node);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_one_side_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
const RRGSB& rr_gsb, enum e_side cb_side);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_rr_node* cur_rr_node);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_one_side_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
const RRGSB& rr_gsb, enum e_side cb_side);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_one_side_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
int num_ipin_rr_nodes,
|
|
||||||
t_rr_node** ipin_rr_node);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
const RRGSB& rr_gsb, t_rr_type cb_type);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_one_side_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
int num_ipin_rr_nodes,
|
|
||||||
t_rr_node** ipin_rr_node);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
const RRGSB& rr_gsb, t_rr_type cb_type);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_cb* cur_cb_info);
|
|
||||||
|
|
||||||
int count_verilog_connection_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_cb* cur_cb_info);
|
|
||||||
|
|
||||||
void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir, char* subckt_dir,
|
|
||||||
t_cb* cur_cb_info,
|
|
||||||
boolean compact_routing_hierarchy,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void print_verilog_routing_resources(ModuleManager& module_manager,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir,
|
|
||||||
char* subckt_dir,
|
|
||||||
const t_arch& arch,
|
|
||||||
const t_det_routing_arch& routing_arch,
|
|
||||||
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,
|
|
||||||
const t_fpga_spice_opts& FPGA_SPICE_Opts);
|
|
||||||
|
|
||||||
void print_verilog_flatten_routing_modules(ModuleManager& module_manager,
|
void print_verilog_flatten_routing_modules(ModuleManager& module_manager,
|
||||||
const DeviceRRGSB& L_device_rr_gsb,
|
const DeviceRRGSB& L_device_rr_gsb,
|
||||||
const t_det_routing_arch& routing_arch,
|
const t_det_routing_arch& routing_arch,
|
||||||
|
|
|
@ -1,859 +0,0 @@
|
||||||
/***********************************/
|
|
||||||
/* SPICE Modeling for VPR */
|
|
||||||
/* Xifan TANG, EPFL/LSI */
|
|
||||||
/***********************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/* 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 "route_common.h"
|
|
||||||
#include "vpr_utils.h"
|
|
||||||
|
|
||||||
#include "rr_graph_builder_utils.h"
|
|
||||||
|
|
||||||
/* Include SPICE support headers*/
|
|
||||||
#include "linkedlist.h"
|
|
||||||
#include "fpga_x2p_types.h"
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
#include "fpga_x2p_backannotate_utils.h"
|
|
||||||
#include "fpga_x2p_mux_utils.h"
|
|
||||||
#include "fpga_x2p_pbtypes_utils.h"
|
|
||||||
#include "fpga_x2p_bitstream_utils.h"
|
|
||||||
#include "fpga_x2p_rr_graph_utils.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
|
|
||||||
/* Include Verilog support headers*/
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
#include "verilog_routing.h"
|
|
||||||
|
|
||||||
#include "verilog_tcl_utils.h"
|
|
||||||
|
|
||||||
/***** Subroutine Functions *****/
|
|
||||||
void dump_verilog_sdc_file_header(FILE* fp,
|
|
||||||
char* usage) {
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s, LINE[%d]) FileHandle is NULL!\n",__FILE__,__LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
fprintf(fp,"#############################################\n");
|
|
||||||
fprintf(fp,"# Synopsys Design Constraints (SDC) # \n");
|
|
||||||
fprintf(fp,"# FPGA Synthesizable Verilog Netlist # \n");
|
|
||||||
fprintf(fp,"# Description: %s \n",usage);
|
|
||||||
fprintf(fp,"# Author: Xifan TANG # \n");
|
|
||||||
fprintf(fp,"# Organization: EPFL/IC/LSI # \n");
|
|
||||||
fprintf(fp,"# Date: %s \n", my_gettime());
|
|
||||||
fprintf(fp,"#############################################\n");
|
|
||||||
fprintf(fp,"\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_verilog_one_sb_chan_pin(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
enum PORTS port_type) {
|
|
||||||
int track_idx;
|
|
||||||
enum e_side side;
|
|
||||||
char* pin_name;
|
|
||||||
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert ((CHANX == cur_rr_node->type)
|
|
||||||
||(CHANY == cur_rr_node->type));
|
|
||||||
/* Get the coordinate of chanx or chany*/
|
|
||||||
/* Find the coordinate of the cur_rr_node */
|
|
||||||
rr_sb.get_node_side_and_index(cur_rr_node, port_type, &side, &track_idx);
|
|
||||||
|
|
||||||
/* FIXME: we should avoid using global variables !!!! */
|
|
||||||
/* If we have an mirror SB, we should the module name of the mirror !!! */
|
|
||||||
DeviceCoordinator coordinator = rr_sb.get_sb_coordinator();
|
|
||||||
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(coordinator);
|
|
||||||
DeviceCoordinator chan_coordinator = unique_mirror.get_side_block_coordinator(side);
|
|
||||||
|
|
||||||
/* Print the pin of the cur_rr_node */
|
|
||||||
pin_name = gen_verilog_routing_channel_one_pin_name(cur_rr_node,
|
|
||||||
chan_coordinator.get_x(),
|
|
||||||
chan_coordinator.get_y(),
|
|
||||||
track_idx,
|
|
||||||
port_type);
|
|
||||||
fprintf(fp, "%s", pin_name);
|
|
||||||
my_free(pin_name);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void dump_verilog_one_sb_chan_pin(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
enum PORTS port_type) {
|
|
||||||
int track_idx, side;
|
|
||||||
int x_start, y_start;
|
|
||||||
char* pin_name;
|
|
||||||
t_rr_type chan_rr_type;
|
|
||||||
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
assert ((CHANX == cur_rr_node->type)
|
|
||||||
||(CHANY == cur_rr_node->type));
|
|
||||||
/* Get the coordinate of chanx or chany*/
|
|
||||||
/* Find the coordinate of the cur_rr_node */
|
|
||||||
get_rr_node_side_and_index_in_sb_info(cur_rr_node,
|
|
||||||
*cur_sb_info,
|
|
||||||
port_type, &side, &track_idx);
|
|
||||||
get_chan_rr_node_coordinate_in_sb_info(*cur_sb_info, side,
|
|
||||||
&(chan_rr_type),
|
|
||||||
&x_start, &y_start);
|
|
||||||
assert (chan_rr_type == cur_rr_node->type);
|
|
||||||
/* Print the pin of the cur_rr_node */
|
|
||||||
pin_name = gen_verilog_routing_channel_one_pin_name(cur_rr_node,
|
|
||||||
x_start, y_start, track_idx,
|
|
||||||
port_type);
|
|
||||||
fprintf(fp, "%s", pin_name);
|
|
||||||
free(pin_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output the pin name of a routing wire in a SB */
|
|
||||||
void dump_verilog_one_sb_routing_pin(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
bool is_explicit_mapping) {
|
|
||||||
int side;
|
|
||||||
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the top-level pin name and print it out */
|
|
||||||
/* Depends on the type of node */
|
|
||||||
switch (cur_rr_node->type) {
|
|
||||||
case OPIN: {
|
|
||||||
/* Identify the side of OPIN on a grid */
|
|
||||||
side = get_grid_pin_side(cur_rr_node->xlow, cur_rr_node->ylow, cur_rr_node->ptc_num);
|
|
||||||
assert (OPEN != side);
|
|
||||||
|
|
||||||
/* FIXME: we should avoid using global variables !!!! */
|
|
||||||
/* If we have an mirror SB, we should the module name of the mirror !!! */
|
|
||||||
DeviceCoordinator coordinator = rr_sb.get_sb_coordinator();
|
|
||||||
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(coordinator);
|
|
||||||
enum e_side pin_gsb_side = NUM_SIDES;
|
|
||||||
int pin_node_id = -1;
|
|
||||||
/* We get the index and side for the cur_rr_node in the mother rr_sb context */
|
|
||||||
rr_sb.get_node_side_and_index(cur_rr_node, IN_PORT, &pin_gsb_side, &pin_node_id);
|
|
||||||
/* Make sure we have valid numbers */
|
|
||||||
assert ( (NUM_SIDES != pin_gsb_side) && (-1 != pin_node_id) );
|
|
||||||
/* We get rr_node with the same index and side in the unique mirror context */
|
|
||||||
t_rr_node* mirror_node = unique_mirror.get_opin_node(pin_gsb_side, pin_node_id);
|
|
||||||
|
|
||||||
/* Identify the side of OPIN on a grid */
|
|
||||||
side = get_grid_pin_side(mirror_node->xlow, mirror_node->ylow, mirror_node->ptc_num);
|
|
||||||
assert (OPEN != side);
|
|
||||||
|
|
||||||
dump_verilog_grid_side_pin_with_given_index(fp, OPIN,
|
|
||||||
mirror_node->ptc_num,
|
|
||||||
side,
|
|
||||||
mirror_node->xlow,
|
|
||||||
mirror_node->ylow,
|
|
||||||
0, /*Used in newer version*/
|
|
||||||
0, /*Used in newer version*/
|
|
||||||
FALSE,is_explicit_mapping); /* Do not specify direction of port */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CHANX:
|
|
||||||
case CHANY:
|
|
||||||
dump_verilog_one_sb_chan_pin(fp, rr_sb, cur_rr_node, IN_PORT);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of ending point rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Output the pin name of a routing wire in a SB */
|
|
||||||
void dump_verilog_one_sb_routing_pin(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
bool is_explicit_mapping) {
|
|
||||||
int side;
|
|
||||||
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the top-level pin name and print it out */
|
|
||||||
/* Depends on the type of node */
|
|
||||||
switch (cur_rr_node->type) {
|
|
||||||
case OPIN:
|
|
||||||
/* Identify the side of OPIN on a grid */
|
|
||||||
side = get_grid_pin_side(cur_rr_node->xlow, cur_rr_node->ylow, cur_rr_node->ptc_num);
|
|
||||||
assert (OPEN != side);
|
|
||||||
dump_verilog_grid_side_pin_with_given_index(fp, OPIN,
|
|
||||||
cur_rr_node->ptc_num,
|
|
||||||
side,
|
|
||||||
cur_rr_node->xlow,
|
|
||||||
cur_rr_node->ylow,
|
|
||||||
0, /*Used in newer version*/
|
|
||||||
0, /*Used in newer version*/
|
|
||||||
FALSE, is_explicit_mapping); /* Do not specify direction of port */
|
|
||||||
break;
|
|
||||||
case CHANX:
|
|
||||||
case CHANY:
|
|
||||||
dump_verilog_one_sb_chan_pin(fp, cur_sb_info, cur_rr_node, IN_PORT);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of ending point rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Given a starting rr_node (CHANX or CHANY)
|
|
||||||
* and a ending rr_node (IPIN)
|
|
||||||
* return the cb contains both (the ending CB of the routing wire)
|
|
||||||
*/
|
|
||||||
DeviceCoordinator get_chan_node_ending_cb(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node) {
|
|
||||||
int next_cb_x, next_cb_y;
|
|
||||||
std::vector<enum e_side> ipin_side;
|
|
||||||
enum e_side chan_side;
|
|
||||||
t_rr_type cb_type;
|
|
||||||
|
|
||||||
/* Type of connection block depends on the src_rr_node */
|
|
||||||
switch (src_rr_node->type) {
|
|
||||||
case CHANX:
|
|
||||||
/* the x of CB is same as end_rr_node,
|
|
||||||
* the y of CB should be same as src_rr_node
|
|
||||||
*/
|
|
||||||
assert (end_rr_node->xlow == end_rr_node->xhigh);
|
|
||||||
next_cb_x = end_rr_node->xlow;
|
|
||||||
assert (src_rr_node->ylow == src_rr_node->yhigh);
|
|
||||||
next_cb_y = src_rr_node->ylow;
|
|
||||||
cb_type = CHANX;
|
|
||||||
break;
|
|
||||||
case CHANY:
|
|
||||||
/* the x of CB is same as src_rr_node,
|
|
||||||
* the y of CB should be same as end_rr_node
|
|
||||||
*/
|
|
||||||
assert (src_rr_node->xlow == src_rr_node->xhigh);
|
|
||||||
next_cb_x = src_rr_node->xlow;
|
|
||||||
assert (end_rr_node->ylow == end_rr_node->yhigh);
|
|
||||||
next_cb_y = end_rr_node->ylow;
|
|
||||||
cb_type = CHANY;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(File: %s [LINE%d]) Invalid type of src_rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceCoordinator next_cb_coordinator(next_cb_x, next_cb_y);
|
|
||||||
/* IMPORTANT: the use of global variables should be removed!!! */
|
|
||||||
const RRGSB& next_cb = device_rr_gsb.get_gsb(next_cb_coordinator);
|
|
||||||
/* Side will be either on TOP or BOTTOM */
|
|
||||||
ipin_side = next_cb.get_cb_ipin_sides(cb_type);
|
|
||||||
chan_side = next_cb.get_cb_chan_side(cb_type);
|
|
||||||
|
|
||||||
/* Double check if src_rr_node is in the IN_PORT list */
|
|
||||||
assert ( (OPEN != next_cb.get_node_index( src_rr_node, chan_side, IN_PORT))
|
|
||||||
|| (OPEN != next_cb.get_node_index( src_rr_node, chan_side, OUT_PORT)) );
|
|
||||||
|
|
||||||
/* Double check if end_rr_node is in the OUT_PORT list */
|
|
||||||
bool node_exist = false;
|
|
||||||
for (size_t iside = 0; iside < ipin_side.size(); ++iside) {
|
|
||||||
if (OPEN != next_cb.get_node_index(end_rr_node, ipin_side[iside], OUT_PORT)) {
|
|
||||||
node_exist = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert (true == node_exist);
|
|
||||||
|
|
||||||
return next_cb_coordinator;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Given a starting rr_node (CHANX or CHANY)
|
|
||||||
* and a ending rr_node (IPIN)
|
|
||||||
* return the cb contains both (the ending CB of the routing wire)
|
|
||||||
*/
|
|
||||||
t_cb* get_chan_rr_node_ending_cb(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node) {
|
|
||||||
int num_ipin_sides = 2;
|
|
||||||
int* ipin_side = (int*)my_calloc(num_ipin_sides, sizeof(int));
|
|
||||||
int num_chan_sides = 2;
|
|
||||||
int* chan_side = (int*)my_calloc(num_chan_sides, sizeof(int));
|
|
||||||
int iside, next_cb_x, next_cb_y;
|
|
||||||
int node_exist;
|
|
||||||
t_cb* next_cb = NULL;
|
|
||||||
|
|
||||||
/* Type of connection block depends on the src_rr_node */
|
|
||||||
switch (src_rr_node->type) {
|
|
||||||
case CHANX:
|
|
||||||
/* the x of CB is same as end_rr_node,
|
|
||||||
* the y of CB should be same as src_rr_node
|
|
||||||
*/
|
|
||||||
assert (end_rr_node->xlow == end_rr_node->xhigh);
|
|
||||||
next_cb_x = end_rr_node->xlow;
|
|
||||||
assert (src_rr_node->ylow == src_rr_node->yhigh);
|
|
||||||
next_cb_y = src_rr_node->ylow;
|
|
||||||
/* Side will be either on TOP or BOTTOM */
|
|
||||||
ipin_side[0] = TOP;
|
|
||||||
ipin_side[1] = BOTTOM;
|
|
||||||
chan_side[0] = RIGHT;
|
|
||||||
chan_side[1] = LEFT;
|
|
||||||
next_cb = &(cbx_info[next_cb_x][next_cb_y]);
|
|
||||||
break;
|
|
||||||
case CHANY:
|
|
||||||
/* the x of CB is same as src_rr_node,
|
|
||||||
* the y of CB should be same as end_rr_node
|
|
||||||
*/
|
|
||||||
assert (src_rr_node->xlow == src_rr_node->xhigh);
|
|
||||||
next_cb_x = src_rr_node->xlow;
|
|
||||||
/* Heterogeneous blocks may have ylow != yhigh */
|
|
||||||
if (IPIN != end_rr_node->type) {
|
|
||||||
assert (end_rr_node->ylow == end_rr_node->yhigh);
|
|
||||||
}
|
|
||||||
next_cb_y = end_rr_node->yhigh;
|
|
||||||
/* Side will be either on RIGHT or LEFT */
|
|
||||||
ipin_side[0] = LEFT;
|
|
||||||
ipin_side[1] = RIGHT;
|
|
||||||
chan_side[0] = BOTTOM;
|
|
||||||
chan_side[1] = TOP;
|
|
||||||
next_cb = &(cby_info[next_cb_x][next_cb_y]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(File: %s [LINE%d]) Invalid type of src_rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Double check if src_rr_node is in the IN_PORT list */
|
|
||||||
/* TODO: this part should be refactored!
|
|
||||||
node_exist = 0;
|
|
||||||
for (iside = 0; iside < num_chan_sides; iside++) {
|
|
||||||
if (OPEN != get_rr_node_index_in_cb_info( src_rr_node,
|
|
||||||
*next_cb,
|
|
||||||
chan_side[iside], IN_PORT)) {
|
|
||||||
node_exist++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert (0 < node_exist);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Double check if end_rr_node is in the OUT_PORT list */
|
|
||||||
/* TODO: this part should be refactored!
|
|
||||||
node_exist = 0;
|
|
||||||
for (iside = 0; iside < num_ipin_sides; iside++) {
|
|
||||||
if (OPEN != get_rr_node_index_in_cb_info( end_rr_node,
|
|
||||||
*next_cb,
|
|
||||||
ipin_side[iside], OUT_PORT)) {
|
|
||||||
node_exist++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert (0 < node_exist);
|
|
||||||
*/
|
|
||||||
|
|
||||||
return next_cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Given a starting rr_node (CHANX or CHANY)
|
|
||||||
* return the sb contains both (the ending CB of the routing wire)
|
|
||||||
*/
|
|
||||||
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node) {
|
|
||||||
/* Get the coordinator where the node ends */
|
|
||||||
DeviceCoordinator end_coordinator = get_track_rr_node_end_coordinator(src_rr_node);
|
|
||||||
/* Initilizae the SB coordinator where the node ends */
|
|
||||||
DeviceCoordinator sb_coordinator;
|
|
||||||
|
|
||||||
/* Case 1:
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* src_rr_node ------>| next_sb |-------> end_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
if ( (CHANX == src_rr_node->type)
|
|
||||||
&& (INC_DIRECTION == src_rr_node->direction) ) {
|
|
||||||
/* SB coordinator is the same as src rr_node */
|
|
||||||
sb_coordinator.set(end_coordinator.get_x(), end_coordinator.get_y());
|
|
||||||
}
|
|
||||||
/* Case 2
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |<-------- src_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
if ( (CHANX == src_rr_node->type)
|
|
||||||
&& (DEC_DIRECTION == src_rr_node->direction) ) {
|
|
||||||
/* SB coordinator is the [x-1][y] */
|
|
||||||
sb_coordinator.set(end_coordinator.get_x() - 1, end_coordinator.get_y());
|
|
||||||
}
|
|
||||||
/* Case 3
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |-------> src_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* src_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
if ( (CHANY == src_rr_node->type)
|
|
||||||
&& (INC_DIRECTION == src_rr_node->direction) ) {
|
|
||||||
/* SB coordinator is the same */
|
|
||||||
sb_coordinator.set(end_coordinator.get_x(), end_coordinator.get_y());
|
|
||||||
}
|
|
||||||
/* Case 4
|
|
||||||
* src_rr_node(chany[x][y+1])
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |--------> end_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
if ( (CHANY == src_rr_node->type)
|
|
||||||
&& (DEC_DIRECTION == src_rr_node->direction) ) {
|
|
||||||
/* SB coordinator is the [x][y-1] */
|
|
||||||
sb_coordinator.set(end_coordinator.get_x(), end_coordinator.get_y() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const RRGSB& rr_sb = device_rr_gsb.get_gsb(sb_coordinator);
|
|
||||||
/* Double check if src_rr_node is in the list */
|
|
||||||
enum e_side side;
|
|
||||||
int index;
|
|
||||||
rr_sb.get_node_side_and_index(src_rr_node, IN_PORT, &side, &index);
|
|
||||||
assert ( (OPEN != index) && (side != NUM_SIDES) );
|
|
||||||
|
|
||||||
/* Passing the check, assign coordinator of next_sb */
|
|
||||||
|
|
||||||
return sb_coordinator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Given a starting rr_node (CHANX or CHANY)
|
|
||||||
* and a ending rr_node (IPIN)
|
|
||||||
* return the sb contains both (the ending CB of the routing wire)
|
|
||||||
*/
|
|
||||||
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node) {
|
|
||||||
int x_start, y_start;
|
|
||||||
int x_end, y_end;
|
|
||||||
int next_sb_x, next_sb_y;
|
|
||||||
|
|
||||||
get_chan_rr_node_start_coordinate(src_rr_node, &x_start, &y_start);
|
|
||||||
get_chan_rr_node_start_coordinate(end_rr_node, &x_end, &y_end);
|
|
||||||
|
|
||||||
/* Case 1:
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* src_rr_node ------>| next_sb |-------> end_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
/* Case 2
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |<-------- src_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
/* Case 3
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |-------> src_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* src_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
/* Case 4
|
|
||||||
* src_rr_node(chany[x][y+1])
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |--------> end_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Try the xlow, ylow of ending rr_node */
|
|
||||||
switch (src_rr_node->type) {
|
|
||||||
case CHANX:
|
|
||||||
next_sb_x = x_end;
|
|
||||||
next_sb_y = y_start;
|
|
||||||
break;
|
|
||||||
case CHANY:
|
|
||||||
next_sb_x = x_start;
|
|
||||||
next_sb_y = y_end;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (src_rr_node->direction) {
|
|
||||||
case INC_DIRECTION:
|
|
||||||
get_chan_rr_node_end_coordinate(src_rr_node, &x_end, &y_end);
|
|
||||||
if (next_sb_x > x_end) {
|
|
||||||
next_sb_x = x_end;
|
|
||||||
}
|
|
||||||
if (next_sb_y > y_end) {
|
|
||||||
next_sb_y = y_end;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEC_DIRECTION:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceCoordinator sb_coordinator(next_sb_x, next_sb_y);
|
|
||||||
const RRGSB& rr_sb = device_rr_gsb.get_gsb(sb_coordinator);
|
|
||||||
/* Double check if src_rr_node is in the list */
|
|
||||||
enum e_side side;
|
|
||||||
int index;
|
|
||||||
rr_sb.get_node_side_and_index(src_rr_node, IN_PORT, &side, &index);
|
|
||||||
assert ( (OPEN != index) && (side != NUM_SIDES) );
|
|
||||||
|
|
||||||
/* Double check if end_rr_node is in the list */
|
|
||||||
rr_sb.get_node_side_and_index(end_rr_node, OUT_PORT, &side, &index);
|
|
||||||
assert ( (OPEN != index) && (side != NUM_SIDES) );
|
|
||||||
|
|
||||||
/* Passing the check, assign coordinator of next_sb */
|
|
||||||
|
|
||||||
return sb_coordinator;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Given a starting rr_node (CHANX or CHANY)
|
|
||||||
* and a ending rr_node (IPIN)
|
|
||||||
* return the sb contains both (the ending CB of the routing wire)
|
|
||||||
*/
|
|
||||||
t_sb* get_chan_rr_node_ending_sb(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node) {
|
|
||||||
int side;
|
|
||||||
int x_start, y_start;
|
|
||||||
int x_end, y_end;
|
|
||||||
int next_sb_x, next_sb_y;
|
|
||||||
int node_exist;
|
|
||||||
t_sb* next_sb = NULL;
|
|
||||||
|
|
||||||
get_chan_rr_node_start_coordinate(src_rr_node, &x_start, &y_start);
|
|
||||||
get_chan_rr_node_start_coordinate(end_rr_node, &x_end, &y_end);
|
|
||||||
|
|
||||||
/* Case 1:
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* src_rr_node ------>| next_sb |-------> end_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
/* Case 2
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |<-------- src_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
/* Case 3
|
|
||||||
* end_rr_node(chany[x][y+1])
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |-------> src_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* src_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
/* Case 4
|
|
||||||
* src_rr_node(chany[x][y+1])
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* ---------
|
|
||||||
* | |
|
|
||||||
* end_rr_node <------| next_sb |--------> end_rr_node
|
|
||||||
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
|
|
||||||
* ---------
|
|
||||||
* |
|
|
||||||
* \|/
|
|
||||||
* end_rr_node(chany[x][y])
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Try the xlow, ylow of ending rr_node */
|
|
||||||
switch (src_rr_node->type) {
|
|
||||||
case CHANX:
|
|
||||||
next_sb_x = x_end;
|
|
||||||
next_sb_y = y_start;
|
|
||||||
break;
|
|
||||||
case CHANY:
|
|
||||||
next_sb_x = x_start;
|
|
||||||
next_sb_y = y_end;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (src_rr_node->direction) {
|
|
||||||
case INC_DIRECTION:
|
|
||||||
get_chan_rr_node_end_coordinate(src_rr_node, &x_end, &y_end);
|
|
||||||
if (next_sb_x > x_end) {
|
|
||||||
next_sb_x = x_end;
|
|
||||||
}
|
|
||||||
if (next_sb_y > y_end) {
|
|
||||||
next_sb_y = y_end;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DEC_DIRECTION:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Double check if src_rr_node is in the list */
|
|
||||||
node_exist = 0;
|
|
||||||
for (side = 0; side < 4; side++) {
|
|
||||||
if( OPEN != get_rr_node_index_in_sb_info(src_rr_node,
|
|
||||||
sb_info[next_sb_x][next_sb_y],
|
|
||||||
side, IN_PORT)) {
|
|
||||||
node_exist++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert (1 == node_exist);
|
|
||||||
|
|
||||||
/* Double check if end_rr_node is in the list */
|
|
||||||
node_exist = 0;
|
|
||||||
for (side = 0; side < 4; side++) {
|
|
||||||
if (OPEN != get_rr_node_index_in_sb_info(end_rr_node,
|
|
||||||
sb_info[next_sb_x][next_sb_y],
|
|
||||||
side, OUT_PORT)) {
|
|
||||||
node_exist++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (1 != node_exist) {
|
|
||||||
assert (1 == node_exist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Passing the check, assign ending sb */
|
|
||||||
next_sb = &(sb_info[next_sb_x][next_sb_y]);
|
|
||||||
|
|
||||||
return next_sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the disabled timing for the sb wire */
|
|
||||||
void restore_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* wire_rr_node) {
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( ( CHANX == wire_rr_node->type )
|
|
||||||
|| ( CHANY == wire_rr_node->type ));
|
|
||||||
|
|
||||||
/* Restore disabled timing for wire_rr_node as an SB output */
|
|
||||||
fprintf(fp, "reset_disable_timing ");
|
|
||||||
/* output instance name */
|
|
||||||
fprintf(fp, "%s/",
|
|
||||||
rr_sb.gen_sb_verilog_instance_name());
|
|
||||||
dump_verilog_one_sb_chan_pin(fp, rr_sb, wire_rr_node, OUT_PORT);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the disabled timing for the sb wire */
|
|
||||||
void restore_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* wire_rr_node) {
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( ( CHANX == wire_rr_node->type )
|
|
||||||
|| ( CHANY == wire_rr_node->type ));
|
|
||||||
|
|
||||||
/* Restore disabled timing for wire_rr_node as an SB output */
|
|
||||||
fprintf(fp, "reset_disable_timing ");
|
|
||||||
/* output instance name */
|
|
||||||
fprintf(fp, "%s/",
|
|
||||||
gen_verilog_one_sb_instance_name(cur_sb_info));
|
|
||||||
dump_verilog_one_sb_chan_pin(fp, cur_sb_info, wire_rr_node, OUT_PORT);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the disabled timing for the sb wire */
|
|
||||||
void set_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* wire_rr_node) {
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( ( CHANX == wire_rr_node->type )
|
|
||||||
|| ( CHANY == wire_rr_node->type ));
|
|
||||||
|
|
||||||
/* Restore disabled timing for wire_rr_node as an SB output */
|
|
||||||
fprintf(fp, "set_disable_timing ");
|
|
||||||
/* output instance name */
|
|
||||||
fprintf(fp, "%s/",
|
|
||||||
rr_sb.gen_sb_verilog_instance_name());
|
|
||||||
|
|
||||||
dump_verilog_one_sb_chan_pin(fp, rr_sb, wire_rr_node, OUT_PORT);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the disabled timing for the sb wire */
|
|
||||||
void set_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* wire_rr_node) {
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( ( CHANX == wire_rr_node->type )
|
|
||||||
|| ( CHANY == wire_rr_node->type ));
|
|
||||||
|
|
||||||
/* Restore disabled timing for wire_rr_node as an SB output */
|
|
||||||
fprintf(fp, "set_disable_timing ");
|
|
||||||
/* output instance name */
|
|
||||||
fprintf(fp, "%s/",
|
|
||||||
gen_verilog_one_sb_instance_name(cur_sb_info));
|
|
||||||
dump_verilog_one_sb_chan_pin(fp, cur_sb_info, wire_rr_node, OUT_PORT);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
#ifndef VERILOG_TCL_UTILS_H
|
|
||||||
#define VERILOG_TCL_UTILS_H
|
|
||||||
|
|
||||||
/* Include header files that require by the function declared in the following lines !!!*/
|
|
||||||
#include "device_coordinator.h"
|
|
||||||
#include "rr_blocks.h"
|
|
||||||
|
|
||||||
void dump_verilog_sdc_file_header(FILE* fp,
|
|
||||||
char* usage);
|
|
||||||
|
|
||||||
void dump_verilog_one_sb_chan_pin(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
enum PORTS port_type);
|
|
||||||
|
|
||||||
void dump_verilog_one_sb_chan_pin(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
enum PORTS port_type);
|
|
||||||
|
|
||||||
void dump_verilog_one_sb_routing_pin(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_one_sb_routing_pin(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* cur_rr_node,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
DeviceCoordinator get_chan_node_ending_cb(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node);
|
|
||||||
|
|
||||||
t_cb* get_chan_rr_node_ending_cb(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node);
|
|
||||||
|
|
||||||
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node);
|
|
||||||
|
|
||||||
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node);
|
|
||||||
|
|
||||||
t_sb* get_chan_rr_node_ending_sb(t_rr_node* src_rr_node,
|
|
||||||
t_rr_node* end_rr_node);
|
|
||||||
|
|
||||||
void restore_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* wire_rr_node);
|
|
||||||
|
|
||||||
void restore_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* wire_rr_node);
|
|
||||||
|
|
||||||
void set_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
const RRGSB& rr_sb,
|
|
||||||
t_rr_node* wire_rr_node);
|
|
||||||
|
|
||||||
void set_disable_timing_one_sb_output(FILE* fp,
|
|
||||||
t_sb* cur_sb_info,
|
|
||||||
t_rr_node* wire_rr_node);
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue