remove legacy codes in FPGA-Verilog
This commit is contained in:
parent
0dd72999d5
commit
322228de43
|
@ -1,406 +0,0 @@
|
||||||
/***********************************/
|
|
||||||
/* Dump Synthesizable Veriolog */
|
|
||||||
/* 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 "route_common.h"
|
|
||||||
#include "vpr_utils.h"
|
|
||||||
|
|
||||||
/* Include spice support headers*/
|
|
||||||
#include "read_xml_spice_util.h"
|
|
||||||
#include "linkedlist.h"
|
|
||||||
#include "fpga_x2p_types.h"
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
#include "fpga_x2p_pbtypes_utils.h"
|
|
||||||
#include "fpga_x2p_backannotate_utils.h"
|
|
||||||
#include "fpga_x2p_bitstream_utils.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
#include "fpga_bitstream.h"
|
|
||||||
|
|
||||||
/* Include verilog support headers*/
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
#include "verilog_routing.h"
|
|
||||||
#include "verilog_pbtypes.h"
|
|
||||||
#include "verilog_decoder.h"
|
|
||||||
#include "verilog_top_netlist_utils.h"
|
|
||||||
#include "verilog_top_testbench.h"
|
|
||||||
|
|
||||||
#include "verilog_autocheck_top_testbench.h"
|
|
||||||
|
|
||||||
/* Local variables */
|
|
||||||
static char* autocheck_testbench_reference_output_postfix = "_benchmark";
|
|
||||||
static char* autocheck_testbench_verification_output_postfix = "_verification";
|
|
||||||
static char* error_counter = "nb_error";
|
|
||||||
|
|
||||||
/* Local Subroutines declaration */
|
|
||||||
|
|
||||||
/******** Subroutines ***********/
|
|
||||||
static
|
|
||||||
void dump_verilog_top_auto_testbench_ports(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* circuit_name,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts){
|
|
||||||
int num_array_bl, num_array_wl;
|
|
||||||
int bl_decoder_size, wl_decoder_size;
|
|
||||||
int iblock, iopad_idx;
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
char* port_name = NULL;
|
|
||||||
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
|
|
||||||
fprintf(fp, "`include \"%s\"\n", fpga_verilog_opts.reference_verilog_benchmark_file);
|
|
||||||
|
|
||||||
fprintf(fp, "module %s%s;\n", circuit_name, modelsim_autocheck_testbench_module_postfix);
|
|
||||||
/* Local wires */
|
|
||||||
/* 1. reset, set, clock signals */
|
|
||||||
/* 2. iopad signals */
|
|
||||||
|
|
||||||
/* Connect to defined signals */
|
|
||||||
/* set and reset signals */
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
dump_verilog_top_testbench_global_ports(fp, global_ports_head, VERILOG_PORT_WIRE);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
/* TODO: dump each global signal as reg here */
|
|
||||||
|
|
||||||
/* Inputs and outputs of I/O pads */
|
|
||||||
/* Inout Pads */
|
|
||||||
assert(NULL != iopad_verilog_model);
|
|
||||||
if ((NULL == iopad_verilog_model)
|
|
||||||
||(iopad_verilog_model->cnt > 0)) {
|
|
||||||
/* Malloc and assign port_name */
|
|
||||||
port_name = (char*)my_malloc(sizeof(char)*(strlen(gio_inout_prefix) + strlen(iopad_verilog_model->prefix) + 1));
|
|
||||||
sprintf(port_name, "%s%s", gio_inout_prefix, iopad_verilog_model->prefix);
|
|
||||||
/* Dump a wired port */
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
port_name, iopad_verilog_model->cnt - 1, 0);
|
|
||||||
fprintf(fp, "; //--- FPGA inouts \n");
|
|
||||||
/* Free port_name */
|
|
||||||
my_free(port_name);
|
|
||||||
/* Malloc and assign port_name */
|
|
||||||
port_name = (char*)my_malloc(sizeof(char)*(strlen(gio_inout_prefix) + strlen(iopad_verilog_model->prefix) + strlen(top_tb_inout_reg_postfix) + 1));
|
|
||||||
sprintf(port_name, "%s%s%s", gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix);
|
|
||||||
/* Dump a wired port */
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
|
||||||
port_name, iopad_verilog_model->cnt - 1, 0);
|
|
||||||
fprintf(fp, "; //--- reg for FPGA inouts \n");
|
|
||||||
/* Free port_name */
|
|
||||||
my_free(port_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a signal to identify the configuration phase is finished */
|
|
||||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_config_done_port_name);
|
|
||||||
/* Programming clock */
|
|
||||||
fprintf(fp, "wire [0:0] %s;\n", top_tb_prog_clock_port_name);
|
|
||||||
fprintf(fp, "reg [0:0] %s%s;\n", top_tb_prog_clock_port_name, top_tb_clock_reg_postfix);
|
|
||||||
/* Operation clock */
|
|
||||||
fprintf(fp, "wire [0:0] %s;\n", top_tb_op_clock_port_name);
|
|
||||||
fprintf(fp, "reg [0:0] %s%s;\n", top_tb_op_clock_port_name, top_tb_clock_reg_postfix);
|
|
||||||
/* Programming set and reset */
|
|
||||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_prog_reset_port_name);
|
|
||||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_prog_set_port_name);
|
|
||||||
/* Global set and reset */
|
|
||||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_reset_port_name);
|
|
||||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_set_port_name);
|
|
||||||
/* Generate stimuli for global ports or connect them to existed signals */
|
|
||||||
dump_verilog_top_testbench_global_ports_stimuli(fp, global_ports_head);
|
|
||||||
|
|
||||||
/* Configuration ports depend on the organization of SRAMs */
|
|
||||||
switch(cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
sram_verilog_model->prefix, sram_verilog_model->cnt - 1, 0);
|
|
||||||
fprintf(fp, "; //---- SRAM outputs \n");
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
/* We put the head of scan-chains here
|
|
||||||
*/
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
|
||||||
top_netlist_scan_chain_head_prefix, 0, 0);
|
|
||||||
fprintf(fp, "; //---- Scan-chain head \n");
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* Get the number of array BLs/WLs, decoder sizes */
|
|
||||||
determine_blwl_decoder_size(cur_sram_orgz_info,
|
|
||||||
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
|
|
||||||
|
|
||||||
fprintf(fp, " wire [0:0] %s;\n",
|
|
||||||
top_netlist_bl_enable_port_name);
|
|
||||||
fprintf(fp, " wire [0:0] %s;\n",
|
|
||||||
top_netlist_wl_enable_port_name);
|
|
||||||
/* Wire en_bl, en_wl to prog_clock */
|
|
||||||
fprintf(fp, "assign %s[0:0] = %s[0:0];\n",
|
|
||||||
top_netlist_bl_enable_port_name,
|
|
||||||
top_tb_prog_clock_port_name);
|
|
||||||
fprintf(fp, "assign %s [0:0]= %s[0:0];\n",
|
|
||||||
top_netlist_wl_enable_port_name,
|
|
||||||
top_tb_prog_clock_port_name);
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
|
||||||
top_netlist_addr_bl_port_name, bl_decoder_size - 1, 0);
|
|
||||||
fprintf(fp, "; //--- Address of bit lines \n");
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
|
||||||
top_netlist_addr_wl_port_name, wl_decoder_size - 1, 0);
|
|
||||||
fprintf(fp, "; //--- Address of word lines \n");
|
|
||||||
/* data_in is only require by BL decoder of SRAM array
|
|
||||||
* As for RRAM array, the data_in signal will not be used
|
|
||||||
*/
|
|
||||||
if (SPICE_MODEL_DESIGN_CMOS == mem_model->design_tech) {
|
|
||||||
fprintf(fp, " reg [0:0] %s; // --- Data_in signal for BL decoder, only required by SRAM array \n",
|
|
||||||
top_netlist_bl_data_in_port_name);
|
|
||||||
}
|
|
||||||
/* I add all the Bit lines and Word lines here just for testbench usage
|
|
||||||
fprintf(fp, " input wire [%d:0] %s_out; //--- Bit lines \n",
|
|
||||||
sram_verilog_model->cnt - 1, sram_verilog_model->prefix);
|
|
||||||
fprintf(fp, " input wire [%d:0] %s_outb; //--- Word lines \n",
|
|
||||||
sram_verilog_model->cnt - 1, sram_verilog_model->prefix);
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add signals from blif benchmark and short-wire them to FPGA I/O PADs
|
|
||||||
* This brings convenience to checking functionality
|
|
||||||
*/
|
|
||||||
fprintf(fp, "//-----Link Blif Benchmark inputs to FPGA IOPADs -----\n");
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
/* General INOUT*/
|
|
||||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
|
||||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
|
||||||
/* Make sure We find the correct logical block !*/
|
|
||||||
assert((VPACK_INPAD == logical_block[iblock].type)
|
|
||||||
||(VPACK_OUTPAD == logical_block[iblock].type));
|
|
||||||
fprintf(fp, "//----- Blif Benchmark inout %s is mapped to FPGA IOPAD %s[%d] -----\n",
|
|
||||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
|
||||||
fprintf(fp, "wire %s_%s_%d_;\n",
|
|
||||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
|
||||||
fprintf(fp, "assign %s_%s_%d_ = %s%s[%d];\n",
|
|
||||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx,
|
|
||||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx);
|
|
||||||
// AA: Generate wire and reg to autocheck with benchmark
|
|
||||||
if(VPACK_OUTPAD == logical_block[iblock].type) {
|
|
||||||
fprintf(fp, "wire %s%s;\n",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_reference_output_postfix);
|
|
||||||
fprintf(fp, "reg %s%s;\n",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_verification_output_postfix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate an integer to count the number of error and determine if the simulation succeed or failed
|
|
||||||
fprintf(fp, "\n//----- Error counter \n");
|
|
||||||
fprintf(fp, " integer %s = 0;\n\n", error_counter);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_top_auto_testbench_call_benchmark(FILE* fp,
|
|
||||||
char* reference_verilog_top_name){
|
|
||||||
int iblock, iopad_idx;
|
|
||||||
|
|
||||||
fprintf(fp, "// Reference Benchmark instanciation\n");
|
|
||||||
fprintf(fp, " %s ref_U0(\n", reference_verilog_top_name);
|
|
||||||
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
/* General INOUT*/
|
|
||||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
|
||||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
|
||||||
/* Make sure We find the correct logical block !*/
|
|
||||||
assert((VPACK_INPAD == logical_block[iblock].type)
|
|
||||||
||(VPACK_OUTPAD == logical_block[iblock].type));
|
|
||||||
if(iblock > 0){
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
if(VPACK_INPAD == logical_block[iblock].type){
|
|
||||||
/* See if this is a clock net */
|
|
||||||
if (TRUE == logical_block[iblock].is_clock) {
|
|
||||||
fprintf(fp, " %s", top_tb_op_clock_port_name);
|
|
||||||
} else{
|
|
||||||
fprintf(fp, " %s_%s_%d_", logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
|
||||||
}
|
|
||||||
} else if(VPACK_OUTPAD == logical_block[iblock].type){
|
|
||||||
fprintf(fp, " %s%s",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_reference_output_postfix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(fp, " );\n");
|
|
||||||
fprintf(fp, "// End Benchmark instanciation\n\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int get_simulation_time(int num_prog_clock_cycles,
|
|
||||||
float prog_clock_period,
|
|
||||||
int num_op_clock_cycles,
|
|
||||||
float op_clock_period) {
|
|
||||||
int total_time_period = 0;
|
|
||||||
|
|
||||||
/* Take into account the prog_reset and reset cycles */
|
|
||||||
total_time_period = ((num_prog_clock_cycles + 2) * prog_clock_period + (2 * num_op_clock_cycles * op_clock_period)) * 1000000000; // * 1000000000 is to change the unit to ns rather than second
|
|
||||||
|
|
||||||
return total_time_period;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_timeout_and_vcd(FILE * fp,
|
|
||||||
char* circuit_name,
|
|
||||||
t_spice verilog,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info){
|
|
||||||
int simulation_time;
|
|
||||||
|
|
||||||
simulation_time = get_simulation_time(get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info),
|
|
||||||
1./verilog.spice_params.stimulate_params.prog_clock_freq,
|
|
||||||
verilog.spice_params.meas_params.sim_num_clock_cycle,
|
|
||||||
1./verilog.spice_params.stimulate_params.op_clock_freq);
|
|
||||||
|
|
||||||
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, " $dumpvars(1, %s%s);\n", circuit_name,
|
|
||||||
modelsim_autocheck_testbench_module_postfix);
|
|
||||||
fprintf(fp, " end\n\n");
|
|
||||||
fprintf(fp, " initial begin\n");
|
|
||||||
fprintf(fp, " $timeformat(-9, 2, \"ns\", 20);\n");
|
|
||||||
fprintf(fp, " $display(\"Simulation start\");\n");
|
|
||||||
fprintf(fp, " #%i // Can be changed by the user for his need\n", simulation_time);
|
|
||||||
fprintf(fp, " if(%s == 0) begin\n", error_counter);
|
|
||||||
fprintf(fp, " $display(\"Simulation Succeed\");\n");
|
|
||||||
fprintf(fp, " end else begin\n");
|
|
||||||
fprintf(fp, " $display(\"Simulation Failed with %s error(s)\", %s);\n", "%d", error_counter);
|
|
||||||
fprintf(fp, " end\n");
|
|
||||||
fprintf(fp, " $finish;\n");
|
|
||||||
fprintf(fp, " end\n");
|
|
||||||
fprintf(fp, "`endif\n\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_top_auto_testbench_check(FILE* fp){
|
|
||||||
int iblock, iopad_idx;
|
|
||||||
fprintf(fp, " // Begin checking\n");
|
|
||||||
fprintf(fp, " always@(negedge %s) begin\n", top_tb_op_clock_port_name);
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
|
||||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
|
||||||
/* 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){
|
|
||||||
fprintf(fp, " %s%s <= %s%s ^ %s_%s_%d_ ;\n",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_verification_output_postfix,
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_reference_output_postfix,
|
|
||||||
logical_block[iblock].name,
|
|
||||||
gio_inout_prefix, iopad_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(fp, " end\n\n");
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
|
||||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
|
||||||
/* 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){
|
|
||||||
fprintf(fp, " always@(posedge %s%s) begin\n",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_verification_output_postfix);
|
|
||||||
fprintf(fp, " if(%s%s) begin\n",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_verification_output_postfix);
|
|
||||||
fprintf(fp, " %s = %s + 1;\n", error_counter, error_counter);
|
|
||||||
fprintf(fp, " $display(\"Mismatch on %s%s at time = %s\", $realtime);\n",
|
|
||||||
logical_block[iblock].name,
|
|
||||||
autocheck_testbench_verification_output_postfix, "%t");
|
|
||||||
fprintf(fp, " end\n");
|
|
||||||
fprintf(fp, " end\n\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_verilog_autocheck_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* circuit_name,
|
|
||||||
const char* top_netlist_name,
|
|
||||||
char* verilog_dir_path,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
t_spice verilog) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
char* title = my_strcat("FPGA Verilog Testbench for Top-level netlist of Design: ", circuit_name);
|
|
||||||
bool is_explicit_mapping = fpga_verilog_opts.dump_explicit_verilog;
|
|
||||||
|
|
||||||
/* Check if the path exists*/
|
|
||||||
fp = fopen(top_netlist_name,"w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Failure in create top Verilog testbench %s!",
|
|
||||||
__FILE__, __LINE__, top_netlist_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO,
|
|
||||||
"Writing Autocheck Testbench for FPGA Top-level Verilog netlist for %s...\n",
|
|
||||||
circuit_name);
|
|
||||||
|
|
||||||
/* Print the title */
|
|
||||||
dump_verilog_file_header(fp, title);
|
|
||||||
my_free(title);
|
|
||||||
|
|
||||||
/* Print preprocessing flags */
|
|
||||||
verilog_include_defines_preproc_file(fp, verilog_dir_path);
|
|
||||||
|
|
||||||
/* Start of testbench */
|
|
||||||
dump_verilog_top_auto_testbench_ports(fp, cur_sram_orgz_info, circuit_name, fpga_verilog_opts);
|
|
||||||
|
|
||||||
/* Call defined top-level module */
|
|
||||||
dump_verilog_top_testbench_call_top_module(cur_sram_orgz_info, fp,
|
|
||||||
circuit_name, is_explicit_mapping);
|
|
||||||
|
|
||||||
/* Call defined benchmark */
|
|
||||||
dump_verilog_top_auto_testbench_call_benchmark(fp, circuit_name);
|
|
||||||
|
|
||||||
/* Add stimuli for reset, set, clock and iopad signals */
|
|
||||||
dump_verilog_top_testbench_stimuli(cur_sram_orgz_info, fp, verilog);
|
|
||||||
|
|
||||||
/* Add output autocheck */
|
|
||||||
dump_verilog_top_auto_testbench_check(fp);
|
|
||||||
|
|
||||||
/* Add Icarus requirement */
|
|
||||||
dump_verilog_timeout_and_vcd(fp, circuit_name , verilog, cur_sram_orgz_info);
|
|
||||||
|
|
||||||
/* Testbench ends*/
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
|
|
||||||
/* Close the file*/
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef VERILOG_AUTOCHECK_TOP_TESTBENCH_H
|
|
||||||
#define VERILOG_AUTOCHECK_TOP_TESTBENCH_H
|
|
||||||
|
|
||||||
|
|
||||||
void dump_verilog_autocheck_top_testbench(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* circuit_name,
|
|
||||||
const char* top_netlist_name,
|
|
||||||
char* verilog_dir_path,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
t_spice verilog);
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,32 +0,0 @@
|
||||||
#ifndef VERILOG_COMPACT_NETLIST_H
|
|
||||||
#define VERILOG_COMPACT_NETLIST_H
|
|
||||||
|
|
||||||
|
|
||||||
void dump_compact_verilog_one_physical_block(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir_path,
|
|
||||||
char* subckt_dir_path,
|
|
||||||
t_type_ptr phy_block_type,
|
|
||||||
int border_side,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void print_compact_verilog_logic_blocks(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir,
|
|
||||||
char* subckt_dir,
|
|
||||||
t_arch& arch,
|
|
||||||
const bool& is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_compact_verilog_top_netlist(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* circuit_name,
|
|
||||||
char* top_netlist_name,
|
|
||||||
char* verilog_dir_path,
|
|
||||||
char* submodule_dir_path,
|
|
||||||
char* lb_dir_path,
|
|
||||||
char* rr_dir_path,
|
|
||||||
int LL_num_rr_nodes,
|
|
||||||
t_rr_node* LL_rr_node,
|
|
||||||
t_ivec*** LL_rr_node_indices,
|
|
||||||
int num_clock,
|
|
||||||
boolean compact_routing_hierarchy,
|
|
||||||
t_spice verilog,
|
|
||||||
bool is_explicit_verilog);
|
|
||||||
#endif
|
|
|
@ -1,570 +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_globals.h"
|
|
||||||
|
|
||||||
/* Include verilog utils */
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
|
|
||||||
/***** Subroutines *****/
|
|
||||||
/* Return the float number of the time unit required by Modelsim */
|
|
||||||
float convert_modelsim_time_unit_to_float(char* modelsim_time_unit) {
|
|
||||||
/* switch cases is made for s, ms, us, ns, ps and fs*/
|
|
||||||
if (0 == strcmp("s", modelsim_time_unit)) {
|
|
||||||
return 1;
|
|
||||||
} else if (0 == strcmp("ms", modelsim_time_unit)) {
|
|
||||||
return 1e-3;
|
|
||||||
} else if (0 == strcmp("us", modelsim_time_unit)) {
|
|
||||||
return 1e-6;
|
|
||||||
} else if (0 == strcmp("ns", modelsim_time_unit)) {
|
|
||||||
return 1e-9;
|
|
||||||
} else if (0 == strcmp("ps", modelsim_time_unit)) {
|
|
||||||
return 1e-12;
|
|
||||||
} else if (0 == strcmp("fs", modelsim_time_unit)) {
|
|
||||||
return 1e-15;
|
|
||||||
} else {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid time unit(=%s) for modelsim!\n",
|
|
||||||
__FILE__, __LINE__, modelsim_time_unit);
|
|
||||||
exit(1);
|
|
||||||
return 0.;
|
|
||||||
}
|
|
||||||
return 0.;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void modelsim_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 \\\n", spice.include_netlists[i].path);
|
|
||||||
spice.include_netlists[i].included = 1;
|
|
||||||
} else {
|
|
||||||
assert(1 == spice.include_netlists[i].included);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Estimate the simulation time period to be assigned in Modelsim:
|
|
||||||
* Total simulation time = number of programming clock cycles * programming clock period
|
|
||||||
* + number of operating clock cycles * operating clock period
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
float get_verilog_modelsim_simulation_time_period(float time_unit,
|
|
||||||
int num_prog_clock_cycles,
|
|
||||||
float prog_clock_period,
|
|
||||||
int num_op_clock_cycles,
|
|
||||||
float op_clock_period) {
|
|
||||||
float total_time_period = 0.;
|
|
||||||
|
|
||||||
/* Take into account the prog_reset and reset cycles */
|
|
||||||
total_time_period = (num_prog_clock_cycles + 2) * prog_clock_period + num_op_clock_cycles * op_clock_period;
|
|
||||||
total_time_period = total_time_period / time_unit;
|
|
||||||
|
|
||||||
return total_time_period;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_modelsim_proc_script(char* modelsim_proc_filename,
|
|
||||||
char* modelsim_ini_path,
|
|
||||||
char* circuit_name) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
char* circuit_top_tb_name = NULL;
|
|
||||||
|
|
||||||
circuit_top_tb_name = my_strcat(circuit_name, modelsim_testbench_module_postfix);
|
|
||||||
|
|
||||||
/* Create Modelsim proc file */
|
|
||||||
/* Open file and file handler */
|
|
||||||
fp = fopen(modelsim_proc_filename, "w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create Modelsim simulation deck auto-generation scripts: %s",
|
|
||||||
__FILE__, __LINE__, modelsim_proc_filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "proc create_project {projectname project_path} {\n");
|
|
||||||
fprintf(fp, " #Switch to the modelsim folder to create the project\n");
|
|
||||||
fprintf(fp, " set libname $projectname\n");
|
|
||||||
fprintf(fp, " set initfile %s\n", modelsim_ini_path);
|
|
||||||
fprintf(fp, " project new $project_path/$projectname $projectname $libname $initfile 0\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
fprintf(fp, " \n");
|
|
||||||
|
|
||||||
fprintf(fp, "proc create_project_with_close {projectname modelsim_path} {\n");
|
|
||||||
fprintf(fp, " #Get the current project name\n");
|
|
||||||
fprintf(fp, " set project_env [project env]\n");
|
|
||||||
fprintf(fp, " if {$project_env eq \"\"} {\n");
|
|
||||||
fprintf(fp, " #If string empty (no project)\n");
|
|
||||||
fprintf(fp, " create_project $projectname $modelsim_path\n");
|
|
||||||
fprintf(fp, " } else {\n");
|
|
||||||
fprintf(fp, " #If string not empty (a project is loaded so clsoe it first)\n");
|
|
||||||
fprintf(fp, " project close\n");
|
|
||||||
fprintf(fp, " create_project $projectname $modelsim_path\n");
|
|
||||||
fprintf(fp, " }\n");
|
|
||||||
fprintf(fp, " }\n");
|
|
||||||
|
|
||||||
fprintf(fp, " \n");
|
|
||||||
|
|
||||||
fprintf(fp, "proc add_files_project {verilog_files} {\n");
|
|
||||||
fprintf(fp, " #Get the length of the list\n");
|
|
||||||
fprintf(fp, " set listlength [llength $verilog_files]\n");
|
|
||||||
fprintf(fp, " #Add the verilog files one by one\n");
|
|
||||||
fprintf(fp, " for {set x 0} {$x<$listlength} {incr x} {\n");
|
|
||||||
fprintf(fp, " project addfile [lindex $verilog_files $x]\n");
|
|
||||||
fprintf(fp, " }\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
fprintf(fp, " \n");
|
|
||||||
|
|
||||||
fprintf(fp, "proc add_waves {} {\n");
|
|
||||||
fprintf(fp, " add wave -position insertpoint sim:/%s/*\n", circuit_top_tb_name);
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fp, "proc runsim {simtime unit} {\n");
|
|
||||||
fprintf(fp, " run $simtime $unit\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fp, "#Top procedure to create enw project\n");
|
|
||||||
fprintf(fp, "proc top_create_new_project {projectname verilog_files modelsim_path simtime unit} {\n");
|
|
||||||
fprintf(fp, " #Create the project\n");
|
|
||||||
fprintf(fp, " create_project_with_close $projectname $modelsim_path\n");
|
|
||||||
fprintf(fp, " #Add the verilog files\n");
|
|
||||||
fprintf(fp, " add_files_project $verilog_files\n");
|
|
||||||
fprintf(fp, " #Compile all the files\n");
|
|
||||||
fprintf(fp, " project compileall\n");
|
|
||||||
fprintf(fp, " #Start the simulation\n");
|
|
||||||
fprintf(fp, " vsim $projectname.%s -voptargs=+acc\n", circuit_top_tb_name);
|
|
||||||
fprintf(fp, " #Add the waves \n");
|
|
||||||
fprintf(fp, " add_waves\n");
|
|
||||||
fprintf(fp, " #run the simulation\n");
|
|
||||||
fprintf(fp, " runsim $simtime $unit\n");
|
|
||||||
fprintf(fp, " #Fit the window view\n");
|
|
||||||
fprintf(fp, " wave zoom full\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Top proc to recompile files and re run the simulation\n");
|
|
||||||
fprintf(fp, "proc top_rerun_sim {simtime unit} {\n");
|
|
||||||
fprintf(fp, " #Compile updated verilog files\n");
|
|
||||||
fprintf(fp, " project compileoutofdate\n");
|
|
||||||
fprintf(fp, " #restart the simulation\n");
|
|
||||||
fprintf(fp, " restart -force\n");
|
|
||||||
fprintf(fp, " #run the simulation\n");
|
|
||||||
fprintf(fp, " runsim $simtime $unit\n");
|
|
||||||
fprintf(fp, " #Fit the window view\n");
|
|
||||||
fprintf(fp, " wave zoom full\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
/* Close File handler */
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/* Free */
|
|
||||||
my_free(circuit_top_tb_name);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_modelsim_proc_auto_script(char* modelsim_proc_filename,
|
|
||||||
char* modelsim_ini_path,
|
|
||||||
char* circuit_name,
|
|
||||||
boolean include_timing,
|
|
||||||
boolean init_sim,
|
|
||||||
char* modelsim_project_name) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
char* circuit_top_tb_name = NULL;
|
|
||||||
|
|
||||||
circuit_top_tb_name = my_strcat(circuit_name, my_strcat(autocheck_testbench_postfix, modelsim_testbench_module_postfix));
|
|
||||||
|
|
||||||
/* Create Modelsim proc file */
|
|
||||||
/* Open file and file handler */
|
|
||||||
fp = fopen(modelsim_proc_filename, "w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create Modelsim simulation deck auto-generation scripts: %s",
|
|
||||||
__FILE__, __LINE__, modelsim_proc_filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "proc create_project {projectname project_path} {\n");
|
|
||||||
fprintf(fp, " #Switch to the modelsim folder to create the project\n");
|
|
||||||
fprintf(fp, " set libname $projectname\n");
|
|
||||||
fprintf(fp, " set initfile %s\n", modelsim_ini_path);
|
|
||||||
fprintf(fp, " project new $project_path/$projectname $projectname $libname $initfile 0\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
fprintf(fp, " \n");
|
|
||||||
|
|
||||||
fprintf(fp, "proc create_project_with_close {projectname modelsim_path} {\n");
|
|
||||||
fprintf(fp, " #Get the current project name\n");
|
|
||||||
fprintf(fp, " set project_env [project env]\n");
|
|
||||||
fprintf(fp, " if {$project_env eq \"\"} {\n");
|
|
||||||
fprintf(fp, " #If string empty (no project)\n");
|
|
||||||
fprintf(fp, " create_project $projectname $modelsim_path\n");
|
|
||||||
fprintf(fp, " } else {\n");
|
|
||||||
fprintf(fp, " #If string not empty (a project is loaded so clsoe it first)\n");
|
|
||||||
fprintf(fp, " project close\n");
|
|
||||||
fprintf(fp, " create_project $projectname $modelsim_path\n");
|
|
||||||
fprintf(fp, " }\n");
|
|
||||||
fprintf(fp, " }\n");
|
|
||||||
|
|
||||||
fprintf(fp, " \n");
|
|
||||||
|
|
||||||
fprintf(fp, "proc add_files_project {verilog_files} {\n");
|
|
||||||
fprintf(fp, " #Get the length of the list\n");
|
|
||||||
fprintf(fp, " set listlength [llength $verilog_files]\n");
|
|
||||||
fprintf(fp, " #Add the verilog files one by one\n");
|
|
||||||
fprintf(fp, " for {set x 0} {$x<$listlength} {incr x} {\n");
|
|
||||||
fprintf(fp, " project addfile [lindex $verilog_files $x]\n");
|
|
||||||
fprintf(fp, " }\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
fprintf(fp, " \n");
|
|
||||||
|
|
||||||
fprintf(fp, "proc add_waves {} {\n");
|
|
||||||
fprintf(fp, " add wave -position insertpoint sim:/%s/*\n", circuit_top_tb_name);
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fp, "proc runsim {simtime unit} {\n");
|
|
||||||
fprintf(fp, " run $simtime $unit\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
|
|
||||||
fprintf(fp, "#Top procedure to create enw project\n");
|
|
||||||
fprintf(fp, "proc top_create_new_project {projectname verilog_files modelsim_path simtime unit} {\n");
|
|
||||||
fprintf(fp, " #Create the project\n");
|
|
||||||
fprintf(fp, " create_project_with_close $projectname $modelsim_path\n");
|
|
||||||
fprintf(fp, " #Add the verilog files\n");
|
|
||||||
fprintf(fp, " add_files_project $verilog_files\n");
|
|
||||||
fprintf(fp, " #Compile all the files\n");
|
|
||||||
// fprintf(fp, " project compileall\n"); // removed to allow compilation with define
|
|
||||||
// Begin of compilation with Define
|
|
||||||
fprintf(fp, " set myFiles [project filenames]\n");
|
|
||||||
fprintf(fp, " foreach x $myFiles {\n");
|
|
||||||
fprintf(fp, " vlog ");
|
|
||||||
if(TRUE == include_timing){
|
|
||||||
fprintf(fp, "+define+%s ", verilog_timing_preproc_flag);
|
|
||||||
}
|
|
||||||
if(TRUE == init_sim){
|
|
||||||
fprintf(fp, "+define+%s ", verilog_signal_init_preproc_flag);
|
|
||||||
}
|
|
||||||
fprintf(fp, "$x\n }\n");
|
|
||||||
// End of compilation with Define
|
|
||||||
fprintf(fp, " #Start the simulation\n");
|
|
||||||
fprintf(fp, " vsim $projectname.%s -voptargs=+acc\n", circuit_top_tb_name);
|
|
||||||
fprintf(fp, " #Add the waves \n");
|
|
||||||
fprintf(fp, " add_waves\n");
|
|
||||||
fprintf(fp, " #run the simulation\n");
|
|
||||||
fprintf(fp, " runsim $simtime $unit\n");
|
|
||||||
fprintf(fp, " #Fit the window view\n");
|
|
||||||
fprintf(fp, " wave zoom full\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Top proc to recompile files and re run the simulation\n");
|
|
||||||
fprintf(fp, "proc top_rerun_sim {simtime unit} {\n");
|
|
||||||
// Save format
|
|
||||||
fprintf(fp, " #Save actual format\n");
|
|
||||||
fprintf(fp, " set myLoc [pwd]\n");
|
|
||||||
fprintf(fp, " write format wave -window .main_pane.wave.interior.cs.body.pw.wf $myLoc/relaunch.do\n");
|
|
||||||
// Quit simulation
|
|
||||||
fprintf(fp, " quit -sim\n");
|
|
||||||
// Recompile file
|
|
||||||
fprintf(fp, " #Compile updated verilog files\n");
|
|
||||||
fprintf(fp, " set myFiles [project filenames]\n");
|
|
||||||
fprintf(fp, " foreach x $myFiles {\n");
|
|
||||||
fprintf(fp, " vlog ");
|
|
||||||
if(TRUE == include_timing){
|
|
||||||
fprintf(fp, "+define+%s ", verilog_timing_preproc_flag);
|
|
||||||
}
|
|
||||||
if(TRUE == init_sim){
|
|
||||||
fprintf(fp, "+define+%s ", verilog_signal_init_preproc_flag);
|
|
||||||
}
|
|
||||||
fprintf(fp, "$x\n }\n");
|
|
||||||
// Restart the Simulation
|
|
||||||
fprintf(fp, " set projectname %s\n", modelsim_project_name);
|
|
||||||
fprintf(fp, " vsim $projectname.%s -voptargs=+acc -do relaunch.do\n", circuit_top_tb_name);
|
|
||||||
// Relaunch the Simulation
|
|
||||||
fprintf(fp, " #run the simulation\n");
|
|
||||||
fprintf(fp, " run $simtime $unit\n");
|
|
||||||
fprintf(fp, "}\n");
|
|
||||||
|
|
||||||
/* Close File handler */
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/* Free */
|
|
||||||
my_free(circuit_top_tb_name);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_modelsim_top_script(char* modelsim_top_script_filename,
|
|
||||||
char* modelsim_proc_script_filename,
|
|
||||||
char* modelsim_project_path,
|
|
||||||
char* circuit_name,
|
|
||||||
char* modelsim_project_name,
|
|
||||||
float sim_time,
|
|
||||||
char* sim_time_unit,
|
|
||||||
t_spice spice,
|
|
||||||
char* src_dir_path) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
|
|
||||||
/* Create Modelsim proc file */
|
|
||||||
/* Open file and file handler */
|
|
||||||
fp = fopen(modelsim_top_script_filename, "w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create Modelsim simulation deck auto-generation scripts: %s",
|
|
||||||
__FILE__, __LINE__, modelsim_top_script_filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "set projectname %s\n", modelsim_project_name);
|
|
||||||
fprintf(fp, "set benchmark %s\n", circuit_name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#in ms\n");
|
|
||||||
fprintf(fp, "set simtime %.10g\n", sim_time);
|
|
||||||
fprintf(fp, "set unit %s\n",
|
|
||||||
sim_time_unit);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Path were both tcl script are located\n");
|
|
||||||
fprintf(fp, "set project_path \"%s%s\"\n", modelsim_project_path, default_modelsim_dir_name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Path were the verilog files are located\n");
|
|
||||||
fprintf(fp, "set script_path \"%s\"\n", modelsim_project_path);
|
|
||||||
fprintf(fp, "set verilog_path \"%s\"\n", src_dir_path);
|
|
||||||
fprintf(fp, "set verilog_files [list \\\n");
|
|
||||||
/* TODO: include verilog files */
|
|
||||||
fprintf(fp, " ${verilog_path}${benchmark}%s \\\n",
|
|
||||||
verilog_top_postfix);
|
|
||||||
fprintf(fp, " ${verilog_path}${benchmark}%s \\\n",
|
|
||||||
top_testbench_verilog_file_postfix);
|
|
||||||
/* User-defined verilog netlists */
|
|
||||||
init_include_user_defined_verilog_netlists(spice);
|
|
||||||
modelsim_include_user_defined_verilog_netlists(fp, spice);
|
|
||||||
|
|
||||||
fprintf(fp, " ${verilog_path}%s%s \\\n",
|
|
||||||
default_lb_dir_name, logic_block_verilog_file_name);
|
|
||||||
fprintf(fp, " ${verilog_path}%s%s \\\n",
|
|
||||||
default_rr_dir_name, routing_verilog_file_name);
|
|
||||||
fprintf(fp, " ${verilog_path}%s%s ] \n",
|
|
||||||
default_submodule_dir_name, submodule_verilog_file_name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Source the tcl script\n");
|
|
||||||
fprintf(fp, "source ${script_path}%s\n", modelsim_proc_script_filename);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Execute the top level procedure\n");
|
|
||||||
fprintf(fp, "top_create_new_project $projectname $verilog_files $project_path $simtime $unit\n");
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Relaunch simulation\n");
|
|
||||||
|
|
||||||
/* Close File handler */
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_modelsim_top_auto_script(char* modelsim_top_auto_script_filename,
|
|
||||||
char* modelsim_proc_auto_script_filename,
|
|
||||||
char* modelsim_project_path,
|
|
||||||
char* circuit_name,
|
|
||||||
char* modelsim_project_name,
|
|
||||||
float sim_time,
|
|
||||||
char* sim_time_unit,
|
|
||||||
t_spice spice,
|
|
||||||
char* src_dir_path) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
|
|
||||||
/* Create Modelsim proc file */
|
|
||||||
/* Open file and file handler */
|
|
||||||
fp = fopen(modelsim_top_auto_script_filename, "w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create Modelsim simulation deck auto-generation scripts: %s",
|
|
||||||
__FILE__, __LINE__, modelsim_top_auto_script_filename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "set projectname %s\n", modelsim_project_name);
|
|
||||||
fprintf(fp, "set benchmark %s\n", circuit_name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#in ms\n");
|
|
||||||
fprintf(fp, "set simtime %.4g\n", sim_time);
|
|
||||||
fprintf(fp, "set unit %s\n",
|
|
||||||
sim_time_unit);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Path were both tcl script are located\n");
|
|
||||||
fprintf(fp, "set project_path \"%s%s\"\n", modelsim_project_path, default_modelsim_dir_name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Path were the verilog files are located\n");
|
|
||||||
fprintf(fp, "set script_path \"%s\"\n", modelsim_project_path);
|
|
||||||
fprintf(fp, "set verilog_path \"%s\"\n", src_dir_path);
|
|
||||||
fprintf(fp, "set verilog_files [list \\\n");
|
|
||||||
/* TODO: include verilog files */
|
|
||||||
fprintf(fp, " ${verilog_path}${benchmark}%s \\\n",
|
|
||||||
verilog_top_postfix);
|
|
||||||
fprintf(fp, " ${verilog_path}${benchmark}%s%s \\\n",
|
|
||||||
autocheck_testbench_postfix, top_testbench_verilog_file_postfix);
|
|
||||||
|
|
||||||
/* User-defined verilog netlists */
|
|
||||||
init_include_user_defined_verilog_netlists(spice);
|
|
||||||
modelsim_include_user_defined_verilog_netlists(fp, spice);
|
|
||||||
|
|
||||||
fprintf(fp, " ${verilog_path}%s%s \\\n",
|
|
||||||
default_lb_dir_name, logic_block_verilog_file_name);
|
|
||||||
fprintf(fp, " ${verilog_path}%s%s \\\n",
|
|
||||||
default_rr_dir_name, routing_verilog_file_name);
|
|
||||||
fprintf(fp, " ${verilog_path}%s%s ] \n",
|
|
||||||
default_submodule_dir_name, submodule_verilog_file_name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Source the tcl script\n");
|
|
||||||
fprintf(fp, "source ${script_path}%s\n", modelsim_proc_auto_script_filename);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Execute the top level procedure\n");
|
|
||||||
fprintf(fp, "top_create_new_project $projectname $verilog_files $project_path $simtime $unit\n");
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
fprintf(fp, "#Relaunch simulation\n");
|
|
||||||
|
|
||||||
/* Close File handler */
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***** Top-level function *****/
|
|
||||||
void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
t_spice spice,
|
|
||||||
int num_operating_clock_cycles,
|
|
||||||
char* verilog_dir_formatted,
|
|
||||||
char* chomped_circuit_name,
|
|
||||||
char* src_dir_path) {
|
|
||||||
char* modelsim_project_name = NULL;
|
|
||||||
char* modelsim_proc_script_filename = NULL;
|
|
||||||
char* modelsim_top_script_filename = NULL;
|
|
||||||
char* modelsim_proc_auto_script_filename = NULL;
|
|
||||||
char* modelsim_top_auto_script_filename = NULL;
|
|
||||||
float simulation_time_period = 0.;
|
|
||||||
|
|
||||||
/* Determine the project name for Modelsim */
|
|
||||||
modelsim_project_name = my_strcat(chomped_circuit_name, modelsim_project_name_postfix);
|
|
||||||
modelsim_top_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, modelsim_top_script_name_postfix));
|
|
||||||
modelsim_proc_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, modelsim_proc_script_name_postfix));
|
|
||||||
|
|
||||||
modelsim_top_auto_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(autocheck_testbench_postfix, modelsim_top_script_name_postfix)));
|
|
||||||
modelsim_proc_auto_script_filename = my_strcat(verilog_dir_formatted, my_strcat(chomped_circuit_name, my_strcat(autocheck_testbench_postfix, modelsim_proc_script_name_postfix)));
|
|
||||||
|
|
||||||
/* Generate files */
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Modelsim simulation deck auto-generation scripts...\n");
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
/* Modelsim ini path must be valid!*/
|
|
||||||
if (NULL == fpga_verilog_opts.modelsim_ini_path) {
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "(FILE:%s, [LINE%d])Invalid Modelsim ini path!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dump the Modelsim process function file */
|
|
||||||
if (fpga_verilog_opts.print_top_testbench){
|
|
||||||
dump_verilog_modelsim_proc_script(modelsim_proc_script_filename,
|
|
||||||
fpga_verilog_opts.modelsim_ini_path, chomped_circuit_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fpga_verilog_opts.print_autocheck_top_testbench){
|
|
||||||
dump_verilog_modelsim_proc_auto_script(modelsim_proc_auto_script_filename,
|
|
||||||
fpga_verilog_opts.modelsim_ini_path, chomped_circuit_name,
|
|
||||||
fpga_verilog_opts.include_timing, fpga_verilog_opts.include_signal_init,
|
|
||||||
modelsim_project_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Compute simulation time period */
|
|
||||||
simulation_time_period = get_verilog_modelsim_simulation_time_period(convert_modelsim_time_unit_to_float(modelsim_simulation_time_unit),
|
|
||||||
get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info),
|
|
||||||
1./spice.spice_params.stimulate_params.prog_clock_freq,
|
|
||||||
num_operating_clock_cycles,
|
|
||||||
1./spice.spice_params.stimulate_params.op_clock_freq);
|
|
||||||
|
|
||||||
/* Dump the Modelsim top-level script file */
|
|
||||||
if (fpga_verilog_opts.print_top_testbench){
|
|
||||||
dump_verilog_modelsim_top_script(modelsim_top_script_filename,
|
|
||||||
my_strcat(chomped_circuit_name, modelsim_proc_script_name_postfix),
|
|
||||||
verilog_dir_formatted,
|
|
||||||
chomped_circuit_name, modelsim_project_name,
|
|
||||||
simulation_time_period, modelsim_simulation_time_unit,
|
|
||||||
spice,
|
|
||||||
src_dir_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fpga_verilog_opts.print_autocheck_top_testbench){
|
|
||||||
dump_verilog_modelsim_top_auto_script(modelsim_top_auto_script_filename,
|
|
||||||
my_strcat(chomped_circuit_name, my_strcat(autocheck_testbench_postfix, modelsim_proc_script_name_postfix)),
|
|
||||||
verilog_dir_formatted,
|
|
||||||
chomped_circuit_name, modelsim_project_name,
|
|
||||||
simulation_time_period, modelsim_simulation_time_unit,
|
|
||||||
spice,
|
|
||||||
src_dir_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free */
|
|
||||||
my_free(modelsim_project_name);
|
|
||||||
my_free(modelsim_proc_script_filename);
|
|
||||||
my_free(modelsim_top_script_filename);
|
|
||||||
my_free(modelsim_proc_auto_script_filename);
|
|
||||||
my_free(modelsim_top_auto_script_filename);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
t_spice spice,
|
|
||||||
int num_operating_clock_cycles,
|
|
||||||
char* verilog_dir_formatted,
|
|
||||||
char* chomped_circuit_name,
|
|
||||||
char* src_dir_path);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,164 +0,0 @@
|
||||||
|
|
||||||
void match_pb_types_verilog_model_rec(t_pb_type* cur_pb_type,
|
|
||||||
int num_verilog_model,
|
|
||||||
t_spice_model* verilog_models);
|
|
||||||
|
|
||||||
int verilog_find_path_id_between_pb_rr_nodes(t_rr_node* local_rr_graph,
|
|
||||||
int src_node,
|
|
||||||
int des_node);
|
|
||||||
|
|
||||||
enum e_interconnect verilog_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_verilog_model(t_pb_graph_pin pb_graph_pin);
|
|
||||||
|
|
||||||
void stats_mux_verilog_model_pb_type_rec(t_llist** muxes_head,
|
|
||||||
t_pb_type* cur_pb_type);
|
|
||||||
|
|
||||||
void stats_mux_verilog_model_pb_node_rec(t_llist** muxes_head,
|
|
||||||
t_pb_graph_node* cur_pb_node);
|
|
||||||
|
|
||||||
|
|
||||||
void dump_verilog_pb_type_bus_ports(FILE* fp,
|
|
||||||
char* port_prefix,
|
|
||||||
int use_global_clock,
|
|
||||||
t_pb_type* cur_pb_type,
|
|
||||||
boolean dump_port_type,
|
|
||||||
boolean dump_last_comma,
|
|
||||||
boolean dump_explicit_port_map);
|
|
||||||
|
|
||||||
void dump_verilog_pb_type_ports(FILE* fp,
|
|
||||||
char* port_prefix,
|
|
||||||
int use_global_clock,
|
|
||||||
t_pb_type* cur_pb_type,
|
|
||||||
boolean dump_port_type,
|
|
||||||
boolean dump_last_comma,
|
|
||||||
boolean require_explicit_port_map,
|
|
||||||
bool is_full_name);
|
|
||||||
|
|
||||||
void dump_verilog_dangling_des_pb_graph_pin_interc(FILE* fp,
|
|
||||||
t_pb_graph_pin* des_pb_graph_pin,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
enum e_spice_pin2pin_interc_type pin2pin_interc_type,
|
|
||||||
char* parent_pin_prefix);
|
|
||||||
|
|
||||||
void generate_verilog_src_des_pb_graph_pin_prefix(t_pb_graph_pin* src_pb_graph_pin,
|
|
||||||
t_pb_graph_pin* des_pb_graph_pin,
|
|
||||||
enum e_spice_pin2pin_interc_type pin2pin_interc_type,
|
|
||||||
t_interconnect* pin2pin_interc,
|
|
||||||
char* parent_pin_prefix,
|
|
||||||
char** src_pin_prefix,
|
|
||||||
char** des_pin_prefix);
|
|
||||||
|
|
||||||
void verilog_find_interc_fan_in_des_pb_graph_pin(t_pb_graph_pin* des_pb_graph_pin,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
t_interconnect** cur_interc,
|
|
||||||
int* fan_in);
|
|
||||||
|
|
||||||
void dump_verilog_pb_graph_pin_interc(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* parent_pin_prefix,
|
|
||||||
enum e_spice_pin2pin_interc_type pin2pin_interc_type,
|
|
||||||
t_pb_graph_pin* des_pb_graph_pin,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_pb_graph_interc(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* pin_prefix,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
int select_mode_index,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_pb_graph_primitive_node(FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
int pb_type_index);
|
|
||||||
|
|
||||||
void dump_verilog_pb_primitive_verilog_model(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb* prim_pb,
|
|
||||||
t_pb_graph_node* prim_pb_graph_node,
|
|
||||||
int pb_index,
|
|
||||||
t_spice_model* verilog_model,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_phy_pb_graph_node_rec(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
int pb_type_index,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_block(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_name,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int z,
|
|
||||||
t_type_ptr type_descriptor,
|
|
||||||
t_block* mapped_block);
|
|
||||||
|
|
||||||
void dump_verilog_physical_block(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_name,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int z,
|
|
||||||
t_type_ptr type_descriptor,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_grid_pins(FILE* fp,
|
|
||||||
int x, int y,
|
|
||||||
boolean top_level,
|
|
||||||
boolean dump_port_type,
|
|
||||||
boolean dump_last_comma,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_io_grid_pins(FILE* fp,
|
|
||||||
int x, int y,
|
|
||||||
boolean top_level,
|
|
||||||
int border_side,
|
|
||||||
boolean dump_port_type,
|
|
||||||
boolean dump_last_comma,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
char* get_grid_block_subckt_name(int x,
|
|
||||||
int y,
|
|
||||||
int z,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_block* mapped_block);
|
|
||||||
|
|
||||||
void dump_verilog_grid_block_subckt_pins(FILE* fp,
|
|
||||||
int z,
|
|
||||||
t_type_ptr type_descriptor,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_io_grid_block_subckt_pins(FILE* fp,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int z,
|
|
||||||
t_type_ptr type_descriptor);
|
|
||||||
|
|
||||||
void dump_verilog_grid_blocks(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
int ix, int iy);
|
|
||||||
|
|
||||||
void dump_verilog_physical_grid_blocks(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
int ix, int iy,
|
|
||||||
t_arch* arch,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_idle_block(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_name,
|
|
||||||
int x, int y, int z,
|
|
||||||
t_type_ptr type_descriptor);
|
|
||||||
|
|
||||||
void dump_verilog_logic_blocks(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* subckt_dir, t_arch* arch,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void rec_copy_name_mux_in_node(t_pb_graph_node* master_node,
|
|
||||||
t_pb_graph_node* target_node);
|
|
|
@ -1,779 +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>
|
|
||||||
|
|
||||||
/* Include vpr structs*/
|
|
||||||
#include "util.h"
|
|
||||||
#include "physical_types.h"
|
|
||||||
#include "vpr_types.h"
|
|
||||||
#include "globals.h"
|
|
||||||
#include "rr_graph.h"
|
|
||||||
#include "rr_graph_swseg.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_pbtypes_utils.h"
|
|
||||||
#include "fpga_x2p_bitstream_utils.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
|
|
||||||
/* Include verilog support headers*/
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
#include "verilog_pbtypes.h"
|
|
||||||
#include "verilog_primitives.h"
|
|
||||||
|
|
||||||
/* Subroutines */
|
|
||||||
/* Dump a hard logic primitive node
|
|
||||||
* This primitive can be a FF or a hard_logic, or an iopad */
|
|
||||||
void dump_verilog_pb_generic_primitive(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb_graph_node* prim_pb_graph_node,
|
|
||||||
int index,
|
|
||||||
t_spice_model* verilog_model,
|
|
||||||
bool is_explicit_mapping) {
|
|
||||||
int num_pad_port = 0; /* INOUT port */
|
|
||||||
t_spice_model_port** pad_ports = NULL;
|
|
||||||
int num_input_port = 0;
|
|
||||||
t_spice_model_port** input_ports = NULL;
|
|
||||||
int num_output_port = 0;
|
|
||||||
t_spice_model_port** output_ports = NULL;
|
|
||||||
int num_clock_port = 0;
|
|
||||||
t_spice_model_port** clock_ports = NULL;
|
|
||||||
int num_sram_port = 0;
|
|
||||||
t_spice_model_port** sram_ports = NULL;
|
|
||||||
|
|
||||||
int num_sram = 0;
|
|
||||||
/* int* sram_bits = NULL; */
|
|
||||||
|
|
||||||
char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
|
||||||
t_pb_type* prim_pb_type = NULL;
|
|
||||||
char* port_prefix = NULL;
|
|
||||||
|
|
||||||
/* For each SRAM, we could have multiple BLs/WLs */
|
|
||||||
int num_bl_ports = 0;
|
|
||||||
t_spice_model_port** bl_port = NULL;
|
|
||||||
int num_wl_ports = 0;
|
|
||||||
t_spice_model_port** wl_port = NULL;
|
|
||||||
|
|
||||||
int cur_num_sram = 0;
|
|
||||||
int num_conf_bits = 0;
|
|
||||||
int num_reserved_conf_bits = 0;
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
int cur_bl, cur_wl;
|
|
||||||
|
|
||||||
char* mem_subckt_name = NULL;
|
|
||||||
|
|
||||||
/* Ensure a valid file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure a valid pb_graph_node */
|
|
||||||
if (NULL == prim_pb_graph_node) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find ports*/
|
|
||||||
pad_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INOUT, &num_pad_port, TRUE);
|
|
||||||
input_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
|
||||||
output_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
|
||||||
clock_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, TRUE);
|
|
||||||
sram_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
|
||||||
|
|
||||||
/* Asserts */
|
|
||||||
assert((SPICE_MODEL_IOPAD == verilog_model->type) /* Support IO PAD which matches the physical design */
|
|
||||||
|| (SPICE_MODEL_FF == verilog_model->type) /* Support IO PAD which matches the physical design */
|
|
||||||
|| (SPICE_MODEL_HARDLOGIC == verilog_model->type)); /* Support IO PAD which matches the physical design */
|
|
||||||
|
|
||||||
/* Initialize */
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
|
|
||||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
|
||||||
|
|
||||||
/* Generate Subckt for pb_type*/
|
|
||||||
/* Simplify the port prefix, make SPICE netlist readable */
|
|
||||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
|
||||||
(strlen(prim_pb_type->name) + 1));
|
|
||||||
sprintf(port_prefix, "%s", prim_pb_type->name);
|
|
||||||
|
|
||||||
/* Print Comment lines depends on the type of this SPICE model */
|
|
||||||
fprintf(fp, "//----- %s Verilog module: %s%s -----\n",
|
|
||||||
generate_string_spice_model_type(verilog_model->type),
|
|
||||||
formatted_subckt_prefix, port_prefix);
|
|
||||||
/* Definition line */
|
|
||||||
fprintf(fp, "module %s%s (", formatted_subckt_prefix, port_prefix);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
/* Only dump the global ports belonging to a spice_model
|
|
||||||
*/
|
|
||||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE, my_bool_to_boolean(is_explicit_mapping), TRUE)) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: assert this is physical mode */
|
|
||||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
|
||||||
/* Get current counter of mem_bits, bl and wl */
|
|
||||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl);
|
|
||||||
|
|
||||||
/* print ports --> input ports */
|
|
||||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, TRUE, FALSE, FALSE, true);
|
|
||||||
/* IOPADs requires a specical port to output */
|
|
||||||
if (SPICE_MODEL_IOPAD == verilog_model->type) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
/* Print output port */
|
|
||||||
fprintf(fp, "inout [%d:%d] %s%s\n",
|
|
||||||
verilog_model->cnt, verilog_model->cnt,
|
|
||||||
gio_inout_prefix, verilog_model->prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print SRAM ports */
|
|
||||||
/* connect to reserved BL/WLs ? */
|
|
||||||
num_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0);
|
|
||||||
/* Get the number of configuration bits required by this MUX */
|
|
||||||
num_conf_bits = count_num_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0);
|
|
||||||
/* Reserved sram ports */
|
|
||||||
if (0 < num_reserved_conf_bits) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
0, num_reserved_conf_bits - 1,
|
|
||||||
VERILOG_PORT_INPUT);
|
|
||||||
}
|
|
||||||
/* Normal sram ports */
|
|
||||||
if (0 < num_conf_bits) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
|
||||||
VERILOG_PORT_INPUT);
|
|
||||||
|
|
||||||
}
|
|
||||||
/* Dump ports only visible during formal verification*/
|
|
||||||
if (0 < num_conf_bits) {
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram,
|
|
||||||
cur_num_sram + num_conf_bits - 1,
|
|
||||||
VERILOG_PORT_INPUT, false);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
fprintf(fp, "`endif\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Local vdd and gnd*/
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
if (0 < num_sram_port) {
|
|
||||||
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1);
|
|
||||||
}
|
|
||||||
if (0 < num_sram_port) {
|
|
||||||
switch (cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* Local wires */
|
|
||||||
/* Find the number of BLs/WLs of each SRAM */
|
|
||||||
/* Detect the SRAM SPICE model linked to this SRAM port */
|
|
||||||
assert(NULL != sram_ports[0]->spice_model);
|
|
||||||
assert(SPICE_MODEL_SRAM == sram_ports[0]->spice_model->type);
|
|
||||||
find_bl_wl_ports_spice_model(sram_ports[0]->spice_model,
|
|
||||||
&num_bl_ports, &bl_port, &num_wl_ports, &wl_port);
|
|
||||||
assert(1 == num_bl_ports);
|
|
||||||
assert(1 == num_wl_ports);
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Definition ends*/
|
|
||||||
|
|
||||||
/* Dump the configuration port bus */
|
|
||||||
if ((0 < num_reserved_conf_bits)
|
|
||||||
|| (0 < num_conf_bits)) {
|
|
||||||
dump_verilog_mem_config_bus(fp, mem_model, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, num_reserved_conf_bits, num_conf_bits);
|
|
||||||
/* Dump ports only visible during formal verification*/
|
|
||||||
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
|
|
||||||
dump_verilog_formal_verification_sram_ports_wiring(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram,
|
|
||||||
cur_num_sram + num_conf_bits - 1);
|
|
||||||
fprintf(fp, "`endif\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Explicit port map support: turn it on when there is need for the full netlist or just standard cell */
|
|
||||||
boolean subckt_require_explicit_port_map = FALSE;
|
|
||||||
if ( (TRUE == verilog_model->dump_explicit_port_map) || (true == is_explicit_mapping) ) {
|
|
||||||
subckt_require_explicit_port_map = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call the subckt*/
|
|
||||||
if (0 == strcmp(verilog_model->name,port_prefix)) {
|
|
||||||
fprintf(fp, "%s %s_logic_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
|
||||||
} else {
|
|
||||||
fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
/* Only dump the global ports belonging to a spice_model
|
|
||||||
* Disable recursive here !
|
|
||||||
*/
|
|
||||||
/*if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE, my_bool_to_boolean(is_explicit_mapping))) {*/
|
|
||||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE, subckt_require_explicit_port_map, TRUE)) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* assert */
|
|
||||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
|
||||||
/* print ports --> input ports */
|
|
||||||
dump_verilog_pb_type_bus_ports(fp, port_prefix, 1, prim_pb_type, FALSE, FALSE,
|
|
||||||
subckt_require_explicit_port_map);
|
|
||||||
/* my_bool_to_boolean(is_explicit_mapping));*/
|
|
||||||
/* IOPADs requires a specical port to output */
|
|
||||||
if (SPICE_MODEL_IOPAD == verilog_model->type) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
assert(1 == num_pad_port);
|
|
||||||
assert(NULL != pad_ports[0]);
|
|
||||||
/* Add explicit port mapping if required */
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
/*if (true == is_explicit_mapping) {*/
|
|
||||||
fprintf(fp, ".%s (",
|
|
||||||
pad_ports[0]->lib_name);
|
|
||||||
}
|
|
||||||
/* Print inout port */
|
|
||||||
fprintf(fp, "%s%s[%d]", gio_inout_prefix,
|
|
||||||
verilog_model->prefix, verilog_model->cnt);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
/*if (true == is_explicit_mapping) {*/
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
}
|
|
||||||
/* Print SRAM ports */
|
|
||||||
/* Connect srams: TODO: to find the SRAM model used by this Verilog model */
|
|
||||||
if (0 < num_sram) {
|
|
||||||
switch (cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
/* Add explicit port mapping if required */
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
assert( 1 == num_sram_port);
|
|
||||||
assert( NULL != sram_ports[0]);
|
|
||||||
fprintf(fp, ".%s (",
|
|
||||||
sram_ports[0]->lib_name);
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
|
||||||
0, VERILOG_PORT_CONKT);
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (true == subckt_require_explicit_port_map)) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we have an inverterd prefix */
|
|
||||||
if (NULL == sram_ports[0]->inv_prefix) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
/* Add explicit port mapping if required */
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
assert( 1 == num_sram_port);
|
|
||||||
assert( NULL != sram_ports[0]);
|
|
||||||
fprintf(fp, ".%s (",
|
|
||||||
sram_ports[0]->inv_prefix);
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
|
||||||
1, VERILOG_PORT_CONKT);
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* Add explicit port mapping if required */
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
assert( 1 == num_sram_port);
|
|
||||||
assert( NULL != sram_ports[0]);
|
|
||||||
fprintf(fp, ".%s (",
|
|
||||||
sram_ports[0]->lib_name);
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
|
||||||
0, VERILOG_PORT_CONKT);
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
/* Check if we have an inverterd prefix */
|
|
||||||
if (NULL == sram_ports[0]->inv_prefix) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
/* Add explicit port mapping if required */
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
assert( 1 == num_sram_port);
|
|
||||||
assert( NULL != sram_ports[0]);
|
|
||||||
fprintf(fp, ".%s (",
|
|
||||||
sram_ports[0]->inv_prefix);
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
|
||||||
1, VERILOG_PORT_CONKT);
|
|
||||||
if ( (0 < num_sram)
|
|
||||||
&& (TRUE == subckt_require_explicit_port_map)) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Local vdd and gnd, verilog_model name,
|
|
||||||
* TODO: Global vdd for i/o pad to split?
|
|
||||||
*/
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Call SRAM subckt */
|
|
||||||
/* what is the SRAM bit of a mode? */
|
|
||||||
/* If logical block is not NULL, we need to decode the sram bit */
|
|
||||||
/* SRAM bits are decoded in bitstream generator! NOT here
|
|
||||||
if (NULL != mapped_logical_block) {
|
|
||||||
assert(NULL != mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits);
|
|
||||||
sram_bits = decode_mode_bits(mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits, &expected_num_sram);
|
|
||||||
assert(expected_num_sram == num_sram);
|
|
||||||
} else {
|
|
||||||
sram_bits = (int*)my_calloc(num_sram, sizeof(int));
|
|
||||||
for (i = 0; i < num_sram; i++) {
|
|
||||||
sram_bits[i] = sram_ports[0]->default_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Call the memory module defined for this SRAM-based MUX! */
|
|
||||||
if (0 < num_sram_port) {
|
|
||||||
mem_subckt_name = generate_verilog_mem_subckt_name(verilog_model, mem_model, verilog_mem_posfix);
|
|
||||||
fprintf(fp, "%s %s_%d_ ( ",
|
|
||||||
mem_subckt_name, mem_subckt_name, verilog_model->cnt);
|
|
||||||
dump_verilog_mem_sram_submodule(fp, cur_sram_orgz_info, verilog_model, -1,
|
|
||||||
mem_model, cur_num_sram, cur_num_sram + num_sram - 1, my_bool_to_boolean(is_explicit_mapping));
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
/* update the number of memory bits */
|
|
||||||
update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + num_sram);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End */
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
/* Comment lines */
|
|
||||||
fprintf(fp, "//----- END %s Verilog module: %s%s -----\n\n",
|
|
||||||
generate_string_spice_model_type(verilog_model->type),
|
|
||||||
formatted_subckt_prefix, port_prefix);
|
|
||||||
|
|
||||||
/* Update the verilog_model counter */
|
|
||||||
verilog_model->cnt++;
|
|
||||||
|
|
||||||
/*Free*/
|
|
||||||
free(formatted_subckt_prefix);
|
|
||||||
free(port_prefix);
|
|
||||||
my_free(input_ports);
|
|
||||||
my_free(output_ports);
|
|
||||||
my_free(pad_ports);
|
|
||||||
my_free(clock_ports);
|
|
||||||
my_free(sram_ports);
|
|
||||||
/* my_free(sram_bits); */
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_verilog_pb_primitive_lut(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb_graph_node* prim_pb_graph_node,
|
|
||||||
int index,
|
|
||||||
t_spice_model* verilog_model,
|
|
||||||
bool is_explicit_mapping) {
|
|
||||||
int i;
|
|
||||||
int lut_size = 0;
|
|
||||||
int num_input_port = 0;
|
|
||||||
t_spice_model_port** input_ports = NULL;
|
|
||||||
int num_output_port = 0;
|
|
||||||
t_spice_model_port** output_ports = NULL;
|
|
||||||
int num_sram_port = 0;
|
|
||||||
t_spice_model_port** sram_ports = NULL;
|
|
||||||
|
|
||||||
int num_lut_sram = 0;
|
|
||||||
int num_mode_sram = 0;
|
|
||||||
t_spice_model_port* lut_sram_port = NULL;
|
|
||||||
|
|
||||||
char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
|
||||||
t_pb_type* cur_pb_type = NULL;
|
|
||||||
char* port_prefix = NULL;
|
|
||||||
int cur_num_sram = 0;
|
|
||||||
int num_sram = 0;
|
|
||||||
/* For each SRAM, we could have multiple BLs/WLs */
|
|
||||||
int num_bl_ports = 0;
|
|
||||||
t_spice_model_port** bl_port = NULL;
|
|
||||||
int num_wl_ports = 0;
|
|
||||||
t_spice_model_port** wl_port = NULL;
|
|
||||||
int num_bl_per_sram = 0;
|
|
||||||
int num_wl_per_sram = 0;
|
|
||||||
int num_conf_bits = 0;
|
|
||||||
int num_reserved_conf_bits = 0;
|
|
||||||
int cur_bl, cur_wl;
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
char* mem_subckt_name = NULL;
|
|
||||||
|
|
||||||
/* Ensure a valid file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure a valid pb_graph_node */
|
|
||||||
if (NULL == prim_pb_graph_node) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* Asserts */
|
|
||||||
assert(SPICE_MODEL_LUT == verilog_model->type);
|
|
||||||
|
|
||||||
/* Determine size of LUT*/
|
|
||||||
input_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
|
||||||
output_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
|
||||||
assert(1 == num_input_port);
|
|
||||||
lut_size = input_ports[0]->size;
|
|
||||||
/* Find SRAM ports for truth tables and mode bits */
|
|
||||||
sram_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
|
||||||
assert((1 == num_sram_port) || (2 == num_sram_port));
|
|
||||||
for (i = 0; i < num_sram_port; i++) {
|
|
||||||
if (FALSE == sram_ports[i]->mode_select) {
|
|
||||||
lut_sram_port = sram_ports[i];
|
|
||||||
num_lut_sram = sram_ports[i]->size;
|
|
||||||
assert (num_lut_sram == (int)pow(2.,(double)(lut_size)));
|
|
||||||
} else {
|
|
||||||
assert (TRUE == sram_ports[i]->mode_select);
|
|
||||||
num_mode_sram = sram_ports[i]->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Must have a lut_sram_port, while mode_bit_port is optional */
|
|
||||||
assert (NULL != lut_sram_port);
|
|
||||||
|
|
||||||
/* Count the number of configuration bits */
|
|
||||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
|
||||||
/* Get memory model */
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
|
|
||||||
/* Find the number of BLs/WLs of each SRAM */
|
|
||||||
switch (cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* Detect the SRAM SPICE model linked to this SRAM port */
|
|
||||||
assert(NULL != sram_ports[0]->spice_model);
|
|
||||||
assert(SPICE_MODEL_SRAM == sram_ports[0]->spice_model->type);
|
|
||||||
find_bl_wl_ports_spice_model(sram_ports[0]->spice_model,
|
|
||||||
&num_bl_ports, &bl_port, &num_wl_ports, &wl_port);
|
|
||||||
assert(1 == num_bl_ports);
|
|
||||||
assert(1 == num_wl_ports);
|
|
||||||
num_bl_per_sram = bl_port[0]->size;
|
|
||||||
num_wl_per_sram = wl_port[0]->size;
|
|
||||||
/* Asserts */
|
|
||||||
assert(num_bl_per_sram == num_wl_per_sram);
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable Generate sram bits*/
|
|
||||||
/* SRAM bits are decoded in bitstream generator! NOT here
|
|
||||||
sram_bits = generate_lut_sram_bits(truth_table_length, truth_table,
|
|
||||||
lut_size, sram_ports[0]->default_val);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Print the subckts*/
|
|
||||||
cur_pb_type = prim_pb_graph_node->pb_type;
|
|
||||||
|
|
||||||
/* Comment lines */
|
|
||||||
fprintf(fp, "//----- LUT Verilog module: %s%s_%d_ -----\n",
|
|
||||||
formatted_subckt_prefix, cur_pb_type->name, index);
|
|
||||||
|
|
||||||
/* Simplify the prefix, make the SPICE netlist readable*/
|
|
||||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
|
||||||
(strlen(cur_pb_type->name) + 1));
|
|
||||||
sprintf(port_prefix, "%s", cur_pb_type->name);
|
|
||||||
|
|
||||||
/* Subckt definition*/
|
|
||||||
fprintf(fp, "module %s%s (",
|
|
||||||
formatted_subckt_prefix, cur_pb_type->name);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
/* Only dump the global ports belonging to a spice_model */
|
|
||||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE, my_bool_to_boolean(is_explicit_mapping), TRUE)) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
/* Print inputs, outputs, inouts, clocks, NO SRAMs*/
|
|
||||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, cur_pb_type, TRUE, TRUE, FALSE, false);
|
|
||||||
/* Print SRAM ports */
|
|
||||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &cur_bl, &cur_wl);
|
|
||||||
/* connect to reserved BL/WLs ? */
|
|
||||||
num_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0);
|
|
||||||
/* Get the number of configuration bits required by this MUX */
|
|
||||||
num_conf_bits = count_num_conf_bits_one_spice_model(verilog_model, cur_sram_orgz_info->type, 0);
|
|
||||||
/* Reserved sram ports */
|
|
||||||
if ( 0 < num_reserved_conf_bits) {
|
|
||||||
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
0, num_reserved_conf_bits - 1,
|
|
||||||
VERILOG_PORT_INPUT);
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
/* Normal sram ports */
|
|
||||||
if (0 < num_conf_bits) {
|
|
||||||
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_conf_bits - 1,
|
|
||||||
VERILOG_PORT_INPUT);
|
|
||||||
}
|
|
||||||
/* Dump ports only visible during formal verification*/
|
|
||||||
if (0 < num_conf_bits) {
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram,
|
|
||||||
cur_num_sram + num_conf_bits - 1,
|
|
||||||
VERILOG_PORT_INPUT, false);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
fprintf(fp, "`endif\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Local Vdd and gnd*/
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
/* Definition ends*/
|
|
||||||
|
|
||||||
/* Specify SRAM output are wires */
|
|
||||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1);
|
|
||||||
|
|
||||||
/* Dump ports only visible during formal verification*/
|
|
||||||
if ((0 < num_reserved_conf_bits)
|
|
||||||
|| (0 < num_conf_bits)) {
|
|
||||||
dump_verilog_mem_config_bus(fp, mem_model, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, num_reserved_conf_bits, num_conf_bits);
|
|
||||||
|
|
||||||
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
|
|
||||||
dump_verilog_formal_verification_sram_ports_wiring(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram,
|
|
||||||
cur_num_sram + num_sram - 1);
|
|
||||||
fprintf(fp, "`endif\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
fprintf(fp, "wire [%d:%d] %s_out;\n",
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1, mem_model->prefix);
|
|
||||||
fprintf(fp, "wire [%d:%d] %s_outb;\n",
|
|
||||||
cur_num_sram, cur_num_sram + num_sram - 1, mem_model->prefix);
|
|
||||||
*/
|
|
||||||
|
|
||||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
|
||||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
|
|
||||||
/* Explicit port map support: turn it on when there is need for the full netlist or just standard cell */
|
|
||||||
boolean subckt_require_explicit_port_map = FALSE;
|
|
||||||
if ( (TRUE == verilog_model->dump_explicit_port_map) || (true == is_explicit_mapping) ) {
|
|
||||||
subckt_require_explicit_port_map = TRUE;
|
|
||||||
}
|
|
||||||
/* Call LUT subckt*/
|
|
||||||
if (0 == strcmp(verilog_model->name,port_prefix)) {
|
|
||||||
fprintf(fp, "%s %s_logic_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
|
||||||
} else {
|
|
||||||
fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
|
||||||
}
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
/* if we have to add global ports when dumping submodules of LUTs
|
|
||||||
* otherwise, the port map here does not match that of submodules
|
|
||||||
* Only dump the global ports belonging to a spice_model
|
|
||||||
* DISABLE recursive here !
|
|
||||||
*/
|
|
||||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE, subckt_require_explicit_port_map, TRUE)) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
/* Connect inputs*/
|
|
||||||
/* Connect outputs*/
|
|
||||||
fprintf(fp, "//----- Input and output ports -----\n");
|
|
||||||
dump_verilog_pb_type_bus_ports(fp, port_prefix, 1, cur_pb_type, FALSE, TRUE, subckt_require_explicit_port_map);
|
|
||||||
fprintf(fp, "\n//----- SRAM ports -----\n");
|
|
||||||
|
|
||||||
/* check */
|
|
||||||
assert (num_sram == num_lut_sram + num_mode_sram);
|
|
||||||
/* Connect srams: TODO: to find the SRAM model used by this Verilog model */
|
|
||||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
/* TODO: switch depending on the type of configuration circuit */
|
|
||||||
switch (cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".sram_out( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_lut_sram - 1,
|
|
||||||
0, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".sram_outb( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_lut_sram - 1,
|
|
||||||
1, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
if (0 < num_mode_sram) {
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".mode_out( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1,
|
|
||||||
0, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".mode_outb( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1,
|
|
||||||
1, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".sram_out( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_lut_sram - 1,
|
|
||||||
0, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".sram_outb( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram, cur_num_sram + num_lut_sram - 1,
|
|
||||||
1, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
if (0 < num_mode_sram) {
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".mode_out( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1,
|
|
||||||
0, VERILOG_PORT_CONKT);
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
fprintf(fp, ", ");
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ".mode_outb( ");
|
|
||||||
}
|
|
||||||
dump_verilog_sram_one_outport(fp, cur_sram_orgz_info,
|
|
||||||
cur_num_sram + num_lut_sram, cur_num_sram + num_lut_sram + num_mode_sram - 1,
|
|
||||||
1, VERILOG_PORT_CONKT);
|
|
||||||
}
|
|
||||||
if (TRUE == subckt_require_explicit_port_map) {
|
|
||||||
fprintf(fp, ")");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* vdd should be connected to special global wire gvdd_lut and gnd,
|
|
||||||
* Every LUT has a special VDD for statistics
|
|
||||||
*/
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
/* Call SRAM subckts only
|
|
||||||
* when Configuration organization style is memory bank */
|
|
||||||
/* No. of SRAMs is different from the number of configuration lines.
|
|
||||||
* Especially when SRAMs/RRAMs are configured with BL/WLs
|
|
||||||
*/
|
|
||||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
|
||||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
|
|
||||||
|
|
||||||
/* Call the memory module defined for this SRAM-based MUX! */
|
|
||||||
mem_subckt_name = generate_verilog_mem_subckt_name(verilog_model, mem_model, verilog_mem_posfix);
|
|
||||||
fprintf(fp, "%s %s_%d_ ( ",
|
|
||||||
mem_subckt_name, mem_subckt_name, verilog_model->cnt);
|
|
||||||
dump_verilog_mem_sram_submodule(fp, cur_sram_orgz_info, verilog_model, -1,
|
|
||||||
mem_model, cur_num_sram, cur_num_sram + num_sram - 1, is_explicit_mapping);
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
/* update the number of memory bits */
|
|
||||||
update_sram_orgz_info_num_mem_bit(cur_sram_orgz_info, cur_num_sram + num_sram);
|
|
||||||
|
|
||||||
/* End of subckt*/
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
|
|
||||||
/* Comment lines */
|
|
||||||
fprintf(fp, "//----- END LUT Verilog module: %s%s_%d_ -----\n\n",
|
|
||||||
formatted_subckt_prefix, cur_pb_type->name, index);
|
|
||||||
|
|
||||||
/* Update counter */
|
|
||||||
verilog_model->cnt++;
|
|
||||||
|
|
||||||
/*Free*/
|
|
||||||
my_free(formatted_subckt_prefix);
|
|
||||||
my_free(input_ports);
|
|
||||||
my_free(output_ports);
|
|
||||||
my_free(sram_ports);
|
|
||||||
my_free(mem_subckt_name);
|
|
||||||
/* my_free(sram_bits); */
|
|
||||||
my_free(port_prefix);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
void dump_verilog_pb_generic_primitive(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb_graph_node* prim_pb_graph_node,
|
|
||||||
int index,
|
|
||||||
t_spice_model* spice_model,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_pb_primitive_lut(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* subckt_prefix,
|
|
||||||
t_pb_graph_node* prim_pb_graph_node,
|
|
||||||
int index,
|
|
||||||
t_spice_model* spice_model,
|
|
||||||
bool is_explicit_mapping);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
void verilog_generate_report_timing(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_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_syn_verilog_opts fpga_verilog_opts,
|
|
||||||
boolean compact_routing_hierarchy);
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,50 +0,0 @@
|
||||||
#ifndef VERILOG_SDC_H
|
|
||||||
#define VERILOG_SDC_H
|
|
||||||
|
|
||||||
void verilog_generate_sdc_pnr(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_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_rr_indexed_data* LL_rr_indexed_data,
|
|
||||||
int LL_nx, int LL_ny, DeviceRRGSB& LL_device_rr_gsb,
|
|
||||||
boolean compact_routing_hierarchy);
|
|
||||||
|
|
||||||
void verilog_generate_sdc_analysis(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_dir,
|
|
||||||
t_arch arch,
|
|
||||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
|
||||||
t_ivec*** LL_rr_node_indices,
|
|
||||||
int LL_nx, int LL_ny, t_grid_tile** LL_grid,
|
|
||||||
t_block* LL_block, DeviceRRGSB& LL_device_rr_gsb,
|
|
||||||
boolean compact_routing_hierarchy);
|
|
||||||
|
|
||||||
void dump_sdc_one_clb_muxes(FILE* fp,
|
|
||||||
char* grid_instance_name,
|
|
||||||
t_rr_graph* rr_graph,
|
|
||||||
t_pb_graph_node* pb_graph_head);
|
|
||||||
|
|
||||||
|
|
||||||
void dump_sdc_rec_one_pb_muxes(FILE* fp,
|
|
||||||
char* grid_instance_name,
|
|
||||||
t_rr_graph* rr_graph,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node);
|
|
||||||
|
|
||||||
void dump_sdc_pb_graph_node_muxes(FILE* fp,
|
|
||||||
char* grid_instance_name,
|
|
||||||
t_rr_graph* rr_graph,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node);
|
|
||||||
|
|
||||||
void dump_sdc_pb_graph_pin_muxes(FILE* fp,
|
|
||||||
char* grid_instance_name,
|
|
||||||
t_rr_graph* rr_graph,
|
|
||||||
t_pb_graph_pin pb_graph_pin);
|
|
||||||
|
|
||||||
/*void verilog_generate_wire_report_timing_blockage_direction(FILE* fp,
|
|
||||||
char* direction,
|
|
||||||
int LL_nx, int LL_ny);
|
|
||||||
|
|
||||||
void verilog_generate_sdc_wire_report_timing_blockage(t_sdc_opts sdc_opts,
|
|
||||||
int LL_nx, int LL_ny);*/
|
|
||||||
#endif
|
|
|
@ -1,553 +0,0 @@
|
||||||
/***********************************/
|
|
||||||
/* SDC Generation dumping */
|
|
||||||
/* Xifan TANG, EPFL/LSI */
|
|
||||||
/* Baudouin Chauviere LNIS */
|
|
||||||
/***********************************/
|
|
||||||
#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 "route_common.h"
|
|
||||||
|
|
||||||
/* Include FPGA-SPICE utils */
|
|
||||||
#include "read_xml_spice_util.h"
|
|
||||||
#include "linkedlist.h"
|
|
||||||
#include "fpga_x2p_types.h"
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
#include "fpga_x2p_pbtypes_utils.h"
|
|
||||||
#include "fpga_x2p_backannotate_utils.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
#include "fpga_bitstream.h"
|
|
||||||
|
|
||||||
/* Include SynVerilog headers */
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
#include "verilog_submodules.h"
|
|
||||||
#include "verilog_pbtypes.h"
|
|
||||||
#include "verilog_routing.h"
|
|
||||||
#include "verilog_compact_netlist.h"
|
|
||||||
#include "verilog_top_testbench.h"
|
|
||||||
#include "verilog_autocheck_top_testbench.h"
|
|
||||||
#include "verilog_verification_top_netlist.h"
|
|
||||||
#include "verilog_modelsim_autodeck.h"
|
|
||||||
#include "verilog_report_timing.h"
|
|
||||||
#include "verilog_sdc.h"
|
|
||||||
#include "verilog_formality_autodeck.h"
|
|
||||||
#include "verilog_sdc_pb_types.h"
|
|
||||||
|
|
||||||
|
|
||||||
void sdc_dump_annotation(char* from_path, // includes the cell
|
|
||||||
char* to_path,
|
|
||||||
FILE* fp,
|
|
||||||
t_pb_graph_edge* cur_edge){
|
|
||||||
|
|
||||||
float min_value = 0;
|
|
||||||
float max_value = 0;
|
|
||||||
|
|
||||||
// Find in the annotations the min and max
|
|
||||||
if (0 != cur_edge->delay_min) {
|
|
||||||
min_value = cur_edge->delay_min;
|
|
||||||
min_value = min_value*pow(10,9);
|
|
||||||
fprintf (fp, "set_min_delay -combinational_from_to -from %s -to %s ", from_path, to_path);
|
|
||||||
fprintf (fp,"%f\n", min_value);
|
|
||||||
}
|
|
||||||
if (0 != cur_edge->delay_max) {
|
|
||||||
max_value = cur_edge->delay_max;
|
|
||||||
max_value = max_value*pow(10,9);
|
|
||||||
fprintf (fp, "set_max_delay -combinational_from_to -from %s -to %s ", from_path, to_path);
|
|
||||||
fprintf (fp,"%f\n", max_value);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_sdc_pb_graph_pin_interc(FILE* fp,
|
|
||||||
t_pb_graph_pin* des_pb_graph_pin,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
char* instance_name) {
|
|
||||||
int iedge;
|
|
||||||
int fan_in = 0;
|
|
||||||
t_interconnect* cur_interc = NULL;
|
|
||||||
enum e_interconnect verilog_interc_type = DIRECT_INTERC;
|
|
||||||
|
|
||||||
t_pb_graph_pin* src_pb_graph_pin = NULL;
|
|
||||||
t_pb_graph_node* src_pb_graph_node = NULL;
|
|
||||||
|
|
||||||
t_pb_graph_node* des_pb_graph_node = NULL;
|
|
||||||
|
|
||||||
char* from_path = NULL;
|
|
||||||
char* to_path = NULL;
|
|
||||||
|
|
||||||
char* set_disable_path;
|
|
||||||
t_pb_graph_pin* cur_pin_disable;
|
|
||||||
char* input_buffer_path;
|
|
||||||
char* input_buffer_name;
|
|
||||||
char* input_buffer_in;
|
|
||||||
char* input_buffer_out;
|
|
||||||
/* Check the file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid file handler.\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1. identify pin interconnection type,
|
|
||||||
* 2. Identify the number of fan-in (Consider interconnection edges of only selected mode)
|
|
||||||
* 3. Select and print the SPICE netlist
|
|
||||||
*/
|
|
||||||
fan_in = 0;
|
|
||||||
cur_interc = NULL;
|
|
||||||
find_interc_fan_in_des_pb_graph_pin (des_pb_graph_pin, cur_mode, &cur_interc, &fan_in);
|
|
||||||
if ((NULL == cur_interc) || (0 == fan_in)) {
|
|
||||||
/* No interconnection matched */
|
|
||||||
/* Connect this pin to GND for better convergence */
|
|
||||||
/* TODO: find the correct pin name!!!*/
|
|
||||||
/*
|
|
||||||
dump_verilog_dangling_des_pb_graph_pin_interc(fp, des_pb_graph_pin, cur_mode, pin2pin_interc_type,
|
|
||||||
formatted_parent_pin_prefix);
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Initialize the interconnection type that will be implemented in SPICE netlist*/
|
|
||||||
verilog_interc_type = determine_actual_pb_interc_type (cur_interc, fan_in);
|
|
||||||
/* This time, (2nd round), we print the subckt, according to interc type*/
|
|
||||||
switch (verilog_interc_type) {
|
|
||||||
case DIRECT_INTERC:
|
|
||||||
/* Check :
|
|
||||||
* 1. Direct interc has only one fan-in!
|
|
||||||
*/
|
|
||||||
assert (1 == fan_in);
|
|
||||||
//assert(1 == des_pb_graph_pin->num_input_edges);
|
|
||||||
/* For more than one mode defined, the direct interc has more than one input_edge ,
|
|
||||||
* We need to find which edge is connected the pin we want
|
|
||||||
*/
|
|
||||||
for (iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) {
|
|
||||||
if (cur_interc == des_pb_graph_pin->input_edges[iedge]->interconnect) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert (iedge < des_pb_graph_pin->num_input_edges);
|
|
||||||
/* 2. spice_model is a wire */
|
|
||||||
assert (NULL != cur_interc->spice_model);
|
|
||||||
assert (SPICE_MODEL_WIRE == cur_interc->spice_model->type);
|
|
||||||
assert (NULL != cur_interc->spice_model->wire_param);
|
|
||||||
/* Initialize*/
|
|
||||||
/* Source pin, node, pb_type*/
|
|
||||||
src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0];
|
|
||||||
src_pb_graph_node = src_pb_graph_pin->parent_node;
|
|
||||||
/* Des pin, node, pb_type */
|
|
||||||
des_pb_graph_node = des_pb_graph_pin->parent_node;
|
|
||||||
|
|
||||||
/* if clock, clock tree synthesis will take care of the timings */
|
|
||||||
if (TRUE == src_pb_graph_pin->port->is_clock ||
|
|
||||||
TRUE == des_pb_graph_pin->port->is_clock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Generation of the paths for the dumping of the annotations
|
|
||||||
from_path = (char *) my_malloc(sizeof(char)*(strlen(instance_name) + 1 + strlen(gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (src_pb_graph_pin)) + 1));
|
|
||||||
sprintf (from_path, "%s/%s", instance_name, gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (src_pb_graph_pin));
|
|
||||||
to_path = (char *) my_malloc(sizeof(char)*(strlen(instance_name) + 1 + strlen(gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (des_pb_graph_pin)) + 1));
|
|
||||||
sprintf (to_path, "%s/%s", instance_name, gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (des_pb_graph_pin));
|
|
||||||
|
|
||||||
// Dumping of the annotations
|
|
||||||
sdc_dump_annotation (from_path, to_path, fp, des_pb_graph_pin->input_edges[iedge]);
|
|
||||||
break;
|
|
||||||
case COMPLETE_INTERC:
|
|
||||||
case MUX_INTERC:
|
|
||||||
/* Check :
|
|
||||||
* MUX should have at least 2 fan_in
|
|
||||||
*/
|
|
||||||
assert ((2 == fan_in) || (2 < fan_in));
|
|
||||||
/* 2. spice_model is a wire */
|
|
||||||
assert (NULL != cur_interc->spice_model);
|
|
||||||
assert (SPICE_MODEL_MUX == cur_interc->spice_model->type);
|
|
||||||
for (iedge = 0; iedge < des_pb_graph_pin->num_input_edges; iedge++) {
|
|
||||||
if (cur_mode != des_pb_graph_pin->input_edges[iedge]->interconnect->parent_mode) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
check_pb_graph_edge(*(des_pb_graph_pin->input_edges[iedge]));
|
|
||||||
/* Initialize*/
|
|
||||||
/* Source pin, node, pb_type*/
|
|
||||||
src_pb_graph_pin = des_pb_graph_pin->input_edges[iedge]->input_pins[0];
|
|
||||||
src_pb_graph_node = src_pb_graph_pin->parent_node;
|
|
||||||
/* Des pin, node, pb_type */
|
|
||||||
des_pb_graph_node = des_pb_graph_pin->parent_node;
|
|
||||||
// Generation of the paths for the dumping of the annotations
|
|
||||||
from_path = (char *) my_malloc(sizeof(char)*(strlen(instance_name) + 1 + strlen(gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (src_pb_graph_pin)) + 1));
|
|
||||||
sprintf (from_path, "%s/%s", instance_name, gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (src_pb_graph_pin));
|
|
||||||
to_path = (char *) my_malloc(sizeof(char)*(strlen(instance_name) + 1 + strlen(gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (des_pb_graph_pin)) + 1));
|
|
||||||
sprintf (to_path, "%s/%s", instance_name, gen_verilog_one_pb_graph_pin_full_name_in_hierarchy (des_pb_graph_pin));
|
|
||||||
|
|
||||||
/* If the pin is disabled, the dumping is different. We need to use the
|
|
||||||
* input and output of the inverter of the mux */
|
|
||||||
if (TRUE == des_pb_graph_pin->input_edges[iedge]->is_disabled) {
|
|
||||||
/* We need to find the highest node between src and des */
|
|
||||||
if (src_pb_graph_node->parent_pb_graph_node == des_pb_graph_node->parent_pb_graph_node) {
|
|
||||||
cur_pin_disable = src_pb_graph_pin->parent_node->parent_pb_graph_node->input_pins[0];
|
|
||||||
}
|
|
||||||
else if (src_pb_graph_node->parent_pb_graph_node == des_pb_graph_node) {
|
|
||||||
cur_pin_disable = des_pb_graph_pin;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cur_pin_disable = src_pb_graph_pin;
|
|
||||||
}
|
|
||||||
if (cur_interc->spice_model->input_buffer == NULL) {
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR,
|
|
||||||
"The loop_breaker annotation can only be applied when there is an input buffer");
|
|
||||||
}
|
|
||||||
if (0 == strcmp("",gen_verilog_one_pb_graph_pin_full_name_in_hierarchy_parent_node(cur_pin_disable))) {
|
|
||||||
input_buffer_path = (char *) my_malloc(sizeof(char)*(strlen(instance_name) + 1 +
|
|
||||||
strlen (cur_interc->spice_model->name) + 5 + strlen(my_itoa(cur_interc->fan_in)) + 1 +
|
|
||||||
strlen (my_itoa(des_pb_graph_pin->input_edges[iedge]->nb_mux)) + 1 + 1));
|
|
||||||
|
|
||||||
sprintf (input_buffer_path, "%s/%s_size%d_%d_",instance_name,
|
|
||||||
cur_interc->spice_model->name, cur_interc->fan_in,
|
|
||||||
des_pb_graph_pin->input_edges[iedge]->nb_mux);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
input_buffer_path = (char *) my_malloc(sizeof(char)*(strlen(instance_name) + 1 +
|
|
||||||
strlen (gen_verilog_one_pb_graph_pin_full_name_in_hierarchy_parent_node(cur_pin_disable)) +
|
|
||||||
strlen (cur_interc->spice_model->name) + 5 + strlen(my_itoa(cur_interc->fan_in)) + 1 +
|
|
||||||
strlen (my_itoa(des_pb_graph_pin->input_edges[iedge]->nb_mux)) + 1 + 1));
|
|
||||||
|
|
||||||
sprintf (input_buffer_path, "%s/%s%s_size%d_%d_",instance_name,
|
|
||||||
gen_verilog_one_pb_graph_pin_full_name_in_hierarchy_parent_node(cur_pin_disable),
|
|
||||||
cur_interc->spice_model->name, cur_interc->fan_in ,
|
|
||||||
des_pb_graph_pin->input_edges[iedge]->nb_mux);
|
|
||||||
}
|
|
||||||
input_buffer_name = cur_interc ->spice_model->input_buffer->spice_model_name;
|
|
||||||
/* BChauviere: might need to find the right port if something other than an inverter is used */
|
|
||||||
input_buffer_in = cur_interc ->spice_model->input_buffer->spice_model->ports[0].lib_name;
|
|
||||||
input_buffer_out = cur_interc ->spice_model->input_buffer->spice_model->ports[1].lib_name;
|
|
||||||
set_disable_path = (char*) my_malloc(sizeof(char)*(
|
|
||||||
strlen(input_buffer_path) + 1 +
|
|
||||||
strlen(input_buffer_name) + 1 +
|
|
||||||
strlen(my_itoa(des_pb_graph_pin->input_edges[iedge]->nb_pin))
|
|
||||||
+ 1 + 1) );
|
|
||||||
sprintf(set_disable_path, "%s/%s_%d_", input_buffer_path, input_buffer_name,
|
|
||||||
des_pb_graph_pin->input_edges[iedge]->nb_pin);
|
|
||||||
|
|
||||||
if (NULL != des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_before_min) {
|
|
||||||
fprintf (fp, "set_min_delay -from %s -to %s/%s %f \n", from_path, set_disable_path, input_buffer_in,
|
|
||||||
pow(10,9)*atof(des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_before_min));
|
|
||||||
}
|
|
||||||
if (NULL != des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_before_max) {
|
|
||||||
fprintf (fp, "set_max_delay -from %s -to %s/%s %f \n", from_path, set_disable_path, input_buffer_in,
|
|
||||||
pow(10,9)*atof(des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_before_max));
|
|
||||||
}
|
|
||||||
fprintf (fp, "set_disable_timing -from %s -to %s %s \n", input_buffer_in, input_buffer_out, set_disable_path);
|
|
||||||
if (NULL != des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_after_min) {
|
|
||||||
fprintf (fp, "set_min_delay -from %s/%s -to %s %f \n", set_disable_path, input_buffer_out,
|
|
||||||
to_path,
|
|
||||||
pow(10,9)*atof(des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_after_min));
|
|
||||||
}
|
|
||||||
if (NULL != des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_after_max) {
|
|
||||||
fprintf (fp, "set_max_delay -from %s/%s -to %s %f \n", set_disable_path, input_buffer_out,
|
|
||||||
to_path,
|
|
||||||
pow(10,9)*atof(des_pb_graph_pin->input_edges[iedge]->loop_breaker_delay_after_max));
|
|
||||||
}
|
|
||||||
my_free(input_buffer_path);
|
|
||||||
my_free(set_disable_path);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Dumping of the annotations
|
|
||||||
sdc_dump_annotation (from_path, to_path, fp, des_pb_graph_pin->input_edges[iedge]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid interconnection type for %s (Arch[LINE%d])!\n",
|
|
||||||
__FILE__, __LINE__, cur_interc->name, cur_interc->line_num);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Print the SPICE interconnections of a port defined in pb_graph */
|
|
||||||
void dump_sdc_pb_graph_port_interc(FILE* fp,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
enum e_spice_pb_port_type pb_port_type,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
char* instance_name) {
|
|
||||||
int iport, ipin;
|
|
||||||
|
|
||||||
/* Check the file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid file handler.\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pb_port_type) {
|
|
||||||
case SPICE_PB_PORT_INPUT:
|
|
||||||
for (iport = 0; iport < cur_pb_graph_node->num_input_ports; iport++) {
|
|
||||||
for (ipin = 0; ipin < cur_pb_graph_node->num_input_pins[iport]; ipin++) {
|
|
||||||
/* If this is a idle block, we set 0 to the selected edge*/
|
|
||||||
/* Get the selected edge of current pin*/
|
|
||||||
dump_sdc_pb_graph_pin_interc (fp,
|
|
||||||
&(cur_pb_graph_node->input_pins[iport][ipin]),
|
|
||||||
cur_mode,
|
|
||||||
instance_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPICE_PB_PORT_OUTPUT:
|
|
||||||
for (iport = 0; iport < cur_pb_graph_node->num_output_ports; iport++) {
|
|
||||||
for (ipin = 0; ipin < cur_pb_graph_node->num_output_pins[iport]; ipin++) {
|
|
||||||
dump_sdc_pb_graph_pin_interc(fp,
|
|
||||||
&(cur_pb_graph_node->output_pins[iport][ipin]),
|
|
||||||
cur_mode,
|
|
||||||
instance_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPICE_PB_PORT_CLOCK:
|
|
||||||
for (iport = 0; iport < cur_pb_graph_node->num_clock_ports; iport++) {
|
|
||||||
for (ipin = 0; ipin < cur_pb_graph_node->num_clock_pins[iport]; ipin++) {
|
|
||||||
dump_sdc_pb_graph_pin_interc(fp,
|
|
||||||
&(cur_pb_graph_node->clock_pins[iport][ipin]),
|
|
||||||
cur_mode,
|
|
||||||
instance_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid pb port type!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sdc_dump_cur_node_constraints(FILE* fp,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
int select_mode_index,
|
|
||||||
char* instance_name) {
|
|
||||||
int ipb, jpb;
|
|
||||||
t_mode* cur_mode = NULL;
|
|
||||||
t_pb_type* cur_pb_type = cur_pb_graph_node->pb_type;
|
|
||||||
t_pb_graph_node* child_pb_graph_node = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/* Check the file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* Check cur_pb_type*/
|
|
||||||
if (NULL == cur_pb_type) {
|
|
||||||
vpr_printf (TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid cur_pb_type.\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign current mode */
|
|
||||||
cur_mode = &(cur_pb_graph_node->pb_type->modes[select_mode_index]);
|
|
||||||
|
|
||||||
/* We check output_pins of cur_pb_graph_node and its the input_edges
|
|
||||||
* Built the interconnections between outputs of cur_pb_graph_node and outputs of child_pb_graph_node
|
|
||||||
* child_pb_graph_node.output_pins -----------------> cur_pb_graph_node.outpins
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* input_pins, edges, output_pins
|
|
||||||
*/
|
|
||||||
dump_sdc_pb_graph_port_interc(fp,
|
|
||||||
cur_pb_graph_node,
|
|
||||||
SPICE_PB_PORT_OUTPUT,
|
|
||||||
cur_mode,
|
|
||||||
instance_name);
|
|
||||||
|
|
||||||
/* We check input_pins of child_pb_graph_node and its the input_edges
|
|
||||||
* Built the interconnections between inputs of cur_pb_graph_node and inputs of child_pb_graph_node
|
|
||||||
* cur_pb_graph_node.input_pins -----------------> child_pb_graph_node.input_pins
|
|
||||||
* /|\
|
|
||||||
* |
|
|
||||||
* input_pins, edges, output_pins
|
|
||||||
*/
|
|
||||||
for (ipb = 0; ipb < cur_pb_type->modes[select_mode_index].num_pb_type_children; ipb++) {
|
|
||||||
for (jpb = 0; jpb < cur_pb_type->modes[select_mode_index].pb_type_children[ipb].num_pb; jpb++) {
|
|
||||||
child_pb_graph_node = &(cur_pb_graph_node->child_pb_graph_nodes[select_mode_index][ipb][jpb]);
|
|
||||||
/* For each child_pb_graph_node input pins*/
|
|
||||||
dump_sdc_pb_graph_port_interc(fp,
|
|
||||||
child_pb_graph_node,
|
|
||||||
SPICE_PB_PORT_INPUT,
|
|
||||||
cur_mode,
|
|
||||||
instance_name);
|
|
||||||
/* TODO: for clock pins, we should do the same work */
|
|
||||||
dump_sdc_pb_graph_port_interc(fp,
|
|
||||||
child_pb_graph_node,
|
|
||||||
SPICE_PB_PORT_CLOCK,
|
|
||||||
cur_mode,
|
|
||||||
instance_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sdc_rec_dump_child_pb_graph_node(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
char* instance_name) {
|
|
||||||
|
|
||||||
int mode_index, ipb, jpb;
|
|
||||||
t_pb_type* cur_pb_type = NULL;
|
|
||||||
|
|
||||||
/* Check the file handler */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* Check current node */
|
|
||||||
if (NULL == cur_pb_graph_node) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid cur_pb_graph_node.\n",__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
|
||||||
|
|
||||||
/* First we only go through the graph through the physical nodes. The other modes don't have sdc constraints. We then check all the children nodes and repeat the operation until arriving to the leaf nodes.
|
|
||||||
* Once at the leaf, all the edges are dumped with a default set_min/max_delay of 0 if non is user-defined.
|
|
||||||
* Contrary to the verilog, because the interconnections can get tricky through shift registers, carry-chains and all, we do not use wild cards or instantiation to be sure to completely constrain our design.
|
|
||||||
*/
|
|
||||||
/* Recursively finish all the child pb types */
|
|
||||||
if (FALSE == is_primitive_pb_type(cur_pb_type)) {
|
|
||||||
/* Find the mode that defines the physical mode*/
|
|
||||||
mode_index = find_pb_type_physical_mode_index((*cur_pb_type));
|
|
||||||
for(ipb = 0; ipb < cur_pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
|
||||||
for(jpb = 0; jpb < cur_pb_type->modes[mode_index].pb_type_children[ipb].num_pb; jpb++){
|
|
||||||
/* Contrary to the verilog, we do not need to keep the prefix
|
|
||||||
* We go done to every child node to dump the constraints now*/
|
|
||||||
sdc_rec_dump_child_pb_graph_node(cur_sram_orgz_info, fp, &(cur_pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]), instance_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sdc_dump_cur_node_constraints(fp, cur_pb_graph_node, mode_index, instance_name); // graph_head only has one pb_type
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sdc_dump_all_pb_graph_nodes(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
int type_descriptors_mode,
|
|
||||||
char* instance_name){
|
|
||||||
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
int iport, ipin;
|
|
||||||
char* port_name = NULL;
|
|
||||||
|
|
||||||
int num_output_ports = 0;
|
|
||||||
t_spice_model_port** output_ports = NULL;
|
|
||||||
|
|
||||||
// Break all the programming cells
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
assert (NULL != mem_model);
|
|
||||||
|
|
||||||
/* Check */
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,
|
|
||||||
"(FILE:%s,LINE[%d])Invalid file handler!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
assert (NULL != mem_model);
|
|
||||||
|
|
||||||
/* Find the output ports of mem_model */
|
|
||||||
output_ports = find_spice_model_ports(mem_model, SPICE_MODEL_PORT_OUTPUT, &num_output_ports, TRUE);
|
|
||||||
|
|
||||||
for (iport = 0; iport < num_output_ports; iport++) {
|
|
||||||
for (ipin = 0; ipin < output_ports[iport]->size; ipin++) {
|
|
||||||
if (TRUE == mem_model->dump_explicit_port_map) {
|
|
||||||
port_name = output_ports[iport]->lib_name;
|
|
||||||
} else {
|
|
||||||
port_name = output_ports[iport]->prefix;
|
|
||||||
}
|
|
||||||
/* Disable the timing for all the memory cells */
|
|
||||||
fprintf(fp,
|
|
||||||
"set_disable_timing [get_pins -filter \"name == %s",
|
|
||||||
port_name);
|
|
||||||
if (1 < output_ports[iport]->size) {
|
|
||||||
fprintf(fp, "[%d]", ipin);
|
|
||||||
}
|
|
||||||
fprintf(fp, "\" ");
|
|
||||||
fprintf(fp,
|
|
||||||
"-of [get_cells -hier -filter \"ref_lib_cell_name == %s\"]]\n",
|
|
||||||
mem_model->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free */
|
|
||||||
|
|
||||||
// Give head of the pb_graph to the recursive function
|
|
||||||
sdc_rec_dump_child_pb_graph_node (cur_sram_orgz_info, fp, type_descriptors[type_descriptors_mode].pb_graph_head, instance_name);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_sdc_physical_blocks(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_path,
|
|
||||||
int type_descriptor_mode,
|
|
||||||
char* instance_name) {
|
|
||||||
|
|
||||||
FILE* fp;
|
|
||||||
|
|
||||||
/* Check if the path exists*/
|
|
||||||
fp = fopen (sdc_path,"w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in creating SDC for constraining Primitive Blocks %s!",__FILE__, __LINE__, sdc_path);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
vpr_printf (TIO_MESSAGE_INFO, "Generating SDC for constraining Primitive Blocks in P&R flow: (%s)...\n",
|
|
||||||
sdc_path);
|
|
||||||
|
|
||||||
|
|
||||||
// Launch a recursive function to visit all the nodes of the correct mode
|
|
||||||
sdc_dump_all_pb_graph_nodes(fp, cur_sram_orgz_info, type_descriptor_mode, instance_name);
|
|
||||||
|
|
||||||
|
|
||||||
/* close file */
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void verilog_generate_sdc_constrain_pb_types(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_dir) {
|
|
||||||
|
|
||||||
int itype;
|
|
||||||
char* sdc_path;
|
|
||||||
char* instance_name;
|
|
||||||
|
|
||||||
sdc_path = my_strcat (sdc_dir, sdc_constrain_pb_type_file_name); // Global var
|
|
||||||
|
|
||||||
for (itype = 0; itype < num_types; itype++){
|
|
||||||
if (FILL_TYPE == &type_descriptors[itype]){
|
|
||||||
instance_name = gen_verilog_one_phy_block_instance_name(&type_descriptors[itype],0); /* it is 0 because the CLBs only have 1 block.*/
|
|
||||||
dump_sdc_physical_blocks(cur_sram_orgz_info, sdc_path, itype, instance_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
|
|
||||||
void sdc_dump_annotation(char* from_path, // includes the cell
|
|
||||||
char* to_path,
|
|
||||||
FILE* fp,
|
|
||||||
t_pb_graph_edge* cur_edge);
|
|
||||||
|
|
||||||
void dump_sdc_pb_graph_pin_interc(FILE* fp,
|
|
||||||
t_pb_graph_pin* des_pb_graph_pin,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
char* instance_name);
|
|
||||||
|
|
||||||
void dump_sdc_pb_graph_port_interc(FILE* fp,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
enum e_spice_pb_port_type pb_port_type,
|
|
||||||
t_mode* cur_mode,
|
|
||||||
char* instance_name);
|
|
||||||
|
|
||||||
void sdc_dump_cur_node_constraints(FILE* fp,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
int select_mode_index,
|
|
||||||
char* instance_name);
|
|
||||||
|
|
||||||
void sdc_rec_dump_child_pb_graph_node(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
t_pb_graph_node* cur_pb_graph_node,
|
|
||||||
char* instance_name);
|
|
||||||
|
|
||||||
void sdc_dump_all_pb_graph_nodes(FILE* fp,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
int type_descriptor_mode,
|
|
||||||
char* instance_name);
|
|
||||||
|
|
||||||
void dump_sdc_physical_blocks(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_path,
|
|
||||||
int type_descriptor_mode,
|
|
||||||
char* instance_name);
|
|
||||||
|
|
||||||
void verilog_generate_sdc_constrain_pb_types(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* sdc_dir);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,14 +13,4 @@ void print_verilog_submodules(ModuleManager& module_manager,
|
||||||
const t_arch& Arch,
|
const t_arch& Arch,
|
||||||
const t_syn_verilog_opts& fpga_verilog_opts);
|
const t_syn_verilog_opts& fpga_verilog_opts);
|
||||||
|
|
||||||
/* TODO: Old function to be deprecated */
|
|
||||||
void dump_verilog_submodules(ModuleManager& module_manager,
|
|
||||||
const MuxLibrary& mux_lib,
|
|
||||||
t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* verilog_dir,
|
|
||||||
char* submodule_dir,
|
|
||||||
t_arch Arch,
|
|
||||||
t_det_routing_arch* routing_arch,
|
|
||||||
t_syn_verilog_opts fpga_verilog_opts);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,59 +0,0 @@
|
||||||
|
|
||||||
void dump_verilog_top_netlist_ports(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
int num_clocks,
|
|
||||||
char* circuit_name,
|
|
||||||
t_spice verilog,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_top_netlist_internal_wires(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp);
|
|
||||||
|
|
||||||
void dump_verilog_defined_channels(FILE* fp,
|
|
||||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
|
||||||
t_ivec*** LL_rr_node_indices,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_defined_connection_boxes(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp, bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_defined_switch_boxes(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp, bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_clb2clb_directs(FILE* fp,
|
|
||||||
int num_directs, t_clb_to_clb_directs* direct);
|
|
||||||
|
|
||||||
void dump_verilog_configuration_circuits(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void dump_verilog_top_module_ports(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
enum e_dump_verilog_port_type dump_port_type,
|
|
||||||
bool is_explicit_mapping);
|
|
||||||
|
|
||||||
void verilog_compact_generate_fake_xy_for_io_border_side(int border_side,
|
|
||||||
int* ix, int* iy) ;
|
|
||||||
|
|
||||||
void dump_compact_verilog_grid_pins(FILE* fp,
|
|
||||||
t_type_ptr grid_type_descriptor,
|
|
||||||
boolean dump_port_type,
|
|
||||||
boolean dump_last_comma) ;
|
|
||||||
|
|
||||||
void dump_compact_verilog_io_grid_pins(FILE* fp,
|
|
||||||
t_type_ptr grid_type_descriptor,
|
|
||||||
int border_side,
|
|
||||||
boolean dump_port_type,
|
|
||||||
boolean dump_last_comma) ;
|
|
||||||
|
|
||||||
char* compact_verilog_get_grid_phy_block_subckt_name(t_type_ptr grid_type_descriptor,
|
|
||||||
int z,
|
|
||||||
char* subckt_prefix);
|
|
||||||
|
|
||||||
void dump_compact_verilog_io_grid_block_subckt_pins(FILE* fp,
|
|
||||||
t_type_ptr grid_type_descriptor,
|
|
||||||
int border_side,
|
|
||||||
int z,
|
|
||||||
bool is_explicit_mapping) ;
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,431 +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>
|
|
||||||
|
|
||||||
/* 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 "route_common.h"
|
|
||||||
|
|
||||||
/* Include SPICE support headers*/
|
|
||||||
#include "linkedlist.h"
|
|
||||||
#include "fpga_x2p_types.h"
|
|
||||||
#include "fpga_x2p_utils.h"
|
|
||||||
#include "fpga_x2p_mux_utils.h"
|
|
||||||
#include "fpga_x2p_pbtypes_utils.h"
|
|
||||||
#include "fpga_x2p_bitstream_utils.h"
|
|
||||||
#include "spice_mux.h"
|
|
||||||
#include "fpga_x2p_globals.h"
|
|
||||||
|
|
||||||
/* Include Synthesizable Verilog headers */
|
|
||||||
#include "verilog_global.h"
|
|
||||||
#include "verilog_utils.h"
|
|
||||||
#include "verilog_primitives.h"
|
|
||||||
#include "verilog_pbtypes.h"
|
|
||||||
#include "verilog_top_netlist_utils.h"
|
|
||||||
#include "verilog_top_testbench.h"
|
|
||||||
|
|
||||||
#include "verilog_verification_top_netlist.h"
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verification_top_netlist_ports(FILE* fp,
|
|
||||||
char* circuit_name) {
|
|
||||||
int iblock, cnt;
|
|
||||||
char* port_name = NULL;
|
|
||||||
|
|
||||||
fprintf(fp, "module %s%s(\n",
|
|
||||||
circuit_name,
|
|
||||||
formal_verification_top_module_postfix);
|
|
||||||
|
|
||||||
cnt = 0;
|
|
||||||
|
|
||||||
/* Print all the I/Os of the circuit implementation to be tested*/
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
/* Make sure We find the correct logical block !*/
|
|
||||||
switch (logical_block[iblock].type) {
|
|
||||||
case VPACK_INPAD:
|
|
||||||
if (0 != cnt) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
port_name = my_strdup(logical_block[iblock].name);
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_INPUT,
|
|
||||||
my_strcat(port_name, formal_verification_top_module_port_postfix),
|
|
||||||
0, 0);
|
|
||||||
my_free(port_name);
|
|
||||||
cnt++;
|
|
||||||
break;
|
|
||||||
case VPACK_OUTPAD:
|
|
||||||
if (0 != cnt) {
|
|
||||||
fprintf(fp, ",\n");
|
|
||||||
}
|
|
||||||
port_name = my_strdup(logical_block[iblock].name);
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_OUTPUT,
|
|
||||||
my_strcat(port_name, formal_verification_top_module_port_postfix),
|
|
||||||
0, 0);
|
|
||||||
my_free(port_name);
|
|
||||||
cnt++;
|
|
||||||
break;
|
|
||||||
case VPACK_COMB:
|
|
||||||
case VPACK_LATCH:
|
|
||||||
case VPACK_EMPTY:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) Invalid type of logical block[%d]!\n",
|
|
||||||
__FILE__, __LINE__, iblock);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verification_top_netlist_internal_wires(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp) {
|
|
||||||
char* port_name = NULL;
|
|
||||||
int num_array_bl, num_array_wl;
|
|
||||||
int bl_decoder_size, wl_decoder_size;
|
|
||||||
t_spice_model* mem_model = NULL;
|
|
||||||
|
|
||||||
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
|
|
||||||
|
|
||||||
/* Print internal wires */
|
|
||||||
/* Connect to defined signals */
|
|
||||||
/* set and reset signals */
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
dump_verilog_top_testbench_global_ports(fp, global_ports_head, VERILOG_PORT_WIRE);
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
|
|
||||||
/* Inputs and outputs of I/O pads */
|
|
||||||
/* Inout Pads */
|
|
||||||
assert(NULL != iopad_verilog_model);
|
|
||||||
if ((NULL == iopad_verilog_model)
|
|
||||||
||(iopad_verilog_model->cnt > 0)) {
|
|
||||||
/* Malloc and assign port_name */
|
|
||||||
port_name = (char*)my_malloc(sizeof(char)*(strlen(gio_inout_prefix) + strlen(iopad_verilog_model->prefix) + 1));
|
|
||||||
sprintf(port_name, "%s%s", gio_inout_prefix, iopad_verilog_model->prefix);
|
|
||||||
/* Dump a wired port */
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
port_name, iopad_verilog_model->cnt - 1, 0);
|
|
||||||
fprintf(fp, "; //--- FPGA iopads \n");
|
|
||||||
/* Free port_name */
|
|
||||||
my_free(port_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Programming Circuits inputs */
|
|
||||||
/* Configuration ports depend on the organization of SRAMs */
|
|
||||||
switch(cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
sram_verilog_model->prefix, sram_verilog_model->cnt - 1, 0);
|
|
||||||
fprintf(fp, "; //---- SRAM outputs \n");
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
/* We put the head of scan-chains here
|
|
||||||
*/
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_scan_chain_head_prefix, 0, 0);
|
|
||||||
fprintf(fp, "; //---- Scan-chain head \n");
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
/* Get the number of array BLs/WLs, decoder sizes */
|
|
||||||
determine_blwl_decoder_size(cur_sram_orgz_info,
|
|
||||||
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
|
|
||||||
|
|
||||||
fprintf(fp, " wire [0:0] %s;\n",
|
|
||||||
top_netlist_bl_enable_port_name
|
|
||||||
);
|
|
||||||
fprintf(fp, " wire [0:0] %s;\n",
|
|
||||||
top_netlist_wl_enable_port_name
|
|
||||||
);
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_addr_bl_port_name, bl_decoder_size - 1, 0);
|
|
||||||
fprintf(fp, "; //--- Address of bit lines \n");
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
|
||||||
top_netlist_addr_wl_port_name, wl_decoder_size - 1, 0);
|
|
||||||
fprintf(fp, "; //--- Address of word lines \n");
|
|
||||||
/* data_in is only require by BL decoder of SRAM array
|
|
||||||
* As for RRAM array, the data_in signal will not be used
|
|
||||||
*/
|
|
||||||
if (SPICE_MODEL_DESIGN_CMOS == mem_model->design_tech) {
|
|
||||||
fprintf(fp, " wire [0:0] %s; // --- Data_in signal for BL decoder, only required by SRAM array \n",
|
|
||||||
top_netlist_bl_data_in_port_name);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verfication_top_netlist_call_top_module(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp,
|
|
||||||
char* circuit_name) {
|
|
||||||
/* Include defined top-level module */
|
|
||||||
fprintf(fp, "//----- FPGA top-level module to be capsulated ----\n");
|
|
||||||
fprintf(fp, "//------Call defined Top-level Verilog Module -----\n");
|
|
||||||
fprintf(fp, "%s_top %s (\n",
|
|
||||||
circuit_name,
|
|
||||||
formal_verification_top_module_uut_name);
|
|
||||||
|
|
||||||
dump_verilog_top_module_ports(cur_sram_orgz_info, fp, VERILOG_PORT_CONKT, false);
|
|
||||||
|
|
||||||
fprintf(fp, ");\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect global ports of FPGA top module to constants except:
|
|
||||||
* 1. operating clock
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verification_top_netlist_connect_global_ports(FILE* fp,
|
|
||||||
t_llist* head) {
|
|
||||||
t_llist* temp = head;
|
|
||||||
t_spice_model_port* cur_global_port = NULL;
|
|
||||||
int ibit, iblock;
|
|
||||||
|
|
||||||
/* Check the file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "//----- Connect Global ports of FPGA top module -----\n");
|
|
||||||
while(NULL != temp) {
|
|
||||||
cur_global_port = (t_spice_model_port*)(temp->dptr);
|
|
||||||
if ((SPICE_MODEL_PORT_CLOCK == cur_global_port->type)
|
|
||||||
&& (FALSE == cur_global_port->is_prog)) {
|
|
||||||
/* Wire this port to the clock of benchmark */
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
/* By pass non-input ports !*/
|
|
||||||
if (VPACK_INPAD != logical_block[iblock].type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* See if this is a clock net */
|
|
||||||
if (FALSE == logical_block[iblock].is_clock) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Reach here we have found a clock! */
|
|
||||||
for (ibit = 0; ibit < cur_global_port->size; ibit++) {
|
|
||||||
fprintf(fp, "assign ");
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_CONKT,
|
|
||||||
cur_global_port->prefix, ibit, ibit);
|
|
||||||
fprintf(fp, " = %s%s;\n",
|
|
||||||
logical_block[iblock].name, formal_verification_top_module_port_postfix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(fp, "assign ");
|
|
||||||
dump_verilog_generic_port(fp, VERILOG_PORT_CONKT,
|
|
||||||
cur_global_port->prefix, 0, cur_global_port->size - 1);
|
|
||||||
fprintf(fp, " = %d'b", cur_global_port->size);
|
|
||||||
for (ibit = 0; ibit < cur_global_port->size; ibit++) {
|
|
||||||
fprintf(fp, "%d", cur_global_port->default_val);
|
|
||||||
}
|
|
||||||
fprintf(fp, ";\n");
|
|
||||||
}
|
|
||||||
/* Go to the next */
|
|
||||||
temp = temp->next;
|
|
||||||
}
|
|
||||||
fprintf(fp, "//----- END Global ports -----\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add stimuli for unused iopads and configuration memories */
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verification_top_netlist_connect_ios(FILE* fp) {
|
|
||||||
int iblock, jiopad, iopad_idx;
|
|
||||||
boolean* used_iopad = (boolean*) my_calloc (iopad_verilog_model->cnt, sizeof(boolean));
|
|
||||||
|
|
||||||
/* Check the file handler*/
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize */
|
|
||||||
for (jiopad = 0; jiopad < iopad_verilog_model->cnt - 1; jiopad++) {
|
|
||||||
used_iopad[jiopad] = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if this IO should be wired to a benchmark input/output */
|
|
||||||
/* Add signals from blif benchmark and short-wire them to FPGA I/O PADs
|
|
||||||
* This brings convenience to checking functionality
|
|
||||||
*/
|
|
||||||
fprintf(fp, "//-----Link Blif Benchmark inputs to FPGA IOPADs -----\n");
|
|
||||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
|
||||||
/* General INOUT*/
|
|
||||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
|
||||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
|
||||||
/* Make sure We find the correct logical block !*/
|
|
||||||
assert((VPACK_INPAD == logical_block[iblock].type)||(VPACK_OUTPAD == logical_block[iblock].type));
|
|
||||||
fprintf(fp, "//----- Blif Benchmark inout %s is mapped to FPGA IOPAD %s[%d] -----\n",
|
|
||||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
|
||||||
fprintf(fp, "//----- name_tag: %s -----\n",
|
|
||||||
logical_block[iblock].pb->spice_name_tag);
|
|
||||||
if (VPACK_INPAD == logical_block[iblock].type) {
|
|
||||||
fprintf(fp, "assign %s%s[%d] = %s%s;\n",
|
|
||||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx,
|
|
||||||
logical_block[iblock].name, formal_verification_top_module_port_postfix);
|
|
||||||
}
|
|
||||||
if (VPACK_OUTPAD == logical_block[iblock].type) {
|
|
||||||
fprintf(fp, "assign %s%s = %s%s[%d];\n",
|
|
||||||
logical_block[iblock].name, formal_verification_top_module_port_postfix,
|
|
||||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx);
|
|
||||||
}
|
|
||||||
/* Mark this iopad has been used! */
|
|
||||||
used_iopad[iopad_idx] = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wire the unused iopads to a constant */
|
|
||||||
for (jiopad = 0; jiopad < iopad_verilog_model->cnt - 1; jiopad++) {
|
|
||||||
/* Bypass used iopads */
|
|
||||||
if (TRUE == used_iopad[jiopad]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* TODO: identify if this iopad is set to input or output by default
|
|
||||||
* and see if it should be driven by a constant
|
|
||||||
*/
|
|
||||||
/* Wire to a contant */
|
|
||||||
fprintf(fp, "assign %s%s[%d] = 1'b%d;\n",
|
|
||||||
gio_inout_prefix, iopad_verilog_model->prefix, jiopad,
|
|
||||||
verilog_default_signal_init_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Impose the bitstream on the configuration memories */
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verification_top_netlist_config_bitstream(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp) {
|
|
||||||
t_llist* head = cur_sram_orgz_info->conf_bit_head;
|
|
||||||
t_llist* temp = head;
|
|
||||||
t_conf_bit_info* cur_conf_bit = NULL;
|
|
||||||
|
|
||||||
fprintf(fp, "//----- BEGIN load bitstream to configuration memories -----\n");
|
|
||||||
|
|
||||||
/* traverse the bitstream and assign values to configuration memories output ports */
|
|
||||||
while (NULL != temp) {
|
|
||||||
/* Get conf bits */
|
|
||||||
cur_conf_bit = (t_conf_bit_info*) (temp->dptr);
|
|
||||||
/* Assign */
|
|
||||||
fprintf(fp, "assign %s.", formal_verification_top_module_uut_name);
|
|
||||||
/* According to the type, we allocate structs */
|
|
||||||
switch (cur_sram_orgz_info->type) {
|
|
||||||
case SPICE_SRAM_STANDALONE:
|
|
||||||
case SPICE_SRAM_SCAN_CHAIN:
|
|
||||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
cur_conf_bit->index, cur_conf_bit->index,
|
|
||||||
VERILOG_PORT_CONKT, false);
|
|
||||||
fprintf(fp, " = 1'b%d",
|
|
||||||
cur_conf_bit->sram_bit->val);
|
|
||||||
break;
|
|
||||||
case SPICE_SRAM_MEMORY_BANK:
|
|
||||||
dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info,
|
|
||||||
cur_conf_bit->bl->addr, cur_conf_bit->bl->addr,
|
|
||||||
VERILOG_PORT_CONKT, false);
|
|
||||||
fprintf(fp, " = 1'b%d",
|
|
||||||
cur_conf_bit->bl->val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid type of SRAM organization!",
|
|
||||||
__FILE__, __LINE__);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, ";\n");
|
|
||||||
/* Go to the next */
|
|
||||||
temp = temp->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(fp, "//----- END load bitstream to configuration memories -----\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add stimuli for unused iopads and configuration memories */
|
|
||||||
static
|
|
||||||
void dump_verilog_formal_verification_top_netlist_initialization(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
FILE* fp) {
|
|
||||||
/* Connect FPGA top module global ports to constant or benchmark global signals! */
|
|
||||||
dump_verilog_formal_verification_top_netlist_connect_global_ports(fp, global_ports_head);
|
|
||||||
|
|
||||||
/* Connect I/Os to benchmark I/Os or constant driver */
|
|
||||||
dump_verilog_formal_verification_top_netlist_connect_ios(fp);
|
|
||||||
|
|
||||||
/* Assign FPGA internal SRAM/Memory ports to bitstream values */
|
|
||||||
dump_verilog_formal_verification_top_netlist_config_bitstream(cur_sram_orgz_info,
|
|
||||||
fp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Top level function 2: the top-level netlist for formal verification purpose
|
|
||||||
* This testbench includes a top-level module and initialization for all the configuration memories
|
|
||||||
*/
|
|
||||||
void dump_verilog_formal_verification_top_netlist(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* circuit_name,
|
|
||||||
const char* top_netlist_name,
|
|
||||||
char* verilog_dir_path) {
|
|
||||||
FILE* fp = NULL;
|
|
||||||
char* title = my_strcat("FPGA Verilog Top-level netlist in formal verification purpose of Design: ", circuit_name);
|
|
||||||
|
|
||||||
/* Check if the path exists*/
|
|
||||||
fp = fopen(top_netlist_name,"w");
|
|
||||||
if (NULL == fp) {
|
|
||||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create top Verilog testbench %s!",__FILE__, __LINE__, top_netlist_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
vpr_printf(TIO_MESSAGE_INFO, "Writing FPGA Top-level Verilog netlist in formal verification purpose for design %s...\n", circuit_name);
|
|
||||||
|
|
||||||
/* Print the title */
|
|
||||||
dump_verilog_file_header(fp, title);
|
|
||||||
my_free(title);
|
|
||||||
|
|
||||||
/* Print preprocessing flags */
|
|
||||||
verilog_include_defines_preproc_file(fp, verilog_dir_path);
|
|
||||||
|
|
||||||
/* Start with module declaration */
|
|
||||||
dump_verilog_formal_verification_top_netlist_ports(fp, circuit_name);
|
|
||||||
|
|
||||||
/* Define internal wires */
|
|
||||||
dump_verilog_formal_verification_top_netlist_internal_wires(cur_sram_orgz_info, fp);
|
|
||||||
|
|
||||||
/* Call defined top-level module */
|
|
||||||
dump_verilog_formal_verfication_top_netlist_call_top_module(cur_sram_orgz_info, fp, circuit_name);
|
|
||||||
|
|
||||||
/* Add stimuli for reset, set, clock and iopad signals */
|
|
||||||
dump_verilog_formal_verification_top_netlist_initialization(cur_sram_orgz_info, fp);
|
|
||||||
|
|
||||||
/* Testbench ends*/
|
|
||||||
fprintf(fp, "endmodule\n");
|
|
||||||
|
|
||||||
/* Close the file*/
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
void dump_verilog_formal_verification_top_netlist(t_sram_orgz_info* cur_sram_orgz_info,
|
|
||||||
char* circuit_name,
|
|
||||||
const char* top_netlist_name,
|
|
||||||
char* verilog_dir_path);
|
|
||||||
|
|
Loading…
Reference in New Issue