Merge pull request #33 from LNIS-Projects/dev

Remove legacy codes in FPGA-Verilog
This commit is contained in:
Laboratory for Nano Integrated Systems (LNIS) 2019-12-04 16:57:19 -07:00 committed by GitHub
commit c091b5ea99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 1300 additions and 26523 deletions

View File

@ -231,7 +231,7 @@ SRAMs
.. note:: The support SRAM modules should have a BL and a WL when the memory-bank-style configuration circuit is declared. Note that the WL should be the write/read enable signal, while BL is the data input.
Logic gates
-----
-----------
.. code-block:: xml

View File

@ -98,3 +98,5 @@ Transistor level
* **is_config_enable:** can be either ``true`` or ``false``. Only valid when ``is_global`` is true. Specify if this port controls a configuration-enable signal. This port is only enabled during FPGA configuration, and always disabled during FPGA operation. All the ``config_enable`` ports are connected to global configuration-enable voltage stimuli in testbenches.
.. note:: Different types of ``circuit_model`` have different XML syntax, with which users can highly customize their circuit topologies. See refer to examples of ``circuit_model`` for more details.
.. note:: Note that we have a list of reserved port names, which indicate the usage of these ports when building FPGA fabrics. Please do not use ``mem_out``, ``mem_inv``, ``bl``, ``wl``, ``blb``, ``wlb``, ``ccff_head`` and ``ccff_tail``.

View File

@ -1,4 +1,38 @@
Bistream Output File Format
============================
**Under Construction**
FPGA-Bitstream can generate two types of bitstreams:
* Generic bitstreams, where configuration bits are organized out-of-order in a database. We output the generic bitstream to a XML format, which is easy to debug. As shown in the following XML code, configuration bits are organized block by block, where each block could be a LUT, a routing multiplexer `etc`. Each ``bitstream_block`` includes two sets of information:
- ``hierarchy`` represents the location of this block in FPGA fabric.
- ``bitstream`` represents the configuration bits affiliated to this block.
.. code-block:: xml
<bitstream_block index="0">
<hierarchy>
<instance level="0" name="fpga_top"/>
<instance level="1" name="grid_clb_1_1"/>
<instance level="2" name="fle_0"/>
<instance level="3" name="lut4_0"/>
</hierarchy>
<bitstream>
<bit memory_port="mem_out[0]" value="1"/>
<bit memory_port="mem_out[1]" value="0"/>
<bit memory_port="mem_out[2]" value="1"/>
<bit memory_port="mem_out[3]" value="0"/>
<bit memory_port="mem_out[4]" value="1"/>
<bit memory_port="mem_out[5]" value="0"/>
<bit memory_port="mem_out[6]" value="1"/>
<bit memory_port="mem_out[7]" value="0"/>
<bit memory_port="mem_out[8]" value="1"/>
<bit memory_port="mem_out[9]" value="0"/>
<bit memory_port="mem_out[10]" value="1"/>
<bit memory_port="mem_out[11]" value="0"/>
<bit memory_port="mem_out[12]" value="1"/>
<bit memory_port="mem_out[13]" value="0"/>
<bit memory_port="mem_out[14]" value="1"/>
<bit memory_port="mem_out[15]" value="0"/>
</bitstream>
</bitstream_block>
* Fabric-dependent bitstreams, where configuration bits are organized to be loadable to the configuration protocols of FPGAs. The bitstream just sets an order to the configuration bits in the database, without duplicating the database. OpenFPGA framework provides a fabric-dependent bitstream generator which is aligned to our Verilog netlists. The fabric-dependent bitstream can be found in autogenerated Verilog testbenches.

View File

@ -1,5 +1,5 @@
FPGA-Bitstream
=============
==============
.. _fpga_bitstream:
User Manual for FPGA Bitstream Generator

View File

@ -5,20 +5,8 @@ If the --fpga_verilog_print_modelsim_autodeck option is selected, it is possible
The point of the verification step is to check that the FPGA reproduces the right function. As illustrated in :numref:`fig_ModelSim`, inside of the red rectangle is the programming of the FPGA. Each prog clock cycle corresponds to one bit added to the scan-chain. Inside of the blue rectangle, we see that the prog clock is set to 0 and the operating clock is toggled. Two outputs are shown, benchmark and FPGA, and by checking the value on both of them, we know if the functionality is respected.
.. _fig_ModelSim:
.. figure:: ./figures/Verification_step.pdf
:scale: 100%
:alt: Functional Verification using ModelSim

View File

@ -26,7 +26,7 @@ This motivates us to generate the Verilog code of the architecture to enable a s
In this manual, we present FPGA-Verilog. This extension enables the generation of a fully functional Verilog code enabling a deeper understanding of the architectures of the FPGAs. We introduce different options to this module to do the verification of the system. This will be presented in more depth in the FPGA-Bitstream section.
The technical details can be found in our TVLSI'19 paper :cite:`XTang_TVLSI_2019`.
The technical details can be found in our TVLSI'19 paper :cite:`XTang_TVLSI_2019` and FPL'19 paper :cite:`XTang_FPL_2019`.
FPGA-Bitstream
--------------
@ -34,3 +34,5 @@ FPGA-Bitstream
To have the right functionality on top of the FPGA generated, it is necessary to have a Bitstream generation which programs the FPGA. For this reason, we generate a Bitstream and some testbenches in parallel which allow the user to do some functional verification of the system to make sure that the functionality is respected. This includes three different testbenches. First, the FPGA is configured then the clock runs with random patterns are generated to test the functionality. Secondly, the FPGA can be configured in parallel to the testbench itself to do a comparison of the signals and check the validity. Finally, the configuration can be skipped to directly have access to the functioning of the system and reduce the processing time.
This will be explained in more depth in the FPGA-Bitstream section.
The technical details can be found in our TVLSI'19 paper :cite:`XTang_TVLSI_2019` and FPL'19 paper :cite:`XTang_FPL_2019`.

View File

@ -14,19 +14,6 @@ doi={10.1109/ICCD.2015.7357183},
ISSN={},
month={Oct},}
@ARTICLE{XTang_JETCAS_2018,
author={X. Tang and E. Giacomin and G. De Micheli and P. Gaillardon},
journal={IEEE Journal on Emerging and Selected Topics in Circuits and Systems},
title={Post-P amp;R Performance and Power Analysis for RRAM-Based FPGAs},
year={2018},
volume={8},
number={3},
pages={639-650},
keywords={Field programmable gate arrays;Random access memory;Analytical models;Delays;Resistance;Routing;Programmable logic arrays;resistive ram;simulation;system modeling;integrated circuit reliability},
doi={10.1109/JETCAS.2018.2847600},
ISSN={2156-3357},
month={Sept},}
@book{VBetz_Book_1999,
editor = {Betz, Vaughn and Rose, Jonathan and Marquardt, Alexander},
title = {Architecture and CAD for Deep-Submicron FPGAs},
@ -36,31 +23,6 @@ month={Sept},}
address = {Norwell, MA, USA},
}
@article{XTang_TCAS1_2016,
title={{A Study on the Programming Structures for RRAM-based FPGA Architectures}},
author={X. Tang and Kim, Gain and Gaillardon, Pierre-Emmanuel and De Micheli, Giovanni},
journal={IEEE Transactions on Circuits and Systems I: Regular Papers},
volume={63},
number={4},
pages={503--516},
year={2016},
publisher={IEEE}
}
@ARTICLE{XTang_TCAS1_2017,
author={X. Tang and E. Giacomin and G. De Micheli and P. E. Gaillardon},
journal={IEEE Transactions on Circuits and Systems I: Regular Papers},
title={{Circuit Designs of High-Performance and Low-Power RRAM-Based Multiplexers Based on 4T(ransistor)1R(RAM) Programming Structure}},
year={2017},
volume={64},
number={5},
pages={1173-1186},
keywords={Delays;Logic gates;Multiplexing;Programming;Resistance;Routing;Transistors;Circuit design;high-performance;low-power;multiplexer;resistive memory},
doi={10.1109/TCSI.2016.2638542},
ISSN={1549-8328},
month={May},}
@inproceedings{JLuu_FPGA_2011,
author = {Luu, Jason and Anderson, Jason Helge and Rose, Jonathan Scott},
title = {{Architecture Description and Packing for Logic Blocks with Hierarchy, Modes and Complex Interconnect}},
@ -119,3 +81,17 @@ month={Sept},}
ISSN={1063-8210},
month={March},
}
@INPROCEEDINGS{XTang_FPL_2019,
author={X. {Tang} and E. {Giacomin} and A. {Alacchi} and B. {Chauviere} and P. {Gaillardon}},
booktitle={2019 29th International Conference on Field Programmable Logic and Applications (FPL)},
title={OpenFPGA: An Opensource Framework Enabling Rapid Prototyping of Customizable FPGAs},
year={2019},
volume={},
number={},
pages={367-374},
keywords={field programmable gate arrays;logic design;reconfigurable architectures;software prototyping;OpenFPGA;FPGA architectures;semicustom design;XML-to-Prototype design flow;Verilog netlists;FPGA fabric;XML language;VTR framework;production-ready layouts;fully-optimized commercial products;data processing applications;Field Programmable Gate Arrays;programmable accelerators;computing systems;Verilog-to-Bitstream generator;Field programmable gate arrays;Computer architecture;Hardware design languages;XML;Microprocessors;Layout;Libraries;FPGA;Verilog generator;Bitstream generation;Semi Custom Designed FPGA},
doi={10.1109/FPL.2019.00065},
ISSN={1946-147X},
month={Sep.},}

View File

@ -1,7 +1,7 @@
//-----------------------------------------------------
// Design Name : dual_port_ram
// File Name : memory_wrapper.v
// Function : Dual port RAM 64x2048
// File Name : dpram.v
// Function : Dual port RAM 32x1024
// Coder : Aurelien
//-----------------------------------------------------
@ -41,13 +41,13 @@ module dual_port_sram (
assign d_out = internal;
always @(negedge wclk) begin
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(negedge rclk) begin
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end

View File

@ -0,0 +1,36 @@
bram $__MY_DPRAM
init 0
abits 10
dbits 32
groups 2
ports 1 1
wrmode 1 0
enable 1 1
transp 0 0
clocks 1 1
clkpol 1 1
endbram
bram $__MY_SPRAM
init 0
abits 10
dbits 32
groups 2
ports 1 1
wrmode 1 0
enable 1 0
transp 0 0
clocks 1 1
clkpol 1 1
endbram
match $__MY_DPRAM
min efficiency 0
make_transp
or_next_if_better
endmatch
match $__MY_SPRAM
min efficiency 0
make_transp
endmatch

View File

@ -0,0 +1,44 @@
module $__MY_DPRAM (
output[31:0] B1DATA,
input CLK1,
input[9:0] B1ADDR,
input[9:0] A1ADDR,
input[31:0] A1DATA,
input A1EN,
input B1EN );
generate
dpram #() _TECHMAP_REPLACE_ (
.clk (CLK1),
.wen (A1EN),
.waddr (A1ADDR),
.d_in (A1DATA),
.ren (B1EN),
.raddr (B1ADDR),
.d_out (B1DATA) );
endgenerate
endmodule
module $__MY_SPRAM (
output[31:0] B1DATA,
input CLK1,
input[9:0] B1ADDR,
input[9:0] A1ADDR,
input[31:0] A1DATA,
input A1EN );
generate
dpram #() _TECHMAP_REPLACE_ (
.clk (CLK1),
.wen (A1EN),
.waddr (A1ADDR),
.d_in (A1DATA),
.ren (1'b1),
.raddr (A1ADDR),
.d_out (B1DATA) );
endgenerate
endmodule

View File

@ -0,0 +1,62 @@
module dpram (
input clk,
input wen,
input ren,
input[9:0] waddr,
input[9:0] raddr,
input[31:0] d_in,
output[31:0] d_out );
dual_port_sram memory_0 (
.wclk (clk),
.wen (wen),
.waddr (waddr),
.data_in (d_in),
.rclk (clk),
.ren (ren),
.raddr (raddr),
.d_out (d_out) );
endmodule
module dual_port_sram (
input wclk,
input wen,
input[9:0] waddr,
input[31:0] data_in,
input rclk,
input ren,
input[9:0] raddr,
output[31:0] d_out );
reg[31:0] ram[1023:0];
reg[31:0] internal;
assign d_out = internal;
always @(posedge wclk) begin
if(wen) begin
ram[waddr] <= data_in;
end
end
always @(posedge rclk) begin
if(ren) begin
internal <= ram[raddr];
end
end
endmodule
module adder(
input cin,
input a,
input b,
output cout,
output sumout );
assign sumout = a ^ b ^ cin;
assign cout = (a & b) | ((a | b) & cin);
endmodule

View File

@ -0,0 +1,164 @@
//////////////////////////
// arithmetic //
//////////////////////////
module \$alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH:0] X, Y;
input CI, BI;
output [Y_WIDTH:0] CO;
wire [Y_WIDTH-1:0] AA, BB;
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B);
end else begin:BLOCK2
assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B);
end
endgenerate
wire [Y_WIDTH: 0 ] CARRY;
assign CARRY[0] = CI;
genvar i;
generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i]),
.cout (CARRY[i+1]),
.a (AA[i]),
.b (BB[i]),
.sumout (Y[i])
);
end endgenerate
generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4
assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1];
end else begin:gen5
adder my_adder (
.cin (CARRY[Y_WIDTH - 1]),
.cout (CARRY[Y_WIDTH]),
.a (1'b0),
.b (1'b0),
.sumout (Y[Y_WIDTH -1])
);
end
endgenerate
endmodule
//---------------------------------------------------------
module \$fa (A, B, C, X, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
input C;
output [Y_WIDTH:0] X, Y;
wire [Y_WIDTH-1:0] AA, BB;
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
assign AA = $signed(A), BB = $signed(B);
end else begin:BLOCK2
assign AA = $unsigned(A), BB = $unsigned(B);
end
endgenerate
wire [Y_WIDTH: 0 ] CARRY;
assign CARRY[0] = C;
genvar i;
generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i]),
.cout (CARRY[i+1]),
.a (AA[i]),
.b (BB[i]),
.sumout (Y[i])
);
end endgenerate
generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4
assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1];
end else begin:gen5
adder my_adder (
.cin (CARRY[Y_WIDTH - 1]),
.cout (CARRY[Y_WIDTH]),
.a (1'b0),
.b (1'b0),
.sumout (Y[Y_WIDTH -1])
);
end
endgenerate
endmodule
//---------------------------------------------------------
module \$add (A, B, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH:0] Y;
wire [Y_WIDTH-1:0] AA, BB;
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
assign AA = $signed(A), BB = $signed(B);
end else begin:BLOCK2
assign AA = $unsigned(A), BB = $unsigned(B);
end
endgenerate
wire [Y_WIDTH: 0 ] CARRY;
assign CARRY[0] = 1'b0;
genvar i;
generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i]),
.cout (CARRY[i+1]),
.a (AA[i]),
.b (BB[i]),
.sumout (Y[i])
);
end endgenerate
generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4
assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1];
end else begin:gen5
adder my_adder (
.cin (CARRY[Y_WIDTH - 1]),
.cout (CARRY[Y_WIDTH]),
.a (1'b0),
.b (1'b0),
.sumout (Y[Y_WIDTH -1])
);
end
endgenerate
endmodule

View File

@ -0,0 +1,41 @@
# Yosys synthesis script for alu4
# read Verilog
read_verilog /full_path/design.v #can be repeated if project has many files
read_verilog -lib /full_path/cells_sim.v # file we provide
hierarchy -check -top top_module
proc
flatten
tribuf -logic
synth -run coarse
opt -fast
memory -nomap
opt_clean
memory_bram -rules /full_OpenFPGA_path/openfpga_flow/misc/OpenFPGA_lib/brams.txt
techmap -map /full_OpenFPGA_path/openfpga_flow/misc/OpenFPGA_lib/brams_map.v
opt -fast -mux_undef -undriven -fine
memory_map
# Technology mapping
#proc
techmap -D NO_LUT -map /full_OpenFPGA_path/openfpga_flow/misc/OpenFPGA_lib/fpga_techmap.v -map +/adff2dff.v
# Synthesis
synth -top top_module -flatten -run fine
clean
# LUT mapping
abc -lut 6
# Check
synth -run check
# Clean and output blif
opt_clean -purge
write_blif design.blif
write_verilog design.v

View File

@ -13,6 +13,7 @@
#include <vector>
/* Include vpr structs*/
#include "vtr_assert.h"
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
@ -137,9 +138,17 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
/* Xifan TANG: Synthesizable verilog dumping */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog) {
/* Create a local SRAM organization info
* TODO: This should be deprecated in future */
VTR_ASSERT(NULL != Arch.sram_inf.verilog_sram_inf_orgz); /* Check !*/
t_spice_model* sram_verilog_model = Arch.sram_inf.verilog_sram_inf_orgz->spice_model;
/* initialize the SRAM organization information struct */
t_sram_orgz_info* sram_verilog_orgz_info = alloc_one_sram_orgz_info();
init_sram_orgz_info(sram_verilog_orgz_info, Arch.sram_inf.verilog_sram_inf_orgz->type, sram_verilog_model, nx + 2, ny + 2);
vpr_fpga_verilog(module_manager, bitstream_manager, fabric_bitstream, mux_lib,
L_logical_blocks, device_size, grids, L_blocks,
vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName);
L_logical_blocks, device_size, grids, L_blocks, device_rr_gsb,
vpr_setup, Arch, std::string(vpr_setup.FileNameOpts.CircuitName), sram_verilog_orgz_info);
}
@ -154,6 +163,9 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
sdc_options.set_generate_sdc_pnr(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_pnr);
sdc_options.set_generate_sdc_analysis(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_analysis);
/* Create directory to contain the SDC files */
create_dir_path(sdc_options.sdc_dir().c_str());
if (true == sdc_options.generate_sdc()) {
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib);
/* TODO: the critical path delay unit should be explicit! */

View File

@ -1,6 +1,7 @@
/********************************************************************
* Most utilized functions in FPGA X2P framework
*******************************************************************/
#include <sys/stat.h>
#include <string>
#include <algorithm>
@ -54,8 +55,8 @@ std::string find_path_file_name(const std::string& file_name) {
if (found != std::string::npos) {
return file_name.substr(found + 1);
}
/* Not found, return an empty string */
return std::string();
/* Not found. The input is the file name! Return the original string */
return file_name;
}
/********************************************************************
@ -133,3 +134,43 @@ std::vector<size_t> my_itobin_vec(const size_t& in_int, const size_t& bin_len) {
return ret;
}
/********************************************************************
* Create a directory with a given path
********************************************************************/
bool create_dir_path(const char* dir_path) {
/* Give up if the path is empty */
if (NULL == dir_path) {
vpr_printf(TIO_MESSAGE_INFO,
"dir_path is empty and nothing is created.\n");
return false;
}
/* Try to create a directory */
int ret = mkdir(dir_path, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
/* Analyze the return flag and output status */
switch (ret) {
case 0:
vpr_printf(TIO_MESSAGE_INFO,
"Create directory(%s)...successfully.\n",
dir_path);
return true;
case -1:
if (EEXIST == errno) {
vpr_printf(TIO_MESSAGE_WARNING,
"Directory(%s) already exists. Will overwrite contents\n",
dir_path);
return true;
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"Create directory(%s)...Failed!\n",
dir_path);
exit(1);
return false;
}
return false;
}

View File

@ -20,6 +20,8 @@ std::string find_path_file_name(const std::string& file_name);
std::vector<size_t> my_itobin_vec(const size_t& in_int, const size_t& bin_len);
bool create_dir_path(const char* dir_path);
/* Old functions */
char* my_gettime();

View File

@ -50,11 +50,12 @@ void shell_execute_fpga_verilog(t_shell_env* env, t_opt_info* opts) {
if (FALSE == shell_setup_fpga_verilog(env, opts)) {
return;
}
vpr_fpga_verilog(env->module_manager, env->bitstream_manager, env->fabric_bitstream,
env->mux_lib, env->logical_blocks, env->device_size, env->grids, env->blocks,
env->device_rr_gsb,
env->vpr_setup, env->arch,
env->vpr_setup.FileNameOpts.CircuitName);
std::string(env->vpr_setup.FileNameOpts.CircuitName), &(env->sram_orgz_info));
return;
}

View File

@ -5,6 +5,7 @@
#include "vtr_geometry.h"
#include "vpr_types.h"
#include "mux_library.h"
#include "rr_blocks.h"
#include "module_manager.h"
#include "bitstream_manager.h"
@ -45,6 +46,8 @@ struct s_shell_env {
vtr::Point<size_t> device_size;
std::vector<std::vector<t_grid_tile>> grids;
std::vector<t_block> blocks;
DeviceRRGSB device_rr_gsb;
t_sram_orgz_info sram_orgz_info;
t_arch arch;
t_vpr_setup vpr_setup;
t_shell_cmd* cmd;

View File

@ -1,552 +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 <vector>
/* Include vpr structs*/
#include "vtr_assert.h"
#include "vtr_geometry.h"
#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 "module_manager.h"
#include "mux_library.h"
#include "mux_library_builder.h"
#include "circuit_library_utils.h"
/* Include SynVerilog headers */
#include "verilog_global.h"
#include "verilog_utils.h"
#include "verilog_submodules.h"
#include "verilog_decoder.h"
#include "verilog_decoders.h"
#include "verilog_pbtypes.h"
#include "verilog_grid.h"
#include "verilog_routing.h"
#include "verilog_top_module.h"
#include "verilog_compact_netlist.h"
#include "verilog_top_testbench.h"
#include "verilog_autocheck_top_testbench.h"
#include "verilog_formal_random_top_testbench.h"
#include "verilog_preconfig_top_module.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"
#include "verilog_auxiliary_netlists.h"
#include "simulation_info_writer.h"
#include "verilog_api.h"
/***** Subroutines *****/
/* Alloc array that records Configuration bits for :
* (1) Switch blocks
* (2) Connection boxes
* TODO: Can be improved in alloc strategy to be more memory efficient!
*/
static
void alloc_global_routing_conf_bits() {
int i;
/* Alloc array for Switch blocks */
num_conf_bits_sb = (int**)my_malloc((nx+1)*sizeof(int*));
for (i = 0; i < (nx + 1); i++) {
num_conf_bits_sb[i] = (int*)my_calloc((ny+1), sizeof(int));
}
/* Alloc array for Connection blocks */
num_conf_bits_cbx = (int**)my_malloc((nx+1)*sizeof(int*));
for (i = 0; i < (nx + 1); i++) {
num_conf_bits_cbx[i] = (int*)my_calloc((ny+1), sizeof(int));
}
num_conf_bits_cby = (int**)my_malloc((nx+1)*sizeof(int*));
for (i = 0; i < (nx + 1); i++) {
num_conf_bits_cby[i] = (int*)my_calloc((ny+1), sizeof(int));
}
return;
}
static
void free_global_routing_conf_bits() {
int i;
/* Free array for Switch blocks */
for (i = 0; i < (nx + 1); i++) {
my_free(num_conf_bits_sb[i]);
}
my_free(num_conf_bits_sb);
/* Free array for Connection box */
for (i = 0; i < (nx + 1); i++) {
my_free(num_conf_bits_cbx[i]);
}
my_free(num_conf_bits_cbx);
for (i = 0; i < (nx + 1); i++) {
my_free(num_conf_bits_cby[i]);
}
my_free(num_conf_bits_cby);
return;
}
/* Top-level function*/
void vpr_fpga_verilog(ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const std::vector<ConfigBitId>& fabric_bitstream,
const MuxLibrary& mux_lib,
const std::vector<t_logical_block>& L_logical_blocks,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& L_grids,
const std::vector<t_block>& L_blocks,
t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name) {
/* Timer */
clock_t t_start;
clock_t t_end;
float run_time_sec;
int num_clocks = Arch.spice->spice_params.stimulate_params.num_clocks;
/* int vpr_crit_path_delay = Arch.spice->spice_params.stimulate_params.vpr_crit_path_delay; */
/* Directory paths */
char* verilog_dir_formatted = NULL;
char* src_dir_path = NULL;
char* submodule_dir_path= NULL;
char* lb_dir_path = NULL;
char* rr_dir_path = NULL;
char* tcl_dir_path = NULL;
char* sdc_dir_path = NULL;
char* msim_dir_path = NULL;
char* fm_dir_path = NULL;
char* top_netlist_file = NULL;
char* top_netlist_path = NULL;
char* blif_testbench_file_name = NULL;
char* blif_testbench_file_path = NULL;
char* bitstream_file_name = NULL;
char* bitstream_file_path = NULL;
char* chomped_parent_dir = NULL;
char* chomped_circuit_name = NULL;
t_sram_orgz_info* sram_verilog_orgz_info = NULL;
/* 0. basic units: inverter, buffers and pass-gate logics, */
/* Check if the routing architecture we support*/
if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) {
vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable Verilog dumping only support uni-directional routing architecture!\n");
exit(1);
}
/* We don't support mrFPGA */
#ifdef MRFPGA_H
if (is_mrFPGA) {
vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable verilog dumping do not support mrFPGA!\n");
exit(1);
}
#endif
assert ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog);
/* VerilogGenerator formally starts*/
vpr_printf(TIO_MESSAGE_INFO, "\nFPGA synthesizable verilog generator starts...\n");
/* Start time count */
t_start = clock();
/* Format the directory paths */
split_path_prog_name(circuit_name, '/', &chomped_parent_dir, &chomped_circuit_name);
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir) {
verilog_dir_formatted = format_dir_path(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir);
} else {
verilog_dir_formatted = format_dir_path(my_strcat(format_dir_path(chomped_parent_dir), default_verilog_dir_name));
}
/* SRC directory */
src_dir_path = format_dir_path(my_strcat(verilog_dir_formatted, default_src_dir_name));
/* lb directory */
lb_dir_path = my_strcat(src_dir_path, default_lb_dir_name);
/* routing resources directory */
rr_dir_path = my_strcat(src_dir_path, default_rr_dir_name);
/* submodule_dir_path */
submodule_dir_path = my_strcat(src_dir_path, default_submodule_dir_name);
/* SDC_dir_path */
sdc_dir_path = my_strcat(verilog_dir_formatted, default_sdc_dir_name);
/* tcl_dir_path */
tcl_dir_path = my_strcat(verilog_dir_formatted, default_tcl_dir_name);
/* msim_dir_path */
msim_dir_path = my_strcat(verilog_dir_formatted, default_msim_dir_name);
/* fm_dir_path */
fm_dir_path = my_strcat(verilog_dir_formatted, default_snpsfm_dir_name);
/* Top netlists dir_path */
top_netlist_file = my_strcat(chomped_circuit_name, verilog_top_postfix);
top_netlist_path = my_strcat(src_dir_path, top_netlist_file);
/* Report timing directory */
if (NULL == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.report_timing_path) {
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.report_timing_path = my_strcat(verilog_dir_formatted, default_report_timing_rpt_dir_name);
}
/* Create directories */
create_dir_path(verilog_dir_formatted);
create_dir_path(src_dir_path);
create_dir_path(lb_dir_path);
create_dir_path(rr_dir_path);
create_dir_path(sdc_dir_path);
create_dir_path(tcl_dir_path);
create_dir_path(fm_dir_path);
create_dir_path(msim_dir_path);
create_dir_path(submodule_dir_path);
/* assign the global variable of SRAM model */
assert(NULL != Arch.sram_inf.verilog_sram_inf_orgz); /* Check !*/
sram_verilog_model = Arch.sram_inf.verilog_sram_inf_orgz->spice_model;
/* initialize the SRAM organization information struct */
sram_verilog_orgz_info = alloc_one_sram_orgz_info();
init_sram_orgz_info(sram_verilog_orgz_info, Arch.sram_inf.verilog_sram_inf_orgz->type, sram_verilog_model, nx + 2, ny + 2);
/* Check all the SRAM port is using the correct SRAM SPICE MODEL */
config_spice_models_sram_port_spice_model(Arch.spice->num_spice_model,
Arch.spice->spice_models,
Arch.sram_inf.verilog_sram_inf_orgz->spice_model);
config_circuit_models_sram_port_to_default_sram_model(Arch.spice->circuit_lib, Arch.sram_inf.verilog_sram_inf_orgz->circuit_model);
/* Assign global variables of input and output pads */
iopad_verilog_model = find_iopad_spice_model(Arch.spice->num_spice_model, Arch.spice->spice_models);
assert(NULL != iopad_verilog_model);
/* zero the counter of each spice_model */
zero_spice_models_cnt(Arch.spice->num_spice_model, Arch.spice->spice_models);
/* Initialize the user-defined verilog netlists to be included */
init_list_include_verilog_netlists(Arch.spice);
/* Initial global variables about configuration bits */
alloc_global_routing_conf_bits();
/* Initialize the number of configuration bits of all the grids */
vpr_printf(TIO_MESSAGE_INFO, "Count the number of configuration bits, IO pads in each logic block...\n");
/* init_grids_num_conf_bits(sram_verilog_orgz_type); */
//init_grids_num_conf_bits(sram_verilog_orgz_info);
init_pb_types_num_conf_bits(sram_verilog_orgz_info);
//init_grids_num_iopads();
init_pb_types_num_iopads();
/* init_grids_num_mode_bits(); */
/* Print Verilog files containing preprocessing flags */
print_verilog_preprocessing_flags_netlist(std::string(src_dir_path),
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
/*
dump_verilog_simulation_preproc(src_dir_path,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
*/
/* Generate primitive Verilog modules, which are corner stones of FPGA fabric
* Note that this function MUST be called before Verilog generation of
* core logic (i.e., logic blocks and routing resources) !!!
* This is because that this function will add the primitive Verilog modules to
* the module manager.
* Without the modules in the module manager, core logic generation is not possible!!!
*/
dump_verilog_submodules(module_manager, mux_lib, sram_verilog_orgz_info, src_dir_path, submodule_dir_path,
Arch, &vpr_setup.RoutingArch,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
/* Dump routing resources: switch blocks, connection blocks and channel tracks */
print_verilog_routing_resources(module_manager, sram_verilog_orgz_info,
src_dir_path, rr_dir_path, Arch, vpr_setup.RoutingArch,
num_rr_nodes, rr_node, rr_node_indices, rr_indexed_data,
vpr_setup.FPGA_SPICE_Opts);
if (TRUE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy) {
print_verilog_unique_routing_modules(module_manager, device_rr_gsb,
vpr_setup.RoutingArch,
std::string(src_dir_path), std::string(rr_dir_path),
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
} else {
VTR_ASSERT(FALSE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
print_verilog_flatten_routing_modules(module_manager, device_rr_gsb,
vpr_setup.RoutingArch,
std::string(src_dir_path), std::string(rr_dir_path),
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
}
/* Dump logic blocks
* Branches to go:
* 1. a compact output
* 2. a full-size output
*/
print_compact_verilog_logic_blocks(sram_verilog_orgz_info, src_dir_path,
lb_dir_path, Arch,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
print_verilog_grids(module_manager,
std::string(src_dir_path), std::string(lb_dir_path),
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* Generate the Verilog module of the configuration peripheral protocol
* which loads bitstream to FPGA fabric
* TODO: generate the BL/WL decoders!!!!
*
* IMPORTANT: this function should be called after Verilog generation of
* core logic (i.e., logic blocks and routing resources) !!!
* This is due to the configuration protocol requires the total
* number of memory cells across the FPGA fabric
*/
print_verilog_config_peripherals(module_manager, sram_verilog_orgz_info, std::string(src_dir_path), std::string(submodule_dir_path));
/* TODO: This is the old function, which will be deprecated when refactoring is done */
dump_verilog_config_peripherals(sram_verilog_orgz_info, src_dir_path, submodule_dir_path);
print_verilog_top_module(module_manager,
std::string(vpr_setup.FileNameOpts.ArchFile),
std::string(src_dir_path),
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* TODO: This is the old function, which will be deprecated when refactoring is done */
dump_compact_verilog_top_netlist(sram_verilog_orgz_info, chomped_circuit_name,
top_netlist_path, src_dir_path, submodule_dir_path, lb_dir_path, rr_dir_path,
num_rr_nodes, rr_node, rr_node_indices,
num_clocks,
vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy,
*(Arch.spice), vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* Dump SDC constraints */
/* Output SDC to contrain the P&R flow
*/
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_pnr) {
verilog_generate_sdc_pnr(sram_verilog_orgz_info, sdc_dir_path,
Arch, &vpr_setup.RoutingArch,
num_rr_nodes, rr_node, rr_node_indices, rr_indexed_data,
nx, ny, device_rr_gsb,
vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
}
/* dump verilog testbench only for input blif */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_input_blif_testbench) {
blif_testbench_file_name = my_strcat(chomped_circuit_name, blif_testbench_verilog_file_postfix);
blif_testbench_file_path = my_strcat(src_dir_path, blif_testbench_file_name);
dump_verilog_input_blif_testbench(chomped_circuit_name, blif_testbench_file_path, src_dir_path,
*(Arch.spice));
/* Free */
my_free(blif_testbench_file_name);
my_free(blif_testbench_file_path);
}
/* Free sram_orgz_info:
* Free the allocated sram_orgz_info before, we start bitstream generation !
*/
free_sram_orgz_info(sram_verilog_orgz_info,
sram_verilog_orgz_info->type);
/* Force enable bitstream generator when we need to output Verilog top testbench*/
if ((TRUE == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist)) {
vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream = TRUE;
}
/* Generate bitstream if required, and also Dump bitstream file */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream) {
bitstream_file_name = my_strcat(chomped_circuit_name, fpga_spice_bitstream_output_file_postfix);
bitstream_file_path = my_strcat(src_dir_path, bitstream_file_name);
/* Run bitstream generation */
vpr_fpga_generate_bitstream(vpr_setup, Arch, circuit_name, bitstream_file_path, &sram_verilog_orgz_info);
my_free(bitstream_file_name);
my_free(bitstream_file_path);
}
/* Collect global ports from the circuit library
* TODO: move outside this function
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib);
/* dump verilog testbench only for top-level: ONLY valid when bitstream is generated! */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench) {
std::string top_testbench_file_path = std::string(src_dir_path)
+ std::string(chomped_circuit_name)
+ std::string(top_testbench_verilog_file_postfix);
/* TODO: this is an old function, to be shadowed */
dump_verilog_top_testbench(sram_verilog_orgz_info, chomped_circuit_name, top_testbench_file_path.c_str(),
src_dir_path, *(Arch.spice));
}
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist) {
std::string formal_verification_top_netlist_file_path = std::string(src_dir_path)
+ std::string(chomped_circuit_name)
+ std::string(formal_verification_verilog_file_postfix);
/* TODO: this is an old function, to be shadowed */
dump_verilog_formal_verification_top_netlist(sram_verilog_orgz_info, chomped_circuit_name,
std::string(formal_verification_top_netlist_file_path + std::string(".bak")).c_str(), src_dir_path);
/* TODO: new function: to be tested */
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
Arch.spice->circuit_lib, global_ports, L_logical_blocks,
device_size, L_grids, L_blocks,
std::string(chomped_circuit_name), formal_verification_top_netlist_file_path,
std::string(src_dir_path));
/* Output script for formality */
write_formality_script(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
fm_dir_path,
src_dir_path,
chomped_circuit_name,
*(Arch.spice));
/* Print out top-level testbench using random vectors */
std::string random_top_testbench_file_path = std::string(src_dir_path)
+ std::string(chomped_circuit_name)
+ std::string(random_top_testbench_verilog_file_postfix);
print_verilog_random_top_testbench(std::string(chomped_circuit_name), random_top_testbench_file_path,
std::string(src_dir_path), L_logical_blocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, Arch.spice->spice_params);
}
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_simulation_ini) {
/* Print exchangeable files which contains simulation settings */
std::string simulation_ini_file_name;
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.simulation_ini_path) {
simulation_ini_file_name = std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.simulation_ini_path);
}
print_verilog_simulation_info(simulation_ini_file_name,
std::string(format_dir_path(chomped_parent_dir)),
std::string(chomped_circuit_name),
std::string(src_dir_path),
bitstream_manager.bits().size(),
Arch.spice->spice_params.meas_params.sim_num_clock_cycle,
Arch.spice->spice_params.stimulate_params.prog_clock_freq,
Arch.spice->spice_params.stimulate_params.op_clock_freq);
}
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench) {
std::string autocheck_top_testbench_file_path = std::string(src_dir_path)
+ std::string(chomped_circuit_name)
+ std::string(autocheck_top_testbench_verilog_file_postfix);
/* TODO: this is an old function, to be shadowed */
/*
dump_verilog_autocheck_top_testbench(sram_verilog_orgz_info, chomped_circuit_name,
autocheck_top_testbench_file_path.c_str(), src_dir_path,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice));
*/
/* TODO: new function: to be tested */
print_verilog_top_testbench(module_manager, bitstream_manager, fabric_bitstream,
sram_verilog_orgz_info->type,
Arch.spice->circuit_lib, global_ports,
L_logical_blocks, device_size, L_grids, L_blocks,
std::string(chomped_circuit_name),
autocheck_top_testbench_file_path,
std::string(src_dir_path),
Arch.spice->spice_params);
}
/* Output Modelsim Autodeck scripts */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_modelsim_autodeck) {
dump_verilog_modelsim_autodeck(sram_verilog_orgz_info,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
*(Arch.spice),
Arch.spice->spice_params.meas_params.sim_num_clock_cycle,
msim_dir_path,
chomped_circuit_name,
src_dir_path);
}
/* Output SDC to contrain the mapped FPGA in timing-analysis purpose
*/
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_analysis) {
verilog_generate_sdc_analysis(sram_verilog_orgz_info, sdc_dir_path,
Arch,
num_rr_nodes, rr_node, rr_node_indices,
nx, ny, grid, block, device_rr_gsb,
vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
}
/* Output routing report_timing script :
*/
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_report_timing_tcl) {
verilog_generate_report_timing(sram_verilog_orgz_info, tcl_dir_path,
Arch, &vpr_setup.RoutingArch,
num_rr_nodes, rr_node, rr_node_indices,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
}
if ((TRUE == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_testbench)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench)
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist)) {
/* Free sram_orgz_info:
* Free the allocated sram_orgz_info before, we start bitstream generation !
*/
free_sram_orgz_info(sram_verilog_orgz_info,
sram_verilog_orgz_info->type);
}
/* Print a Verilog file including all the netlists that have been generated */
std::string ref_verilog_benchmark_file_name;
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file) {
ref_verilog_benchmark_file_name = std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file);
}
print_include_netlists(std::string(src_dir_path),
std::string(chomped_circuit_name),
ref_verilog_benchmark_file_name,
Arch.spice->circuit_lib);
vpr_printf(TIO_MESSAGE_INFO, "Outputted %lu Verilog modules in total.\n", module_manager.num_modules());
/* End time count */
t_end = clock();
run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
vpr_printf(TIO_MESSAGE_INFO, "Synthesizable verilog dumping took %g seconds\n", run_time_sec);
/* Free global array */
free_global_routing_conf_bits();
/* Free */
my_free(verilog_dir_formatted);
my_free(src_dir_path);
my_free(lb_dir_path);
my_free(rr_dir_path);
my_free(msim_dir_path);
my_free(fm_dir_path);
my_free(sdc_dir_path);
my_free(tcl_dir_path);
my_free(top_netlist_file);
my_free(top_netlist_path);
my_free(submodule_dir_path);
return;
}

View File

@ -0,0 +1,234 @@
/********************************************************************
* This file include top-level function of FPGA-Verilog
********************************************************************/
/* Standard header files */
#include <ctime>
/* External library header files */
#include "util.h"
#include "vtr_assert.h"
#include "circuit_library_utils.h"
/* FPGA-X2P header files */
#include "fpga_x2p_utils.h"
#include "rr_blocks.h"
/* FPGA-Verilog header files */
#include "verilog_global.h"
#include "verilog_submodules.h"
#include "verilog_routing.h"
#include "verilog_submodules.h"
#include "verilog_grid.h"
#include "verilog_routing.h"
#include "verilog_top_module.h"
#include "verilog_top_testbench.h"
#include "verilog_formal_random_top_testbench.h"
#include "verilog_preconfig_top_module.h"
#include "simulation_info_writer.h"
#include "verilog_auxiliary_netlists.h"
/* Header file for this source file */
#include "verilog_api.h"
/********************************************************************
* Top-level function of FPGA-Verilog
* This function will generate
* 1. primitive modules required by the full fabric
* which are LUTs, routing multiplexer, logic gates, transmission-gates etc.
* 2. Routing modules, which are Switch Blocks (SBs) and Connection Blocks (CBs)
* 3. Logic block modules, which are Configuration Logic Blocks (CLBs)
* 4. FPGA module, which are the full FPGA fabric with configuration protocol
* 5. A wrapper module, which encapsulate the FPGA module in a Verilog module which have the same port as the input benchmark
* 6. Testbench, where a FPGA module is configured with a bitstream and then driven by input vectors
* 7. Pre-configured testbench, which can skip the configuration phase and pre-configure the FPGA module. This testbench is created for quick verification and formal verification purpose.
* 8. Verilog netlist including preprocessing flags and all the Verilog netlists that have been generated
********************************************************************/
void vpr_fpga_verilog(ModuleManager& module_manager,
const BitstreamManager& bitstream_manager,
const std::vector<ConfigBitId>& fabric_bitstream,
const MuxLibrary& mux_lib,
const std::vector<t_logical_block>& L_logical_blocks,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& L_grids,
const std::vector<t_block>& L_blocks,
const DeviceRRGSB& L_device_rr_gsb,
const t_vpr_setup& vpr_setup,
const t_arch& Arch,
const std::string& circuit_name,
t_sram_orgz_info* sram_verilog_orgz_info) {
/* Start time count */
clock_t t_start = clock();
/* 0. basic units: inverter, buffers and pass-gate logics, */
/* Check if the routing architecture we support*/
if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) {
vpr_printf(TIO_MESSAGE_ERROR,
"FPGA-Verilog only supports uni-directional routing architecture!\n");
exit(1);
}
/* We don't support mrFPGA */
#ifdef MRFPGA_H
if (is_mrFPGA) {
vpr_printf(TIO_MESSAGE_ERROR,
"FPGA-Verilog does not support mrFPGA!\n");
exit(1);
}
#endif
/* Verilog generator formally starts*/
vpr_printf(TIO_MESSAGE_INFO,
"\nFPGA-Verilog starts...\n");
/* Format the directory paths */
std::string chomped_parent_dir = find_path_dir_name(circuit_name);
std::string chomped_circuit_name = find_path_file_name(circuit_name);
std::string verilog_dir_formatted;
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir) {
verilog_dir_formatted = format_dir_path(std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir));
} else {
verilog_dir_formatted = format_dir_path(format_dir_path(chomped_parent_dir) + std::string(default_verilog_dir_name));
}
/* Create directories */
create_dir_path(verilog_dir_formatted.c_str());
/* SRC directory to contain all the netlists */
std::string src_dir_path = format_dir_path(verilog_dir_formatted + std::string(default_src_dir_name));
create_dir_path(src_dir_path.c_str());
/* Sub directory under SRC directory to contain all the primitive block netlists */
std::string submodule_dir_path = src_dir_path + std::string(default_submodule_dir_name);
create_dir_path(submodule_dir_path.c_str());
/* Sub directory under SRC directory to contain all the logic block netlists */
std::string lb_dir_path = src_dir_path + std::string(default_lb_dir_name);
create_dir_path(lb_dir_path.c_str());
/* Sub directory under SRC directory to contain all the routing block netlists */
std::string rr_dir_path = src_dir_path + std::string(default_rr_dir_name);
create_dir_path(rr_dir_path.c_str());
/* Ensure all the SRAM port is using the correct circuit model */
config_circuit_models_sram_port_to_default_sram_model(Arch.spice->circuit_lib, Arch.sram_inf.verilog_sram_inf_orgz->circuit_model);
/* Print Verilog files containing preprocessing flags */
print_verilog_preprocessing_flags_netlist(std::string(src_dir_path),
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
print_verilog_simulation_preprocessing_flags(std::string(src_dir_path),
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
/* Generate primitive Verilog modules, which are corner stones of FPGA fabric
* Note that this function MUST be called before Verilog generation of
* core logic (i.e., logic blocks and routing resources) !!!
* This is because that this function will add the primitive Verilog modules to
* the module manager.
* Without the modules in the module manager, core logic generation is not possible!!!
*/
print_verilog_submodules(module_manager, mux_lib, sram_verilog_orgz_info, src_dir_path.c_str(), submodule_dir_path.c_str(),
Arch, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
/* Generate routing blocks */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy) {
print_verilog_unique_routing_modules(module_manager, L_device_rr_gsb,
vpr_setup.RoutingArch,
src_dir_path, rr_dir_path,
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
} else {
VTR_ASSERT(FALSE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
print_verilog_flatten_routing_modules(module_manager, L_device_rr_gsb,
vpr_setup.RoutingArch,
src_dir_path, rr_dir_path,
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
}
/* Generate grids */
print_verilog_grids(module_manager,
src_dir_path, lb_dir_path,
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* Generate FPGA fabric */
print_verilog_top_module(module_manager,
std::string(vpr_setup.FileNameOpts.ArchFile),
src_dir_path,
TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
/* Collect global ports from the circuit library
* TODO: move outside this function
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(Arch.spice->circuit_lib);
/* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_formal_verification_top_netlist) {
std::string formal_verification_top_netlist_file_path = src_dir_path + chomped_circuit_name
+ std::string(formal_verification_verilog_file_postfix);
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
Arch.spice->circuit_lib, global_ports, L_logical_blocks,
device_size, L_grids, L_blocks,
std::string(chomped_circuit_name), formal_verification_top_netlist_file_path,
std::string(src_dir_path));
/* Generate top-level testbench using random vectors */
std::string random_top_testbench_file_path = src_dir_path + chomped_circuit_name
+ std::string(random_top_testbench_verilog_file_postfix);
print_verilog_random_top_testbench(chomped_circuit_name, random_top_testbench_file_path,
src_dir_path, L_logical_blocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, Arch.spice->spice_params);
}
/* Generate exchangeable files which contains simulation settings */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_simulation_ini) {
std::string simulation_ini_file_name;
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.simulation_ini_path) {
simulation_ini_file_name = std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.simulation_ini_path);
}
print_verilog_simulation_info(simulation_ini_file_name,
format_dir_path(chomped_parent_dir),
chomped_circuit_name,
src_dir_path,
bitstream_manager.bits().size(),
Arch.spice->spice_params.meas_params.sim_num_clock_cycle,
Arch.spice->spice_params.stimulate_params.prog_clock_freq,
Arch.spice->spice_params.stimulate_params.op_clock_freq);
}
/* Generate full testbench for verification, including configuration phase and operating phase */
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench) {
std::string autocheck_top_testbench_file_path = src_dir_path + chomped_circuit_name
+ std::string(autocheck_top_testbench_verilog_file_postfix);
print_verilog_top_testbench(module_manager, bitstream_manager, fabric_bitstream,
sram_verilog_orgz_info->type,
Arch.spice->circuit_lib, global_ports,
L_logical_blocks, device_size, L_grids, L_blocks,
chomped_circuit_name,
autocheck_top_testbench_file_path,
src_dir_path,
Arch.spice->spice_params);
}
/* Generate a Verilog file including all the netlists that have been generated */
std::string ref_verilog_benchmark_file_name;
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file) {
ref_verilog_benchmark_file_name = std::string(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.reference_verilog_benchmark_file);
}
print_include_netlists(src_dir_path,
chomped_circuit_name,
ref_verilog_benchmark_file_name,
Arch.spice->circuit_lib);
/* Given a brief stats on how many Verilog modules have been written to files */
vpr_printf(TIO_MESSAGE_INFO,
"Outputted %lu Verilog modules in total\n",
module_manager.num_modules());
/* End time count */
clock_t t_end = clock();
float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
vpr_printf(TIO_MESSAGE_INFO,
"FPGA-Verilog took %g seconds\n",
run_time_sec);
}

View File

@ -1,9 +1,11 @@
#ifndef VERILOG_API_H
#define VERILOG_API_H
#include <string>
#include <vector>
#include "vpr_types.h"
#include "mux_library.h"
#include "rr_blocks.h"
#include "module_manager.h"
#include "bitstream_manager.h"
@ -15,8 +17,10 @@ void vpr_fpga_verilog(ModuleManager& module_manager,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& L_grids,
const std::vector<t_block>& L_blocks,
t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name);
const DeviceRRGSB& L_device_rr_gsb,
const t_vpr_setup& vpr_setup,
const t_arch& Arch,
const std::string& circuit_name,
t_sram_orgz_info* sram_verilog_orgz_info);
#endif

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -1,751 +0,0 @@
/***********************************/
/* Synthesizable Verilog Dumping */
/* Xifan TANG, EPFL/LSI */
/***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
/* Include vpr structs*/
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph.h"
#include "vpr_utils.h"
#include "path_delay.h"
#include "stats.h"
/* Include FPGA-SPICE utils */
#include "linkedlist.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_bitstream_utils.h"
#include "fpga_x2p_globals.h"
/* Include verilog utils */
#include "verilog_global.h"
#include "verilog_utils.h"
#include "verilog_decoder.h"
/***** Subroutines *****/
void dump_verilog_decoder_memory_bank_ports(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
enum e_dump_verilog_port_type dump_port_type) {
t_spice_model* mem_model = NULL;
int num_array_bl, num_array_wl;
int bl_decoder_size, wl_decoder_size;
char split_sign;
split_sign = determine_verilog_generic_port_split_sign(dump_port_type);
/* Only accept two types of dump_port_type here! */
assert((VERILOG_PORT_INPUT == dump_port_type)||(VERILOG_PORT_CONKT == dump_port_type));
/* Check */
assert (cur_sram_orgz_info->type == SPICE_SRAM_MEMORY_BANK);
/* A valid file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
exit(1);
}
/* Depending on the memory technology*/
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
assert(NULL != mem_model);
determine_blwl_decoder_size(cur_sram_orgz_info,
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
/* Depend on the memory technology */
switch (mem_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_bl_enable_port_name, 0, 0);
fprintf(fp, "%c //--- BL enable port \n", split_sign);
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_wl_enable_port_name, 0, 0);
fprintf(fp, "%c //--- WL enable port \n", split_sign);
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_bl_data_in_port_name, 0, 0);
fprintf(fp, "%c //--- BL data input port \n", split_sign);
break;
case SPICE_MODEL_DESIGN_RRAM:
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_bl_enable_port_name, 0, 0);
fprintf(fp, "%c //--- BL enable port \n", split_sign);
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_wl_enable_port_name, 0, 0);
fprintf(fp, "%c //--- WL enable port \n", split_sign);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
__FILE__, __LINE__);
exit(1);
}
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_addr_bl_port_name, bl_decoder_size - 1, 0);
fprintf(fp, "%c //--- Address of bit lines \n", split_sign);
dump_verilog_generic_port(fp, dump_port_type,
top_netlist_addr_wl_port_name, wl_decoder_size - 1, 0);
fprintf(fp, " //--- Address of word lines \n");
return;
}
static
void dump_verilog_decoder(FILE* fp,
t_sram_orgz_info* cur_sram_orgz_info) {
int num_array_bl, num_array_wl;
int bl_decoder_size, wl_decoder_size;
t_spice_model* mem_model = NULL;
boolean bl_inverted = FALSE;
boolean wl_inverted = FALSE;
/* Check */
assert(SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type);
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid file handler!\n",
__FILE__, __LINE__);
exit(1);
}
/* Get number of BLs,WLs and decoder sizes */
determine_blwl_decoder_size(cur_sram_orgz_info,
&num_array_bl, &num_array_wl,
&bl_decoder_size, &wl_decoder_size);
/* Different design technology requires different BL decoder logic */
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
/* Find if we need an inversion of the BL */
check_mem_model_blwl_inverted(mem_model, SPICE_MODEL_PORT_BL, &bl_inverted);
check_mem_model_blwl_inverted(mem_model, SPICE_MODEL_PORT_WL, &wl_inverted);
switch (mem_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS: /* CMOS SRAM*/
/* SRAM technology requires its BL decoder has an additional input called data_in
* only the selected BL will be set to the value of data_in, other BLs will be in high-resistance state
*/
/* Start the BL decoder module definition */
fprintf(fp, "//----- BL Decoder convert %d bits to binary %d bits -----\n",
bl_decoder_size, num_array_bl);
fprintf(fp, "module bl_decoder%dto%d (\n",
bl_decoder_size, num_array_bl);
fprintf(fp, "input wire enable,\n");
fprintf(fp, "input wire [%d:0] addr_in,\n",
bl_decoder_size - 1);
fprintf(fp, "input wire data_in,\n");
fprintf(fp, "output reg [0:%d] addr_out\n",
num_array_bl - 1);
fprintf(fp, ");\n");
/* Wee need to know the default value of bl port and wl port */
/* Internal logics */
fprintf(fp, "always@(addr_out,addr_in,enable, data_in)\n");
fprintf(fp, "begin\n");
fprintf(fp, "\taddr_out = %d'bz;\n", num_array_bl);
fprintf(fp, "\tif (1'b1 == enable) begin\n");
fprintf(fp, "\t\taddr_out[addr_in] = data_in;\n");
fprintf(fp, "\tend\n");
fprintf(fp, "end\n");
fprintf(fp, "endmodule\n");
break;
case SPICE_MODEL_DESIGN_RRAM: /* RRAM */
/* For RRAM technology, BL decoder should be same as the WL decoder */
/* Start the BL decoder module definition */
fprintf(fp, "//----- BL Decoder convert %d bits to binary %d bits -----\n",
bl_decoder_size, num_array_bl);
fprintf(fp, "module bl_decoder%dto%d (\n",
bl_decoder_size, num_array_bl);
fprintf(fp, "input wire enable,\n");
fprintf(fp, "input wire [%d:0] addr_in,\n",
bl_decoder_size-1);
fprintf(fp, "output reg [0:%d] addr_out\n",
num_array_bl-1);
fprintf(fp, ");\n");
/* Internal logics */
fprintf(fp, "always@(addr_out,addr_in,enable)\n");
fprintf(fp, "begin\n");
if (TRUE == bl_inverted) {
fprintf(fp, "\taddr_out = %d'b1;\n", num_array_bl);
} else {
assert (FALSE == bl_inverted);
fprintf(fp, "\taddr_out = %d'b0;\n", num_array_bl);
}
fprintf(fp, "\tif (1'b1 == enable) begin\n");
if (TRUE == bl_inverted) {
fprintf(fp, "\t\taddr_out[addr_in] = 1'b0;\n");
} else {
assert (FALSE == bl_inverted);
fprintf(fp, "\t\taddr_out[addr_in] = 1'b1;\n");
}
fprintf(fp, "\tend\n");
fprintf(fp, "end\n");
fprintf(fp, "endmodule\n");
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology [CMOS|RRAM] for memory technology!\n",
__FILE__, __LINE__);
exit(1);
}
/* WL decoder logic is the same whatever SRAM or RRAM technology is considered */
/* Start the WL module definition */
fprintf(fp, "//----- WL Decoder convert %d bits to binary %d bits -----\n",
wl_decoder_size, num_array_wl);
fprintf(fp, "module wl_decoder%dto%d (\n",
wl_decoder_size, num_array_wl);
fprintf(fp, "input wire enable,\n");
fprintf(fp, "input wire [%d:0] addr_in,\n",
wl_decoder_size-1);
fprintf(fp, "output reg [0:%d] addr_out\n",
num_array_bl-1);
fprintf(fp, ");\n");
/* Internal logics */
fprintf(fp, "always@(addr_out,addr_in,enable)\n");
fprintf(fp, "begin\n");
if (TRUE == wl_inverted) {
fprintf(fp, "\taddr_out = %d'b1;\n", num_array_wl);
} else {
assert (FALSE == wl_inverted);
fprintf(fp, "\taddr_out = %d'b0;\n", num_array_wl);
}
fprintf(fp, "\tif (1'b1 == enable) begin\n");
if (TRUE == wl_inverted) {
fprintf(fp, "\t\taddr_out[addr_in] = 1'b0;\n");
} else {
assert (FALSE == wl_inverted);
fprintf(fp, "\t\taddr_out[addr_in] = 1'b1;\n");
}
fprintf(fp, "\tend\n");
fprintf(fp, "end\n");
fprintf(fp, "endmodule\n");
return;
}
/* For standalone-SRAM configuration organization:
* Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
*/
static
void dump_verilog_standalone_sram_config_module(FILE* fp,
t_sram_orgz_info* cur_sram_orgz_info) {
int i, num_mem_bits;
/* Check */
assert(SPICE_SRAM_STANDALONE == cur_sram_orgz_info->type);
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File handler!",__FILE__, __LINE__);
exit(1);
}
/* Get the total memory bits */
num_mem_bits = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
/* Dump each SRAM */
fprintf(fp, "//------ Configuration Peripheral for Standalone SRAMs -----\n");
fprintf(fp, "module %s (\n",
verilog_config_peripheral_prefix);
/* Dump port map*/
fprintf(fp, "input %s_in[%d:%d],\n",
sram_verilog_model->prefix,
0, num_mem_bits - 1);
fprintf(fp, "output %s_out[%d:%d],\n",
sram_verilog_model->prefix,
0, num_mem_bits - 1);
fprintf(fp, "output %s_outb[%d:%d]);\n",
sram_verilog_model->prefix,
0, num_mem_bits - 1);
for (i = 0; i < num_mem_bits; i++) {
/* Input and 2 outputs */
fprintf(fp, "assign %s_out[%d] = %s_in[%d];\n",
sram_verilog_model->prefix, i,
sram_verilog_model->prefix, i);
fprintf(fp, ");\n");
}
fprintf(fp, "endmodule\n");
fprintf(fp, "//------ END Standalone SRAMs -----\n");
return;
}
/* For scan-chain configuration organization:
* Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
*/
static
void dump_verilog_scan_chain_config_module(FILE* fp,
t_sram_orgz_info* cur_sram_orgz_info) {
int num_mem_bits;
/* Check */
assert(SPICE_SRAM_SCAN_CHAIN == cur_sram_orgz_info->type);
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid file handler!",__FILE__, __LINE__);
exit(1);
}
/* Get the total memory bits */
num_mem_bits = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
/* Dump each Scan-chain FF */
fprintf(fp, "//------ Configuration Peripheral for Scan-chain FFs -----\n");
fprintf(fp, "module %s (\n",
verilog_config_peripheral_prefix);
/* Port map definition */
/* Scan-chain input*/
dump_verilog_generic_port(fp, VERILOG_PORT_INPUT,
top_netlist_scan_chain_head_prefix, 0, 0);
fprintf(fp, ",\n");
/* Scan-chain regular inputs */
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, num_mem_bits - 1, -1, VERILOG_PORT_OUTPUT);
fprintf(fp, ",\n");
fprintf(fp, "input ");
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, num_mem_bits - 1, 0, VERILOG_PORT_WIRE);
fprintf(fp, ");\n");
/* Connect scan-chain input to the first scan-chain input */
fprintf(fp, " ");
fprintf(fp, "assign ");
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, 0, -1, VERILOG_PORT_CONKT);
fprintf(fp, " = ");
dump_verilog_generic_port(fp, VERILOG_PORT_CONKT,
top_netlist_scan_chain_head_prefix, 0, 0);
fprintf(fp, ";\n");
/* Verilog Module body */
/* Connect the head of current ccff to the tail of previous ccff*/
fprintf(fp, " ");
fprintf(fp, "assign ");
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 1, num_mem_bits - 1, -1, VERILOG_PORT_CONKT);
fprintf(fp, " = ");
dump_verilog_sram_one_local_outport(fp, cur_sram_orgz_info, 0, num_mem_bits - 2, 0, VERILOG_PORT_CONKT);
fprintf(fp, ";\n");
fprintf(fp, "endmodule\n");
fprintf(fp, "//------ END Scan-chain FFs -----\n");
return;
}
/** Output a inverter module for inverting a BL/WL line
*/
static
void dump_verilog_membank_one_inv_module(FILE* fp,
const t_spice_model* inv_spice_model,
const char* instance_tag,
const char* in_port_name,
const char* out_port_name,
int inv_index) {
/* A valid file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
exit(1);
}
assert(NULL != instance_tag);
assert(NULL != in_port_name);
assert(NULL != out_port_name);
/* Find the input port, output port, and sram port*/
int num_buf_input_port;
int num_buf_output_port;
t_spice_model_port** buf_input_port = find_spice_model_ports(inv_spice_model, SPICE_MODEL_PORT_INPUT, &num_buf_input_port, TRUE);
t_spice_model_port** buf_output_port = find_spice_model_ports(inv_spice_model, SPICE_MODEL_PORT_OUTPUT, &num_buf_output_port, TRUE);
/* Instanciate an inverter module */
fprintf(fp, " %s %s_%s_%d (",
inv_spice_model->name, inv_spice_model->prefix,
instance_tag, inv_index);
/* Dump global ports */
if (0 < rec_dump_verilog_spice_model_global_ports(fp, inv_spice_model, FALSE, FALSE, inv_spice_model->dump_explicit_port_map, TRUE)) {
fprintf(fp, ",\n");
}
/* Dump explicit port map if required */
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
fprintf(fp, ".%s(",
buf_input_port[0]->lib_name);
}
fprintf(fp, "%s[%d]",
in_port_name, inv_index);
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
fprintf(fp, ")");
}
fprintf(fp, ", ");
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
fprintf(fp, ".%s(",
buf_output_port[0]->lib_name);
}
fprintf(fp, "%s[%d]",
out_port_name, inv_index);
if ( TRUE == inv_spice_model->dump_explicit_port_map) {
fprintf(fp, ")");
}
fprintf(fp, ");\n");
/* Free */
my_free(buf_input_port);
my_free(buf_output_port);
return;
}
/* For Memory-bank configuration organization:
* Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
*/
static
void dump_verilog_membank_config_module(FILE* fp,
t_sram_orgz_info* cur_sram_orgz_info) {
t_spice_model* mem_model = NULL;
int iinv, icol, irow;
int num_bl, num_wl;
int num_array_bl, num_array_wl;
int num_reserved_bl, num_reserved_wl;
int cur_bl_lsb, cur_wl_lsb;
int cur_bl_msb, cur_wl_msb;
int bl_decoder_size, wl_decoder_size;
int num_blb_ports, num_wlb_ports;
t_spice_model_port** blb_port = NULL;
t_spice_model_port** wlb_port = NULL;
t_spice_model* blb_inv_spice_model = NULL;
t_spice_model* wlb_inv_spice_model = NULL;
/* Check */
assert(SPICE_SRAM_MEMORY_BANK == cur_sram_orgz_info->type);
assert(NULL != cur_sram_orgz_info->mem_bank_info);
/* A valid file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
exit(1);
}
/* Depending on the memory technology*/
get_sram_orgz_info_mem_model(cur_sram_orgz_info, &mem_model);
assert(NULL != mem_model);
/* Get the total number of BLs and WLs */
get_sram_orgz_info_num_blwl(cur_sram_orgz_info, &num_bl, &num_wl);
/* Get the reserved BLs and WLs */
get_sram_orgz_info_reserved_blwl(cur_sram_orgz_info, &num_reserved_bl, &num_reserved_wl);
determine_blwl_decoder_size(cur_sram_orgz_info,
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
/* Get BLB and WLB ports */
find_blb_wlb_ports_spice_model(mem_model, &num_blb_ports, &blb_port,
&num_wlb_ports, &wlb_port);
/* Get inverter spice_model */
/* Dump each SRAM */
fprintf(fp, "//------ Configuration Peripheral for Memory-bank -----\n");
fprintf(fp, "module %s (\n",
verilog_config_peripheral_prefix);
/* Port map */
/* Ports for memory decoders */
dump_verilog_decoder_memory_bank_ports(cur_sram_orgz_info, fp, VERILOG_PORT_INPUT);
fprintf(fp, ",\n");
/* Ports for all the SRAM cells */
switch (mem_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
assert( 0 == num_reserved_bl );
assert( 0 == num_reserved_wl );
/* Declare normal BL / WL inputs */
fprintf(fp, " output wire [%d:%d] %s%s",
0, num_bl - 1, mem_model->prefix, top_netlist_normal_bl_port_postfix);
fprintf(fp, ", //---- Normal Bit lines \n");
fprintf(fp, " output wire [%d:%d] %s%s",
0, num_wl - 1, mem_model->prefix, top_netlist_normal_wl_port_postfix);
/* Declare inverted wires if needed */
if (1 == num_blb_ports) {
fprintf(fp, ", //---- Normal Word lines \n");
} else {
fprintf(fp, " //---- Normal Word lines\n");
}
if (1 == num_blb_ports) {
fprintf(fp, " output wire [%d:%d] %s%s",
0, num_bl - 1, mem_model->prefix, top_netlist_normal_blb_port_postfix);
}
if (1 == num_wlb_ports) {
fprintf(fp, ", //---- Inverted Normal Bit lines \n");
} else {
fprintf(fp, " //---- Inverted Normal Bit lines \n");
}
if (1 == num_wlb_ports) {
fprintf(fp, " output wire [%d:%d] %s%s //---- Inverted Normal Word lines \n",
0, num_wl - 1, mem_model->prefix, top_netlist_normal_wlb_port_postfix);
}
fprintf(fp, ");\n");
break;
case SPICE_MODEL_DESIGN_RRAM:
/* Check: there should be reserved BLs and WLs */
assert( 0 < num_reserved_bl );
assert( 0 < num_reserved_wl );
/* Declare reserved and normal conf_bits ports */
fprintf(fp, " input wire [0:%d] %s%s, //---- Reserved Bit lines \n",
num_reserved_bl - 1, mem_model->prefix, top_netlist_reserved_bl_port_postfix);
fprintf(fp, " input wire [0:%d] %s%s, //---- Reserved Word lines \n",
num_reserved_wl - 1, mem_model->prefix, top_netlist_reserved_wl_port_postfix);
fprintf(fp, " input wire [%d:%d] %s%s, //---- Normal Bit lines \n",
num_reserved_bl, num_array_bl - 1, mem_model->prefix, top_netlist_normal_bl_port_postfix);
fprintf(fp, " input wire [%d:%d] %s%s); //---- Normal Word lines \n",
num_reserved_wl, num_array_wl - 1, mem_model->prefix, top_netlist_normal_wl_port_postfix);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
__FILE__, __LINE__);
exit(1);
}
/* Important!!!:
* BL/WL should always start from LSB to MSB!
* In order to follow this convention in primitive nodes.
*/
fprintf(fp, "\n");
/* No. of BLs and WLs in the array */
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
top_netlist_array_bl_port_name, 0, num_array_bl - 1);
fprintf(fp, "; //--- Array Bit lines bus \n");
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
top_netlist_array_wl_port_name, 0, num_array_wl - 1);
fprintf(fp, "; //--- Array Bit lines bus \n");
if (1 == num_blb_ports) {
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
top_netlist_array_blb_port_name, 0, num_array_bl - 1);
fprintf(fp, "; //--- Inverted Array Bit lines bus \n");
}
if (1 == num_wlb_ports) {
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
top_netlist_array_wlb_port_name, 0, num_array_wl - 1);
fprintf(fp, "; //--- Inverted Array Word lines bus \n");
}
fprintf(fp, "\n");
switch (mem_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
assert( 0 == num_reserved_bl );
assert( 0 == num_reserved_wl );
/* SRAMs are place in an array
* BLs of SRAMs in the same column are connected to a common BL
* BLs of SRAMs in the same row are connected to a common WL
*/
/* Declare inverted wires if needed */
if (1 == num_blb_ports) {
/* get inv_spice_model */
blb_inv_spice_model = blb_port[0]->inv_spice_model;
/* Make an inversion of the BL */
for (iinv = 0; iinv < num_array_bl; iinv++) {
dump_verilog_membank_one_inv_module(fp, blb_inv_spice_model, "blb",
top_netlist_array_bl_port_name,
top_netlist_array_blb_port_name,
iinv);
}
}
if (1 == num_wlb_ports) {
/* get inv_spice_model */
wlb_inv_spice_model = wlb_port[0]->inv_spice_model;
/* Make an inversion of the WL */
for (iinv = 0; iinv < num_array_wl; iinv++) {
dump_verilog_membank_one_inv_module(fp, wlb_inv_spice_model, "wlb",
top_netlist_array_wl_port_name,
top_netlist_array_wlb_port_name,
iinv);
}
}
/* Connections for columns */
for (icol = 0; icol < num_array_bl; icol++) {
cur_bl_lsb = icol * num_array_bl;
cur_bl_msb = (icol + 1) * num_array_bl - 1;
/* Check if the msb exceeds the upbound of num_bl */
if (cur_bl_msb > num_bl - 1) {
cur_bl_msb = num_bl - 1;
}
/* connect to the BLs of all the SRAMs in the column */
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
mem_model->prefix, top_netlist_normal_bl_port_postfix, cur_bl_lsb, cur_bl_msb,
top_netlist_array_bl_port_name, 0, cur_bl_msb - cur_bl_lsb);
if (1 == num_blb_ports) {
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
mem_model->prefix, top_netlist_normal_blb_port_postfix, cur_bl_lsb, cur_bl_msb,
top_netlist_array_blb_port_name, 0, cur_bl_msb - cur_bl_lsb);
}
/* Finish if MSB meets the upbound */
if (cur_bl_msb == num_bl - 1) {
break;
}
}
/* Connections for rows */
for (irow = 0; irow < num_array_wl; irow++) {
cur_wl_lsb = irow * num_array_wl;
cur_wl_msb = (irow + 1) * num_array_wl - 1;
/* Check if the msb exceeds the upbound of num_bl */
if (cur_wl_msb > num_wl - 1) {
cur_wl_msb = num_wl - 1;
}
/* connect to the BLs of all the SRAMs in the column */
for (icol = cur_wl_lsb; icol < cur_wl_msb + 1; icol++) {
fprintf(fp, " assign %s%s[%d] = %s[%d];\n",
mem_model->prefix, top_netlist_normal_wl_port_postfix, icol,
top_netlist_array_wl_port_name, irow);
if (1 == num_wlb_ports) {
fprintf(fp, " assign %s%s[%d] = %s[%d];\n",
mem_model->prefix, top_netlist_normal_wlb_port_postfix, icol,
top_netlist_array_wlb_port_name, irow);
}
}
/* Finish if MSB meets the upbound */
if (cur_wl_msb == num_wl - 1) {
break;
}
}
break;
case SPICE_MODEL_DESIGN_RRAM:
/* Check: there should be reserved BLs and WLs */
assert( 0 < num_reserved_bl );
assert( 0 < num_reserved_wl );
/* Declare reserved and normal conf_bits ports */
fprintf(fp, " wire [0:%d] %s%s; //---- Reserved Bit lines \n",
num_reserved_bl - 1, mem_model->prefix, top_netlist_reserved_bl_port_postfix);
fprintf(fp, " wire [0:%d] %s%s; //---- Reserved Word lines \n",
num_reserved_wl - 1, mem_model->prefix, top_netlist_reserved_wl_port_postfix);
fprintf(fp, " wire [%d:%d] %s%s; //---- Normal Bit lines \n",
num_reserved_bl, num_array_bl - 1, mem_model->prefix, top_netlist_normal_bl_port_postfix);
fprintf(fp, " wire [%d:%d] %s%s; //---- Normal Word lines \n",
num_reserved_wl, num_array_wl - 1, mem_model->prefix, top_netlist_normal_wl_port_postfix);
/* Connect reserved conf_bits and normal conf_bits to the bus */
fprintf(fp, " assign %s%s[0:%d] = %s[0:%d];\n",
mem_model->prefix, top_netlist_reserved_bl_port_postfix, num_reserved_bl - 1,
top_netlist_array_bl_port_name, num_reserved_bl - 1);
fprintf(fp, " assign %s%s[0:%d] = %s[0:%d];\n",
mem_model->prefix, top_netlist_reserved_wl_port_postfix, num_reserved_wl - 1,
top_netlist_array_wl_port_name, num_reserved_wl - 1);
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
mem_model->prefix, top_netlist_normal_bl_port_postfix, num_reserved_bl, num_array_bl - 1,
top_netlist_array_bl_port_name, num_reserved_bl, num_array_bl - 1);
fprintf(fp, " assign %s%s[%d:%d] = %s[%d:%d];\n",
mem_model->prefix, top_netlist_normal_wl_port_postfix, num_reserved_wl, num_array_wl - 1,
top_netlist_array_wl_port_name, num_reserved_wl, num_array_wl - 1);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
__FILE__, __LINE__);
exit(1);
}
/* Comment lines */
fprintf(fp, "//----- BEGIN call decoders for memory bank controller -----\n");
/* Dump Decoders for Bit lines and Word lines */
/* Two huge decoders
* TODO: divide to a number of small decoders ?
*/
/* Bit lines decoder */
fprintf(fp, " ");
fprintf(fp, "bl_decoder%dto%d mem_bank_bl_decoder (",
bl_decoder_size, num_array_bl);
/* Prefix of BL & WL is fixed, in order to simplify grouping nets */
fprintf(fp, "%s, %s[%d:0], ",
top_netlist_bl_enable_port_name,
top_netlist_addr_bl_port_name, bl_decoder_size - 1);
/* Port map depends on the memory technology */
switch (mem_model->design_tech) {
case SPICE_MODEL_DESIGN_CMOS:
/* Data input port of BL decoder, only required by SRAM array */
fprintf(fp, "%s, ",
top_netlist_bl_data_in_port_name);
break;
case SPICE_MODEL_DESIGN_RRAM:
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
__FILE__, __LINE__);
exit(1);
}
fprintf(fp, "%s[0:%d]",
top_netlist_array_bl_port_name, num_array_bl - 1);
fprintf(fp, ");\n");
/* Word lines decoder is the same for both technology */
fprintf(fp, " ");
fprintf(fp, "wl_decoder%dto%d mem_bank_wl_decoder (",
wl_decoder_size, num_array_wl);
fprintf(fp, "%s, %s[%d:0], ",
top_netlist_wl_enable_port_name,
top_netlist_addr_wl_port_name, wl_decoder_size - 1);
fprintf(fp, "%s[0:%d]",
top_netlist_array_wl_port_name, num_array_wl - 1);
fprintf(fp, ");\n");
fprintf(fp, "//----- END call decoders for memory bank controller -----\n\n");
/* Comment lines */
fprintf(fp, "endmodule\n");
fprintf(fp, "//----- END configuration peripheral for memory-bank -----\n\n");
}
/* Top-level function */
void dump_verilog_config_peripherals(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir_path,
char* submodule_dir_path) {
FILE* fp = NULL;
char* verilog_name = my_strcat(submodule_dir_path, config_peripheral_verilog_file_name);
/* Open file and file handler */
fp = fopen(verilog_name, "w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create decoder SPICE netlist %s",
__FILE__, __LINE__, verilog_name);
exit(1);
}
/* Generate file header*/
vpr_printf(TIO_MESSAGE_INFO, "Writing configuration peripheral verilog netlist...\n");
/* Generate the descriptions*/
dump_verilog_file_header(fp, " Verilog Configuration Peripheral");
verilog_include_defines_preproc_file(fp, verilog_dir_path);
switch(cur_sram_orgz_info->type) {
case SPICE_SRAM_STANDALONE:
break;
case SPICE_SRAM_SCAN_CHAIN:
dump_verilog_scan_chain_config_module(fp, cur_sram_orgz_info);
break;
case SPICE_SRAM_MEMORY_BANK:
/* Dump verilog decoder */
dump_verilog_decoder(fp, cur_sram_orgz_info);
dump_verilog_membank_config_module(fp, cur_sram_orgz_info);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
__FILE__, __LINE__);
exit(1);
}
/* Close the file*/
fclose(fp);
/* Add fname to the linked list */
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_name);
return;
}

View File

@ -1,12 +0,0 @@
#ifndef VERILOG_DECODER_H
#define VERILOG_DECODER_H
void dump_verilog_decoder_memory_bank_ports(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
enum e_dump_verilog_port_type dump_port_type);
void dump_verilog_config_peripherals(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir_path,
char* submodule_dir);
#endif

View File

@ -1,315 +0,0 @@
/***********************************/
/* SPICE Modeling for VPR */
/* Xifan TANG, EPFL/LSI */
/***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#define MINI_CASE_SENSITIVE
#include "ini.h"
/* Include vpr structs*/
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph_util.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "route_common.h"
#include "vpr_utils.h"
/* Include SPICE support headers*/
#include "linkedlist.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_backannotate_utils.h"
#include "fpga_x2p_mux_utils.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "fpga_x2p_bitstream_utils.h"
#include "fpga_x2p_rr_graph_utils.h"
#include "fpga_x2p_globals.h"
/* Include Verilog support headers*/
#include "verilog_global.h"
#include "verilog_utils.h"
#include "verilog_routing.h"
#include "verilog_tcl_utils.h"
mINI::INIStructure ini;
static void searching_used_latch(FILE *fp, t_pb * pb, int pb_index, char* chomped_circuit_name, char* inst_name){
int i, j;
char WriteBuffer[200];
char INI_lbl[100];
// char* tmp = NULL;
const t_pb_type *pb_type;
t_mode *mode;
t_pb_graph_node * node;
// char* index = NULL;
pb_type = pb->pb_graph_node->pb_type;
node = pb->pb_graph_node->physical_pb_graph_node;
mode = &pb_type->modes[pb->mode];
// tmp = (char*) my_malloc(sizeof(1 + (strlen(ff_hierarchy) + 1 + strlen(my_strcat(pb_type->name, index)))));
// tmp = ff_hierarchy;
// index = my_strcat("_", my_strcat(my_itoa(pb_index), "_"));
if (pb_type->num_modes > 0) {
for (i = 0; i < mode->num_pb_type_children; i++) {
for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
// if(strcmp(pb_type->name, mode->name) != 0)
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->name, index)));
if(pb->child_pbs[i][j].name != NULL)
searching_used_latch(fp, &pb->child_pbs[i][j], j, chomped_circuit_name, inst_name);
}
}
} else if((pb_type->class_type == LATCH_CLASS) && (pb->name)){
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->physical_pb_type_name, my_strcat(index, "/dff_0_"))));
fprintf(fp, "set_user_match r:/WORK/%s/%s_reg i:/WORK/%s/%sdff_0 -type cell -noninverted\n", chomped_circuit_name,
pb->name,
inst_name,
gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node) );
sprintf(WriteBuffer, "%s/%sdff_0 ",
inst_name, gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node));
sprintf(INI_lbl, "%s_reg", pb->name);
ini["REGISTER_MATCH"][INI_lbl] = WriteBuffer;
}
//free(tmp); //Looks like is the cause of a double free, once free executated next iteration as no value in tmp
return;
}
static void clb_iteration(FILE *fp, char* chomped_circuit_name, int h){
t_pb* pb;
char* inst_name = NULL;
const t_pb_type *pb_type;
t_mode *mode;
int i, j, x_pos, y_pos;
char* grid_x = NULL;
char* grid_y = NULL;
x_pos = block[h].x;
y_pos = block[h].y;
pb = (t_pb*) block[h].pb;
pb_type = pb->pb_graph_node->pb_type;
mode = &pb_type->modes[pb->mode];
grid_x = my_strcat("_", my_strcat(my_itoa(x_pos), "_"));
grid_y = my_strcat("_", my_strcat(my_itoa(y_pos), "_"));
if (strcmp(pb_type->name, FILL_TYPE->name) == 0) {
inst_name = my_strcat(chomped_circuit_name, my_strcat(formal_verification_top_postfix, my_strcat("/", my_strcat(formal_verification_top_module_uut_name, my_strcat("/grid",my_strcat(grid_x, my_strcat(grid_y, "/" )))))));
if (pb_type->num_modes > 0) {
for (i = 0; i < mode->num_pb_type_children; i++) {
inst_name = my_strcat(inst_name, my_strcat("grid_", my_strcat(pb_type->name, my_strcat("_", my_strcat(my_itoa(i), "_")))));
for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
/* If child pb is not used but routing is used, I must print things differently */
if ((pb->child_pbs[i] != NULL)
&& (pb->child_pbs[i][j].name != NULL)) {
searching_used_latch(fp, &pb->child_pbs[i][j], j, chomped_circuit_name, inst_name);
}
}
}
}
}
return;
}
static void match_registers(FILE *fp, char* chomped_circuit_name) {
int h;
for(h = 0; h < copy_nb_clusters; h++)
clb_iteration(fp, chomped_circuit_name, h);
/* for(h = 0; h < copy_nb_clusters; h++){
free_cb(copy_clb[h].pb);
free(copy_clb[h].name);
free(copy_clb[h].nets);
free(copy_clb[h].pb);
}*/
// free(copy_clb);
// free(block);
return;
}
static
void formality_include_user_defined_verilog_netlists(FILE* fp,
t_spice spice) {
int i;
/* A valid file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Invalid File Handler!\n",
__FILE__, __LINE__);
exit(1);
}
/* Include user-defined sub-circuit netlist */
for (i = 0; i < spice.num_include_netlist; i++) {
if (0 == spice.include_netlists[i].included) {
assert(NULL != spice.include_netlists[i].path);
fprintf(fp, "%s ", spice.include_netlists[i].path);
spice.include_netlists[i].included = 1;
} else {
assert(1 == spice.include_netlists[i].included);
}
}
return;
}
void write_formality_script (t_syn_verilog_opts fpga_verilog_opts,
char* fm_dir_formatted,
char* src_dir_formatted,
char* chomped_circuit_name,
t_spice spice){
int iblock, i, FileCounter=0;
char* formality_script_file_name = NULL;
char* benchmark_path = NULL;
char* original_output_name = NULL;
char WriteBuffer[4096];
char INI_lbl[4096];
/* int output_length; */
/* int pos; */
FILE* fp = NULL;
if(TRUE == fpga_verilog_opts.print_autocheck_top_testbench)
benchmark_path = fpga_verilog_opts.reference_verilog_benchmark_file;
else
benchmark_path = "Insert verilog benchmark path";
formality_script_file_name = my_strcat(fm_dir_formatted, my_strcat(chomped_circuit_name, formality_script_name_postfix));
fp = fopen(formality_script_file_name, "w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Failure in create formality script %s",
__FILE__, __LINE__, formality_script_file_name);
exit(1);
}
/* Load Verilog benchmark as reference */
fprintf(fp, "read_verilog -container r -libname WORK -05 { %s }\n", benchmark_path);
ini["BENCHMARK_INFO"]["benchmark_netlist "] = benchmark_path;
/* Set reference top */
fprintf(fp, "set_top r:/WORK/%s\n", chomped_circuit_name);
ini["BENCHMARK_INFO"]["src_top_module "] = chomped_circuit_name;
/* Load generated verilog as implemnetation */
fprintf(fp, "read_verilog -container i -libname WORK -05 { ");
fprintf(fp, "%s%s%s ", src_dir_formatted,
chomped_circuit_name,
verilog_top_postfix);
sprintf(WriteBuffer, "%s%s%s", src_dir_formatted, chomped_circuit_name,
verilog_top_postfix);
sprintf(INI_lbl, "impl_netlist_%02d",FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
fprintf(fp, "%s%s%s ", src_dir_formatted,
chomped_circuit_name,
formal_verification_verilog_file_postfix);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
chomped_circuit_name, formal_verification_verilog_file_postfix);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
init_include_user_defined_verilog_netlists(spice);
// formality_include_user_defined_verilog_netlists(fp, spice);
/* Include user-defined sub-circuit netlist */
for (i = 0; i < spice.num_include_netlist; i++) {
if (0 == spice.include_netlists[i].included) {
assert(NULL != spice.include_netlists[i].path);
fprintf(fp, "%s ", spice.include_netlists[i].path);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = spice.include_netlists[i].path;
spice.include_netlists[i].included = 1;
} else {
assert(1 == spice.include_netlists[i].included);
}
}
fprintf(fp, "%s%s%s ", src_dir_formatted,
default_rr_dir_name,
routing_verilog_file_name);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
default_rr_dir_name,
routing_verilog_file_name);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fprintf(fp, "%s%s%s ", src_dir_formatted,
default_lb_dir_name,
logic_block_verilog_file_name);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
default_lb_dir_name,
logic_block_verilog_file_name);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fprintf(fp, "%s%s%s ", src_dir_formatted,
default_submodule_dir_name,
submodule_verilog_file_name);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
default_submodule_dir_name,
submodule_verilog_file_name);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
fprintf(fp, "}\n");
/* Set implementation top */
fprintf(fp, "set_top i:/WORK/%s\n", my_strcat(chomped_circuit_name,
formal_verification_top_postfix));
sprintf(WriteBuffer, "%s", my_strcat(chomped_circuit_name,
formal_verification_top_postfix));
ini["FPGA_INFO"]["impl_top_module"] = WriteBuffer;
/* Run matching */
fprintf(fp, "match\n");
/* Add manual matching for the outputs */
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
original_output_name = NULL;
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
/* Make sure We find the correct logical block !*/
assert((VPACK_INPAD == logical_block[iblock].type)
||(VPACK_OUTPAD == logical_block[iblock].type));
if(VPACK_OUTPAD == logical_block[iblock].type){
/* output_length = strlen(logical_block[iblock].name); */
original_output_name = logical_block[iblock].name + 4;
/* printf("%s", original_output_name); */
fprintf(fp, "set_user_match r:/WORK/%s/%s i:/WORK/%s/%s[0] -type port -noninverted\n",
chomped_circuit_name,
original_output_name,
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
my_strcat(logical_block[iblock].name,
formal_verification_top_module_port_postfix));
sprintf(WriteBuffer, "%s/%s[0]",
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
my_strcat(logical_block[iblock].name, formal_verification_top_module_port_postfix));
sprintf(INI_lbl, "%s", original_output_name);
ini["PORT_MATCHING"][INI_lbl] = WriteBuffer;
}
}
}
match_registers(fp, chomped_circuit_name);
/* Run verification */
fprintf(fp, "verify\n");
/* Script END */
fclose(fp);
mINI::INIFile file(my_strcat(formality_script_file_name,".ini"));
file.generate(ini, true);
return;
}

View File

@ -1,5 +0,0 @@
void write_formality_script (t_syn_verilog_opts fpga_verilog_opts,
char* fm_dir_formatted,
char* src_dir_formatted,
char* chomped_circuit_name,
t_spice spice);

View File

@ -262,9 +262,7 @@ void print_verilog_grid(ModuleManager& module_manager,
fp.close();
/* Add fname to the linked list */
/* TODO: add it when it is ready
grid_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(grid_verilog_subckt_file_path_head, verilog_fname.c_str());
*/
}
/*****************************************************************************

View File

@ -71,10 +71,6 @@ void print_verilog_submodule_luts(ModuleManager& module_manager,
fp.close();
/* Add fname to the linked list */
/* Add it when the Verilog generation is refactored
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str());
*/
return;
}

View File

@ -187,8 +187,7 @@ void print_verilog_submodule_memories(ModuleManager& module_manager,
/* Close the file stream */
fp.close();
/* Add fname to the linked list
/* Add fname to the linked list */
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str());
*/
}

View File

@ -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;
}

View File

@ -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);

View File

@ -1279,9 +1279,7 @@ void print_verilog_submodule_muxes(ModuleManager& module_manager,
try_update_sram_orgz_info_reserved_blwl(cur_sram_orgz_info,
mux_lib.max_mux_size(), mux_lib.max_mux_size());
/* TODO: Add fname to the linked list when debugging is finished */
/*
/* Add fname to the linked list when debugging is finished */
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str());
*/
}

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,351 @@
/*********************************************************************
* This file includes functions that are used for
* Verilog generation of FPGA routing architecture (global routing)
*********************************************************************/
#include <time.h>
#include "vtr_assert.h"
/* Include FPGA-X2P header files*/
#include "fpga_x2p_naming.h"
#include "fpga_x2p_utils.h"
/* Include FPGA-Verilog header files*/
#include "verilog_global.h"
#include "verilog_utils.h"
#include "verilog_writer_utils.h"
#include "verilog_module_writer.h"
#include "verilog_routing.h"
/********************************************************************
* Print the sub-circuit of a connection Box (Type: [CHANX|CHANY])
* Actually it is very similiar to switch box but
* the difference is connection boxes connect Grid INPUT Pins to channels
* NOTE: direct connection between CLBs should NOT be included inside this
* module! They should be added in the top-level module as their connection
* is not limited to adjacent CLBs!!!
*
* Location of a X- and Y-direction Connection Block in FPGA fabric
* +------------+ +-------------+
* | |------>| |
* | CLB |<------| Y-direction |
* | | ... | Connection |
* | |------>| Block |
* +------------+ +-------------+
* | ^ ... | | ^ ... |
* v | v v | v
* +-------------------+ +-------------+
* --->| |--->| |
* <---| X-direction |<---| Switch |
* ...| Connection block |... | Block |
* --->| |--->| |
* +-------------------+ +-------------+
*
* Internal structure:
* This is an example of a X-direction connection block
* Note that middle output ports are shorted wire from inputs of routing tracks,
* which are also the inputs of routing multiplexer of the connection block
*
* CLB Input Pins
* (IPINs)
* ^ ^ ^
* | | ... |
* +--------------------------+
* | ^ ^ ^ |
* | | | ... | |
* | +--------------------+ |
* | | routing | |
* | | multiplexers | |
* | +--------------------+ |
* | middle outputs |
* | of routing channel |
* | ^ ^ ^ ^ ^ ^ ^ ^ |
* | | | | | ... | | | | |
* in[0] -->|------------------------->|---> out[0]
* out[1] <--|<-------------------------|<--- in[1]
* | ... |
* in[W-2] -->|------------------------->|---> out[W-2]
* out[W-1] <--|<-------------------------|<--- in[W-1]
* +--------------------------+
*
* W: routing channel width
*
********************************************************************/
static
void print_verilog_routing_connection_box_unique_module(ModuleManager& module_manager,
const std::string& verilog_dir,
const std::string& subckt_dir,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const bool& use_explicit_port_map) {
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
std::string verilog_fname(subckt_dir + generate_connection_block_netlist_name(cb_type, gsb_coordinate, std::string(verilog_netlist_file_postfix)));
/* TODO: remove the bak file when the file is ready */
//verilog_fname += ".bak";
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_handler(fp);
print_verilog_file_header(fp, std::string("Verilog modules for Unique Connection Blocks[" + std::to_string(rr_gsb.get_cb_x(cb_type)) + "]["+ std::to_string(rr_gsb.get_cb_y(cb_type)) + "]"));
/* Print preprocessing flags */
print_verilog_include_defines_preproc_file(fp, verilog_dir);
/* Create a Verilog Module based on the circuit model, and add to module manager */
ModuleId cb_module = module_manager.find_module(generate_connection_block_module_name(cb_type, gsb_coordinate));
VTR_ASSERT(true == module_manager.valid_module_id(cb_module));
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, cb_module, use_explicit_port_map);
/* Add an empty line as a splitter */
fp << std::endl;
/* Close file handler */
fp.close();
/* Add fname to the linked list */
routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, verilog_fname.c_str());
}
/*********************************************************************
* Generate the Verilog module for a Switch Box.
* A Switch Box module consists of following ports:
* 1. Channel Y [x][y] inputs
* 2. Channel X [x+1][y] inputs
* 3. Channel Y [x][y-1] outputs
* 4. Channel X [x][y] outputs
* 5. Grid[x][y+1] Right side outputs pins
* 6. Grid[x+1][y+1] Left side output pins
* 7. Grid[x+1][y+1] Bottom side output pins
* 8. Grid[x+1][y] Top side output pins
* 9. Grid[x+1][y] Left side output pins
* 10. Grid[x][y] Right side output pins
* 11. Grid[x][y] Top side output pins
* 12. Grid[x][y+1] Bottom side output pins
*
* Location of a Switch Box in FPGA fabric:
*
* -------------- --------------
* | | | |
* | Grid | ChanY | Grid |
* | [x][y+1] | [x][y+1] | [x+1][y+1] |
* | | | |
* -------------- --------------
* ----------
* ChanX | Switch | ChanX
* [x][y] | Box | [x+1][y]
* | [x][y] |
* ----------
* -------------- --------------
* | | | |
* | Grid | ChanY | Grid |
* | [x][y] | [x][y] | [x+1][y] |
* | | | |
* -------------- --------------
*
* Switch Block pin location map
*
* Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1]
* right_pins inputs/outputs left_pins
* | ^ |
* | | |
* v v v
* +-----------------------------------------------+
* | |
* Grid[x][y+1] | | Grid[x+1][y+1]
* bottom_pins---->| |<---- bottom_pins
* | |
* ChanX[x][y] | Switch Box [x][y] | ChanX[x+1][y]
* inputs/outputs<--->| |<---> inputs/outputs
* | |
* Grid[x][y+1] | | Grid[x+1][y+1]
* top_pins---->| |<---- top_pins
* | |
* +-----------------------------------------------+
* ^ ^ ^
* | | |
* | v |
* Grid[x][y] ChanY[x][y] Grid[x+1][y]
* right_pins inputs/outputs left_pins
*
*
********************************************************************/
static
void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manager,
const std::string& verilog_dir,
const std::string& subckt_dir,
const RRGSB& rr_gsb,
const bool& use_explicit_port_map) {
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
std::string verilog_fname(subckt_dir + generate_routing_block_netlist_name(sb_verilog_file_name_prefix, gsb_coordinate, std::string(verilog_netlist_file_postfix)));
/* TODO: remove the bak file when the file is ready */
//verilog_fname += ".bak";
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_handler(fp);
print_verilog_file_header(fp, std::string("Verilog modules for Unique Switch Blocks[" + std::to_string(rr_gsb.get_sb_x()) + "]["+ std::to_string(rr_gsb.get_sb_y()) + "]"));
/* Print preprocessing flags */
print_verilog_include_defines_preproc_file(fp, verilog_dir);
/* Create a Verilog Module based on the circuit model, and add to module manager */
ModuleId sb_module = module_manager.find_module(generate_switch_block_module_name(gsb_coordinate));
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
/* Write the verilog module */
write_verilog_module_to_file(fp, module_manager, sb_module, use_explicit_port_map);
/* Close file handler */
fp.close();
/* Add fname to the linked list */
routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, verilog_fname.c_str());
return;
}
/********************************************************************
* Iterate over all the connection blocks in a device
* and build a module for each of them
*******************************************************************/
static
void print_verilog_flatten_connection_block_modules(ModuleManager& module_manager,
const DeviceRRGSB& L_device_rr_gsb,
const std::string& verilog_dir,
const std::string& subckt_dir,
const t_rr_type& cb_type,
const bool& use_explicit_port_map) {
/* Build unique X-direction connection block modules */
DeviceCoordinator cb_range = L_device_rr_gsb.get_gsb_range();
for (size_t ix = 0; ix < cb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < cb_range.get_y(); ++iy) {
/* Check if the connection block exists in the device!
* Some of them do NOT exist due to heterogeneous blocks (height > 1)
* We will skip those modules
*/
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
if ( (TRUE != is_cb_exist(cb_type, rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type)))
|| (true != rr_gsb.is_cb_exist(cb_type))) {
continue;
}
print_verilog_routing_connection_box_unique_module(module_manager,
verilog_dir,
subckt_dir,
rr_gsb, cb_type,
use_explicit_port_map);
}
}
}
/********************************************************************
* A top-level function of this file
* Print all the modules for global routing architecture of a FPGA fabric
* in Verilog format in a flatten way:
* Each connection block and switch block will be generated as a unique module
* Covering:
* 1. Connection blocks
* 2. Switch blocks
*******************************************************************/
void print_verilog_flatten_routing_modules(ModuleManager& module_manager,
const DeviceRRGSB& L_device_rr_gsb,
const t_det_routing_arch& routing_arch,
const std::string& verilog_dir,
const std::string& subckt_dir,
const bool& use_explicit_port_map) {
/* We only support uni-directional routing architecture now */
VTR_ASSERT (UNI_DIRECTIONAL == routing_arch.directionality);
/* TODO: deprecate DeviceCoordinator, use vtr::Point<size_t> only! */
DeviceCoordinator sb_range = L_device_rr_gsb.get_gsb_range();
/* Build unique switch block modules */
for (size_t ix = 0; ix < sb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < sb_range.get_y(); ++iy) {
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
print_verilog_routing_switch_box_unique_module(module_manager,
verilog_dir,
subckt_dir,
rr_gsb,
use_explicit_port_map);
}
}
print_verilog_flatten_connection_block_modules(module_manager, L_device_rr_gsb, verilog_dir, subckt_dir, CHANX, use_explicit_port_map);
print_verilog_flatten_connection_block_modules(module_manager, L_device_rr_gsb, verilog_dir, subckt_dir, CHANY, use_explicit_port_map);
vpr_printf(TIO_MESSAGE_INFO,"Generating header file for routing submodules...\n");
dump_verilog_subckt_header_file(routing_verilog_subckt_file_path_head,
subckt_dir.c_str(),
routing_verilog_file_name);
}
/********************************************************************
* A top-level function of this file
* Print all the unique modules for global routing architecture of a FPGA fabric
* in Verilog format, including:
* 1. Connection blocks
* 2. Switch blocks
*
* Note: this function SHOULD be called only when
* the option compact_routing_hierarchy is turned on!!!
*******************************************************************/
void print_verilog_unique_routing_modules(ModuleManager& module_manager,
const DeviceRRGSB& L_device_rr_gsb,
const t_det_routing_arch& routing_arch,
const std::string& verilog_dir,
const std::string& subckt_dir,
const bool& use_explicit_port_map) {
/* We only support uni-directional routing architecture now */
VTR_ASSERT (UNI_DIRECTIONAL == routing_arch.directionality);
/* Build unique switch block modules */
for (size_t isb = 0; isb < L_device_rr_gsb.get_num_sb_unique_module(); ++isb) {
const RRGSB& unique_mirror = L_device_rr_gsb.get_sb_unique_module(isb);
print_verilog_routing_switch_box_unique_module(module_manager,
verilog_dir,
subckt_dir,
unique_mirror,
use_explicit_port_map);
}
/* Build unique X-direction connection block modules */
for (size_t icb = 0; icb < L_device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) {
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(CHANX, icb);
print_verilog_routing_connection_box_unique_module(module_manager,
verilog_dir,
subckt_dir,
unique_mirror, CHANX,
use_explicit_port_map);
}
/* Build unique X-direction connection block modules */
for (size_t icb = 0; icb < L_device_rr_gsb.get_num_cb_unique_module(CHANY); ++icb) {
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(CHANY, icb);
print_verilog_routing_connection_box_unique_module(module_manager,
verilog_dir,
subckt_dir,
unique_mirror, CHANY,
use_explicit_port_map);
}
vpr_printf(TIO_MESSAGE_INFO,"Generating header file for routing submodules...\n");
dump_verilog_subckt_header_file(routing_verilog_subckt_file_path_head,
subckt_dir.c_str(),
routing_verilog_file_name);
}

View File

@ -9,150 +9,6 @@
#include "module_manager.h"
#include "rr_blocks.h"
void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* subckt_dir,
int x, int y,
t_rr_type chan_type,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_rr_indexed_data* LL_rr_indexed_data,
int num_segment, t_segment_inf* segments,
t_syn_verilog_opts fpga_verilog_opts);
void dump_verilog_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
int pin_index, int side,
int x, int y,
int unique_x, int unique_y, /* If explicit, needs the coordinates of the mirror*/
boolean dump_port_type,
bool is_explicit_mapping);
void dump_verilog_grid_side_pins(FILE* fp,
t_rr_type pin_type, int x, int y, int side,
boolean dump_port_type);
void dump_verilog_switch_box_chan_port(FILE* fp,
t_sb* cur_sb_info,
int chan_side,
t_rr_node* cur_rr_node,
enum PORTS cur_rr_node_direction);
void dump_verilog_switch_box_short_interc(FILE* fp,
t_sb* cur_sb_info,
int chan_side,
t_rr_node* cur_rr_node,
int actual_fan_in,
t_rr_node* drive_rr_node,
bool is_explicit_mapping);
void dump_verilog_switch_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
t_sb* cur_sb_info,
int chan_side,
t_rr_node* cur_rr_node,
int mux_size,
t_rr_node** drive_rr_nodes,
int switch_index,
bool is_explicit_mapping);
int count_verilog_switch_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb cur_sb_info, int chan_side,
t_rr_node* cur_rr_node);
int count_verilog_switch_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb cur_sb_info, int chan_side,
t_rr_node* cur_rr_node);
void dump_verilog_switch_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
t_sb* cur_sb_info,
int chan_side,
t_rr_node* cur_rr_node,
bool is_explicit_mapping);
int count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb cur_sb_info);
int count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_sb cur_sb_info);
void dump_verilog_routing_switch_box_subckt(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir, char* subckt_dir,
t_sb* cur_sb_info,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_syn_verilog_opts fpga_verilog_opts,
boolean compact_routing_hierarchy,
bool is_explicit_mapping);
void dump_verilog_connection_box_short_interc(FILE* fp,
t_cb* cur_cb_info,
t_rr_node* src_rr_node,
bool is_explicit_mapping);
void dump_verilog_connection_box_mux(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
t_cb* cur_cb_info,
t_rr_node* src_rr_node,
bool is_explicit_mapping);
void dump_verilog_connection_box_interc(t_sram_orgz_info* cur_sram_orgz_info,
FILE* fp,
t_cb* cur_cb_info,
t_rr_node* src_rr_node,
bool is_explicit_mapping);
int count_verilog_connection_box_interc_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_rr_node* cur_rr_node);
int count_verilog_connection_box_one_side_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
const RRGSB& rr_gsb, enum e_side cb_side);
int count_verilog_connection_box_interc_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_rr_node* cur_rr_node);
int count_verilog_connection_box_one_side_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
const RRGSB& rr_gsb, enum e_side cb_side);
int count_verilog_connection_box_one_side_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
int num_ipin_rr_nodes,
t_rr_node** ipin_rr_node);
int count_verilog_connection_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
const RRGSB& rr_gsb, t_rr_type cb_type);
int count_verilog_connection_box_one_side_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
int num_ipin_rr_nodes,
t_rr_node** ipin_rr_node);
int count_verilog_connection_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
const RRGSB& rr_gsb, t_rr_type cb_type);
int count_verilog_connection_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_cb* cur_cb_info);
int count_verilog_connection_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info,
t_cb* cur_cb_info);
void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir, char* subckt_dir,
t_cb* cur_cb_info,
boolean compact_routing_hierarchy,
bool is_explicit_mapping);
void print_verilog_routing_resources(ModuleManager& module_manager,
t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* subckt_dir,
const t_arch& arch,
const t_det_routing_arch& routing_arch,
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
t_ivec*** LL_rr_node_indices,
t_rr_indexed_data* LL_rr_indexed_data,
const t_fpga_spice_opts& FPGA_SPICE_Opts);
void print_verilog_flatten_routing_modules(ModuleManager& module_manager,
const DeviceRRGSB& L_device_rr_gsb,
const t_det_routing_arch& routing_arch,

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -14,6 +14,7 @@
/* FPGA-X2P context header files */
#include "fpga_x2p_utils.h"
#include "module_manager_utils.h"
/* FPGA-Verilog context header files */
#include "verilog_global.h"
@ -119,3 +120,117 @@ void print_verilog_submodule_signal_init(std::fstream& fp,
fp << "`endif" << std::endl;
}
/*********************************************************************
* Register all the user-defined modules in the module manager
* Walk through the circuit library and add user-defined circuit models
* to the module_manager
********************************************************************/
void add_user_defined_verilog_modules(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib) {
/* Iterate over Verilog modules */
for (const auto& model : circuit_lib.models()) {
/* We only care about user-defined models */
if (true == circuit_lib.model_verilog_netlist(model).empty()) {
continue;
}
/* Skip Routing channel wire models because they need a different name. Do it later */
if (SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) {
continue;
}
/* Reach here, the model requires a user-defined Verilog netlist,
* Try to find it in the module manager
* If not found, register it in the module_manager
*/
ModuleId module_id = module_manager.find_module(circuit_lib.model_name(model));
if (ModuleId::INVALID() == module_id) {
add_circuit_model_to_module_manager(module_manager, circuit_lib, model);
}
}
}
/*********************************************************************
* Print a template for a user-defined circuit model
* The template will include just the port declaration of the Verilog module
* The template aims to help user to write Verilog codes with a guaranteed
* module definition, which can be correctly instanciated (with correct
* port mapping) in the FPGA fabric
********************************************************************/
static
void print_one_verilog_template_module(const ModuleManager& module_manager,
std::fstream& fp,
const std::string& module_name) {
/* Ensure a valid file handler*/
check_file_handler(fp);
print_verilog_comment(fp, std::string("----- Template Verilog module for " + module_name + " -----"));
/* Find the module in module manager, which should be already registered */
/* TODO: routing channel wire model may have a different name! */
ModuleId template_module = module_manager.find_module(module_name);
VTR_ASSERT(ModuleId::INVALID() != template_module);
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, template_module);
/* Finish dumping ports */
print_verilog_comment(fp, std::string("----- Internal logic should start here -----"));
/* Add some empty lines as placeholders for the internal logic*/
fp << std::endl << std::endl;
print_verilog_comment(fp, std::string("----- Internal logic should end here -----"));
/* Put an end to the Verilog module */
print_verilog_module_end(fp, module_name);
/* Add an empty line as a splitter */
fp << std::endl;
}
/*********************************************************************
* Print a template of all the submodules that are user-defined
* The template will include just the port declaration of the submodule
* The template aims to help user to write Verilog codes with a guaranteed
* module definition, which can be correctly instanciated (with correct
* port mapping) in the FPGA fabric
********************************************************************/
void print_verilog_submodule_templates(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::string& verilog_dir,
const std::string& submodule_dir) {
std::string verilog_fname(submodule_dir + user_defined_template_verilog_file_name);
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_handler(fp);
/* Print out debugging information for if the file is not opened/created properly */
vpr_printf(TIO_MESSAGE_INFO,
"Creating template for user-defined Verilog modules (%s)...\n",
verilog_fname.c_str());
print_verilog_file_header(fp, "Template for user-defined Verilog modules");
print_verilog_include_defines_preproc_file(fp, verilog_dir);
/* Output essential models*/
for (const auto& model : circuit_lib.models()) {
/* Focus on user-defined modules, which must have a Verilog netlist defined */
if (circuit_lib.model_verilog_netlist(model).empty()) {
continue;
}
/* Skip Routing channel wire models because they need a different name. Do it later */
if (SPICE_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) {
continue;
}
/* Print a Verilog template for the circuit model */
print_one_verilog_template_module(module_manager, fp, circuit_lib.model_name(model));
}
/* close file stream */
fp.close();
/* No need to add the template to the subckt include files! */
}

View File

@ -9,6 +9,9 @@
#define VERILOG_SUBMODULE_UTILS_H
#include <fstream>
#include <string>
#include "module_manager.h"
#include "circuit_library.h"
void print_verilog_submodule_timing(std::fstream& fp,
const CircuitLibrary& circuit_lib,
@ -18,4 +21,12 @@ void print_verilog_submodule_signal_init(std::fstream& fp,
const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
void add_user_defined_verilog_modules(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib);
void print_verilog_submodule_templates(const ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const std::string& verilog_dir,
const std::string& submodule_dir);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
/*********************************************************************
* This file includes top-level function to generate Verilog primitive modules
* and print them to files
********************************************************************/
/* Standard header files */
/* External library header files */
#include "util.h"
/* FPGA-Verilog header files */
#include "verilog_global.h"
#include "verilog_utils.h"
#include "verilog_submodule_utils.h"
#include "verilog_essential_gates.h"
#include "verilog_decoders.h"
#include "verilog_mux.h"
#include "verilog_lut.h"
#include "verilog_wire.h"
#include "verilog_memory.h"
/* Header file for this source file */
#include "verilog_submodules.h"
/*********************************************************************
* Top-level function to generate primitive modules:
* 1. Logic gates: AND/OR, inverter, buffer and transmission-gate/pass-transistor
* 2. Routing multiplexers
* 3. Local encoders for routing multiplexers
* 4. Wires
* 5. Configuration memory blocks
* 6. Verilog template
********************************************************************/
void print_verilog_submodules(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
t_sram_orgz_info* cur_sram_orgz_info,
const char* verilog_dir,
const char* submodule_dir,
const t_arch& Arch,
const t_syn_verilog_opts& fpga_verilog_opts) {
/* Register all the user-defined modules in the module manager
* This should be done prior to other steps in this function,
* because they will be instanciated by other primitive modules
*/
vpr_printf(TIO_MESSAGE_INFO,
"Registering user-defined modules...\n");
add_user_defined_verilog_modules(module_manager, Arch.spice->circuit_lib);
print_verilog_submodule_essentials(module_manager,
std::string(verilog_dir),
std::string(submodule_dir),
Arch.spice->circuit_lib);
/* Routing multiplexers */
vpr_printf(TIO_MESSAGE_INFO,
"Generating modules for routing multiplexers...\n");
/* NOTE: local decoders generation must go before the MUX generation!!!
* because local decoders modules will be instanciated in the MUX modules
*/
print_verilog_submodule_mux_local_decoders(module_manager, mux_lib, Arch.spice->circuit_lib,
std::string(verilog_dir), std::string(submodule_dir));
print_verilog_submodule_muxes(module_manager, mux_lib, Arch.spice->circuit_lib, cur_sram_orgz_info,
std::string(verilog_dir), std::string(submodule_dir),
fpga_verilog_opts.dump_explicit_verilog);
/* LUTes */
vpr_printf(TIO_MESSAGE_INFO,
"Generating modules for LUTs...\n");
print_verilog_submodule_luts(module_manager, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir),
fpga_verilog_opts.dump_explicit_verilog);
/* Hard wires */
print_verilog_submodule_wires(module_manager, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir));
/* 4. Memories */
vpr_printf(TIO_MESSAGE_INFO,
"Generating modules for configuration memory blocks...\n");
print_verilog_submodule_memories(module_manager, mux_lib, Arch.spice->circuit_lib,
std::string(verilog_dir), std::string(submodule_dir),
fpga_verilog_opts.dump_explicit_verilog);
/* 5. Dump template for all the modules */
if (TRUE == fpga_verilog_opts.print_user_defined_template) {
print_verilog_submodule_templates(module_manager, Arch.spice->circuit_lib, std::string(verilog_dir), std::string(submodule_dir));
}
/* Create a header file to include all the subckts */
vpr_printf(TIO_MESSAGE_INFO,
"Generating header file for basic submodules...\n");
dump_verilog_subckt_header_file(submodule_verilog_subckt_file_path_head,
submodule_dir,
submodule_verilog_file_name);
}

View File

@ -1,15 +1,16 @@
#ifndef VERILOG_SUBMODULES_H
#define VERILOG_SUBMODULES_H
#include "vpr_types.h"
#include "module_manager.h"
#include "mux_library.h"
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);
void print_verilog_submodules(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
t_sram_orgz_info* cur_sram_orgz_info,
const char* verilog_dir,
const char* submodule_dir,
const t_arch& Arch,
const t_syn_verilog_opts& fpga_verilog_opts);
#endif

View File

@ -1,859 +0,0 @@
/***********************************/
/* SPICE Modeling for VPR */
/* Xifan TANG, EPFL/LSI */
/***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
/* Include vpr structs*/
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph_util.h"
#include "rr_graph.h"
#include "rr_graph2.h"
#include "route_common.h"
#include "vpr_utils.h"
#include "rr_graph_builder_utils.h"
/* Include SPICE support headers*/
#include "linkedlist.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_backannotate_utils.h"
#include "fpga_x2p_mux_utils.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "fpga_x2p_bitstream_utils.h"
#include "fpga_x2p_rr_graph_utils.h"
#include "fpga_x2p_globals.h"
/* Include Verilog support headers*/
#include "verilog_global.h"
#include "verilog_utils.h"
#include "verilog_routing.h"
#include "verilog_tcl_utils.h"
/***** Subroutine Functions *****/
void dump_verilog_sdc_file_header(FILE* fp,
char* usage) {
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s, LINE[%d]) FileHandle is NULL!\n",__FILE__,__LINE__);
exit(1);
}
fprintf(fp,"#############################################\n");
fprintf(fp,"# Synopsys Design Constraints (SDC) # \n");
fprintf(fp,"# FPGA Synthesizable Verilog Netlist # \n");
fprintf(fp,"# Description: %s \n",usage);
fprintf(fp,"# Author: Xifan TANG # \n");
fprintf(fp,"# Organization: EPFL/IC/LSI # \n");
fprintf(fp,"# Date: %s \n", my_gettime());
fprintf(fp,"#############################################\n");
fprintf(fp,"\n");
return;
}
void dump_verilog_one_sb_chan_pin(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* cur_rr_node,
enum PORTS port_type) {
int track_idx;
enum e_side side;
char* pin_name;
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
/* Check */
assert ((CHANX == cur_rr_node->type)
||(CHANY == cur_rr_node->type));
/* Get the coordinate of chanx or chany*/
/* Find the coordinate of the cur_rr_node */
rr_sb.get_node_side_and_index(cur_rr_node, port_type, &side, &track_idx);
/* FIXME: we should avoid using global variables !!!! */
/* If we have an mirror SB, we should the module name of the mirror !!! */
DeviceCoordinator coordinator = rr_sb.get_sb_coordinator();
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(coordinator);
DeviceCoordinator chan_coordinator = unique_mirror.get_side_block_coordinator(side);
/* Print the pin of the cur_rr_node */
pin_name = gen_verilog_routing_channel_one_pin_name(cur_rr_node,
chan_coordinator.get_x(),
chan_coordinator.get_y(),
track_idx,
port_type);
fprintf(fp, "%s", pin_name);
my_free(pin_name);
return;
}
void dump_verilog_one_sb_chan_pin(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* cur_rr_node,
enum PORTS port_type) {
int track_idx, side;
int x_start, y_start;
char* pin_name;
t_rr_type chan_rr_type;
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
/* Check */
assert ((CHANX == cur_rr_node->type)
||(CHANY == cur_rr_node->type));
/* Get the coordinate of chanx or chany*/
/* Find the coordinate of the cur_rr_node */
get_rr_node_side_and_index_in_sb_info(cur_rr_node,
*cur_sb_info,
port_type, &side, &track_idx);
get_chan_rr_node_coordinate_in_sb_info(*cur_sb_info, side,
&(chan_rr_type),
&x_start, &y_start);
assert (chan_rr_type == cur_rr_node->type);
/* Print the pin of the cur_rr_node */
pin_name = gen_verilog_routing_channel_one_pin_name(cur_rr_node,
x_start, y_start, track_idx,
port_type);
fprintf(fp, "%s", pin_name);
free(pin_name);
return;
}
/* Output the pin name of a routing wire in a SB */
void dump_verilog_one_sb_routing_pin(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* cur_rr_node,
bool is_explicit_mapping) {
int side;
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
/* Get the top-level pin name and print it out */
/* Depends on the type of node */
switch (cur_rr_node->type) {
case OPIN: {
/* Identify the side of OPIN on a grid */
side = get_grid_pin_side(cur_rr_node->xlow, cur_rr_node->ylow, cur_rr_node->ptc_num);
assert (OPEN != side);
/* FIXME: we should avoid using global variables !!!! */
/* If we have an mirror SB, we should the module name of the mirror !!! */
DeviceCoordinator coordinator = rr_sb.get_sb_coordinator();
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(coordinator);
enum e_side pin_gsb_side = NUM_SIDES;
int pin_node_id = -1;
/* We get the index and side for the cur_rr_node in the mother rr_sb context */
rr_sb.get_node_side_and_index(cur_rr_node, IN_PORT, &pin_gsb_side, &pin_node_id);
/* Make sure we have valid numbers */
assert ( (NUM_SIDES != pin_gsb_side) && (-1 != pin_node_id) );
/* We get rr_node with the same index and side in the unique mirror context */
t_rr_node* mirror_node = unique_mirror.get_opin_node(pin_gsb_side, pin_node_id);
/* Identify the side of OPIN on a grid */
side = get_grid_pin_side(mirror_node->xlow, mirror_node->ylow, mirror_node->ptc_num);
assert (OPEN != side);
dump_verilog_grid_side_pin_with_given_index(fp, OPIN,
mirror_node->ptc_num,
side,
mirror_node->xlow,
mirror_node->ylow,
0, /*Used in newer version*/
0, /*Used in newer version*/
FALSE,is_explicit_mapping); /* Do not specify direction of port */
break;
}
case CHANX:
case CHANY:
dump_verilog_one_sb_chan_pin(fp, rr_sb, cur_rr_node, IN_PORT);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of ending point rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
return;
}
/* Output the pin name of a routing wire in a SB */
void dump_verilog_one_sb_routing_pin(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* cur_rr_node,
bool is_explicit_mapping) {
int side;
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
/* Get the top-level pin name and print it out */
/* Depends on the type of node */
switch (cur_rr_node->type) {
case OPIN:
/* Identify the side of OPIN on a grid */
side = get_grid_pin_side(cur_rr_node->xlow, cur_rr_node->ylow, cur_rr_node->ptc_num);
assert (OPEN != side);
dump_verilog_grid_side_pin_with_given_index(fp, OPIN,
cur_rr_node->ptc_num,
side,
cur_rr_node->xlow,
cur_rr_node->ylow,
0, /*Used in newer version*/
0, /*Used in newer version*/
FALSE, is_explicit_mapping); /* Do not specify direction of port */
break;
case CHANX:
case CHANY:
dump_verilog_one_sb_chan_pin(fp, cur_sb_info, cur_rr_node, IN_PORT);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of ending point rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
return;
}
/** Given a starting rr_node (CHANX or CHANY)
* and a ending rr_node (IPIN)
* return the cb contains both (the ending CB of the routing wire)
*/
DeviceCoordinator get_chan_node_ending_cb(t_rr_node* src_rr_node,
t_rr_node* end_rr_node) {
int next_cb_x, next_cb_y;
std::vector<enum e_side> ipin_side;
enum e_side chan_side;
t_rr_type cb_type;
/* Type of connection block depends on the src_rr_node */
switch (src_rr_node->type) {
case CHANX:
/* the x of CB is same as end_rr_node,
* the y of CB should be same as src_rr_node
*/
assert (end_rr_node->xlow == end_rr_node->xhigh);
next_cb_x = end_rr_node->xlow;
assert (src_rr_node->ylow == src_rr_node->yhigh);
next_cb_y = src_rr_node->ylow;
cb_type = CHANX;
break;
case CHANY:
/* the x of CB is same as src_rr_node,
* the y of CB should be same as end_rr_node
*/
assert (src_rr_node->xlow == src_rr_node->xhigh);
next_cb_x = src_rr_node->xlow;
assert (end_rr_node->ylow == end_rr_node->yhigh);
next_cb_y = end_rr_node->ylow;
cb_type = CHANY;
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid type of src_rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
DeviceCoordinator next_cb_coordinator(next_cb_x, next_cb_y);
/* IMPORTANT: the use of global variables should be removed!!! */
const RRGSB& next_cb = device_rr_gsb.get_gsb(next_cb_coordinator);
/* Side will be either on TOP or BOTTOM */
ipin_side = next_cb.get_cb_ipin_sides(cb_type);
chan_side = next_cb.get_cb_chan_side(cb_type);
/* Double check if src_rr_node is in the IN_PORT list */
assert ( (OPEN != next_cb.get_node_index( src_rr_node, chan_side, IN_PORT))
|| (OPEN != next_cb.get_node_index( src_rr_node, chan_side, OUT_PORT)) );
/* Double check if end_rr_node is in the OUT_PORT list */
bool node_exist = false;
for (size_t iside = 0; iside < ipin_side.size(); ++iside) {
if (OPEN != next_cb.get_node_index(end_rr_node, ipin_side[iside], OUT_PORT)) {
node_exist = true;
break;
}
}
assert (true == node_exist);
return next_cb_coordinator;
}
/** Given a starting rr_node (CHANX or CHANY)
* and a ending rr_node (IPIN)
* return the cb contains both (the ending CB of the routing wire)
*/
t_cb* get_chan_rr_node_ending_cb(t_rr_node* src_rr_node,
t_rr_node* end_rr_node) {
int num_ipin_sides = 2;
int* ipin_side = (int*)my_calloc(num_ipin_sides, sizeof(int));
int num_chan_sides = 2;
int* chan_side = (int*)my_calloc(num_chan_sides, sizeof(int));
int iside, next_cb_x, next_cb_y;
int node_exist;
t_cb* next_cb = NULL;
/* Type of connection block depends on the src_rr_node */
switch (src_rr_node->type) {
case CHANX:
/* the x of CB is same as end_rr_node,
* the y of CB should be same as src_rr_node
*/
assert (end_rr_node->xlow == end_rr_node->xhigh);
next_cb_x = end_rr_node->xlow;
assert (src_rr_node->ylow == src_rr_node->yhigh);
next_cb_y = src_rr_node->ylow;
/* Side will be either on TOP or BOTTOM */
ipin_side[0] = TOP;
ipin_side[1] = BOTTOM;
chan_side[0] = RIGHT;
chan_side[1] = LEFT;
next_cb = &(cbx_info[next_cb_x][next_cb_y]);
break;
case CHANY:
/* the x of CB is same as src_rr_node,
* the y of CB should be same as end_rr_node
*/
assert (src_rr_node->xlow == src_rr_node->xhigh);
next_cb_x = src_rr_node->xlow;
/* Heterogeneous blocks may have ylow != yhigh */
if (IPIN != end_rr_node->type) {
assert (end_rr_node->ylow == end_rr_node->yhigh);
}
next_cb_y = end_rr_node->yhigh;
/* Side will be either on RIGHT or LEFT */
ipin_side[0] = LEFT;
ipin_side[1] = RIGHT;
chan_side[0] = BOTTOM;
chan_side[1] = TOP;
next_cb = &(cby_info[next_cb_x][next_cb_y]);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid type of src_rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
/* Double check if src_rr_node is in the IN_PORT list */
/* TODO: this part should be refactored!
node_exist = 0;
for (iside = 0; iside < num_chan_sides; iside++) {
if (OPEN != get_rr_node_index_in_cb_info( src_rr_node,
*next_cb,
chan_side[iside], IN_PORT)) {
node_exist++;
}
}
assert (0 < node_exist);
*/
/* Double check if end_rr_node is in the OUT_PORT list */
/* TODO: this part should be refactored!
node_exist = 0;
for (iside = 0; iside < num_ipin_sides; iside++) {
if (OPEN != get_rr_node_index_in_cb_info( end_rr_node,
*next_cb,
ipin_side[iside], OUT_PORT)) {
node_exist++;
}
}
assert (0 < node_exist);
*/
return next_cb;
}
/** Given a starting rr_node (CHANX or CHANY)
* return the sb contains both (the ending CB of the routing wire)
*/
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node) {
/* Get the coordinator where the node ends */
DeviceCoordinator end_coordinator = get_track_rr_node_end_coordinator(src_rr_node);
/* Initilizae the SB coordinator where the node ends */
DeviceCoordinator sb_coordinator;
/* Case 1:
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* src_rr_node ------>| next_sb |-------> end_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
if ( (CHANX == src_rr_node->type)
&& (INC_DIRECTION == src_rr_node->direction) ) {
/* SB coordinator is the same as src rr_node */
sb_coordinator.set(end_coordinator.get_x(), end_coordinator.get_y());
}
/* Case 2
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* end_rr_node <------| next_sb |<-------- src_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
if ( (CHANX == src_rr_node->type)
&& (DEC_DIRECTION == src_rr_node->direction) ) {
/* SB coordinator is the [x-1][y] */
sb_coordinator.set(end_coordinator.get_x() - 1, end_coordinator.get_y());
}
/* Case 3
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* end_rr_node <------| next_sb |-------> src_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* /|\
* |
* src_rr_node(chany[x][y])
*/
if ( (CHANY == src_rr_node->type)
&& (INC_DIRECTION == src_rr_node->direction) ) {
/* SB coordinator is the same */
sb_coordinator.set(end_coordinator.get_x(), end_coordinator.get_y());
}
/* Case 4
* src_rr_node(chany[x][y+1])
* |
* \|/
* ---------
* | |
* end_rr_node <------| next_sb |--------> end_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
if ( (CHANY == src_rr_node->type)
&& (DEC_DIRECTION == src_rr_node->direction) ) {
/* SB coordinator is the [x][y-1] */
sb_coordinator.set(end_coordinator.get_x(), end_coordinator.get_y() - 1);
}
const RRGSB& rr_sb = device_rr_gsb.get_gsb(sb_coordinator);
/* Double check if src_rr_node is in the list */
enum e_side side;
int index;
rr_sb.get_node_side_and_index(src_rr_node, IN_PORT, &side, &index);
assert ( (OPEN != index) && (side != NUM_SIDES) );
/* Passing the check, assign coordinator of next_sb */
return sb_coordinator;
}
/** Given a starting rr_node (CHANX or CHANY)
* and a ending rr_node (IPIN)
* return the sb contains both (the ending CB of the routing wire)
*/
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node,
t_rr_node* end_rr_node) {
int x_start, y_start;
int x_end, y_end;
int next_sb_x, next_sb_y;
get_chan_rr_node_start_coordinate(src_rr_node, &x_start, &y_start);
get_chan_rr_node_start_coordinate(end_rr_node, &x_end, &y_end);
/* Case 1:
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* src_rr_node ------>| next_sb |-------> end_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
/* Case 2
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* end_rr_node <------| next_sb |<-------- src_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
/* Case 3
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* end_rr_node <------| next_sb |-------> src_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* /|\
* |
* src_rr_node(chany[x][y])
*/
/* Case 4
* src_rr_node(chany[x][y+1])
* |
* \|/
* ---------
* | |
* end_rr_node <------| next_sb |--------> end_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
/* Try the xlow, ylow of ending rr_node */
switch (src_rr_node->type) {
case CHANX:
next_sb_x = x_end;
next_sb_y = y_start;
break;
case CHANY:
next_sb_x = x_start;
next_sb_y = y_end;
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
switch (src_rr_node->direction) {
case INC_DIRECTION:
get_chan_rr_node_end_coordinate(src_rr_node, &x_end, &y_end);
if (next_sb_x > x_end) {
next_sb_x = x_end;
}
if (next_sb_y > y_end) {
next_sb_y = y_end;
}
break;
case DEC_DIRECTION:
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
DeviceCoordinator sb_coordinator(next_sb_x, next_sb_y);
const RRGSB& rr_sb = device_rr_gsb.get_gsb(sb_coordinator);
/* Double check if src_rr_node is in the list */
enum e_side side;
int index;
rr_sb.get_node_side_and_index(src_rr_node, IN_PORT, &side, &index);
assert ( (OPEN != index) && (side != NUM_SIDES) );
/* Double check if end_rr_node is in the list */
rr_sb.get_node_side_and_index(end_rr_node, OUT_PORT, &side, &index);
assert ( (OPEN != index) && (side != NUM_SIDES) );
/* Passing the check, assign coordinator of next_sb */
return sb_coordinator;
}
/** Given a starting rr_node (CHANX or CHANY)
* and a ending rr_node (IPIN)
* return the sb contains both (the ending CB of the routing wire)
*/
t_sb* get_chan_rr_node_ending_sb(t_rr_node* src_rr_node,
t_rr_node* end_rr_node) {
int side;
int x_start, y_start;
int x_end, y_end;
int next_sb_x, next_sb_y;
int node_exist;
t_sb* next_sb = NULL;
get_chan_rr_node_start_coordinate(src_rr_node, &x_start, &y_start);
get_chan_rr_node_start_coordinate(end_rr_node, &x_end, &y_end);
/* Case 1:
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* src_rr_node ------>| next_sb |-------> end_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
/* Case 2
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* end_rr_node <------| next_sb |<-------- src_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
/* Case 3
* end_rr_node(chany[x][y+1])
* /|\
* |
* ---------
* | |
* end_rr_node <------| next_sb |-------> src_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* /|\
* |
* src_rr_node(chany[x][y])
*/
/* Case 4
* src_rr_node(chany[x][y+1])
* |
* \|/
* ---------
* | |
* end_rr_node <------| next_sb |--------> end_rr_node
* (chanx[x][y]) | [x][y] | (chanx[x+1][y]
* ---------
* |
* \|/
* end_rr_node(chany[x][y])
*/
/* Try the xlow, ylow of ending rr_node */
switch (src_rr_node->type) {
case CHANX:
next_sb_x = x_end;
next_sb_y = y_start;
break;
case CHANY:
next_sb_x = x_start;
next_sb_y = y_end;
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
switch (src_rr_node->direction) {
case INC_DIRECTION:
get_chan_rr_node_end_coordinate(src_rr_node, &x_end, &y_end);
if (next_sb_x > x_end) {
next_sb_x = x_end;
}
if (next_sb_y > y_end) {
next_sb_y = y_end;
}
break;
case DEC_DIRECTION:
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid type of rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
/* Double check if src_rr_node is in the list */
node_exist = 0;
for (side = 0; side < 4; side++) {
if( OPEN != get_rr_node_index_in_sb_info(src_rr_node,
sb_info[next_sb_x][next_sb_y],
side, IN_PORT)) {
node_exist++;
}
}
assert (1 == node_exist);
/* Double check if end_rr_node is in the list */
node_exist = 0;
for (side = 0; side < 4; side++) {
if (OPEN != get_rr_node_index_in_sb_info(end_rr_node,
sb_info[next_sb_x][next_sb_y],
side, OUT_PORT)) {
node_exist++;
}
}
if (1 != node_exist) {
assert (1 == node_exist);
}
/* Passing the check, assign ending sb */
next_sb = &(sb_info[next_sb_x][next_sb_y]);
return next_sb;
}
/* Restore the disabled timing for the sb wire */
void restore_disable_timing_one_sb_output(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* wire_rr_node) {
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
assert( ( CHANX == wire_rr_node->type )
|| ( CHANY == wire_rr_node->type ));
/* Restore disabled timing for wire_rr_node as an SB output */
fprintf(fp, "reset_disable_timing ");
/* output instance name */
fprintf(fp, "%s/",
rr_sb.gen_sb_verilog_instance_name());
dump_verilog_one_sb_chan_pin(fp, rr_sb, wire_rr_node, OUT_PORT);
fprintf(fp, "\n");
return;
}
/* Restore the disabled timing for the sb wire */
void restore_disable_timing_one_sb_output(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* wire_rr_node) {
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
assert( ( CHANX == wire_rr_node->type )
|| ( CHANY == wire_rr_node->type ));
/* Restore disabled timing for wire_rr_node as an SB output */
fprintf(fp, "reset_disable_timing ");
/* output instance name */
fprintf(fp, "%s/",
gen_verilog_one_sb_instance_name(cur_sb_info));
dump_verilog_one_sb_chan_pin(fp, cur_sb_info, wire_rr_node, OUT_PORT);
fprintf(fp, "\n");
return;
}
/* Restore the disabled timing for the sb wire */
void set_disable_timing_one_sb_output(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* wire_rr_node) {
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
assert( ( CHANX == wire_rr_node->type )
|| ( CHANY == wire_rr_node->type ));
/* Restore disabled timing for wire_rr_node as an SB output */
fprintf(fp, "set_disable_timing ");
/* output instance name */
fprintf(fp, "%s/",
rr_sb.gen_sb_verilog_instance_name());
dump_verilog_one_sb_chan_pin(fp, rr_sb, wire_rr_node, OUT_PORT);
fprintf(fp, "\n");
return;
}
/* Restore the disabled timing for the sb wire */
void set_disable_timing_one_sb_output(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* wire_rr_node) {
/* Check the file handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Invalid file handler for SDC generation",
__FILE__, __LINE__);
exit(1);
}
assert( ( CHANX == wire_rr_node->type )
|| ( CHANY == wire_rr_node->type ));
/* Restore disabled timing for wire_rr_node as an SB output */
fprintf(fp, "set_disable_timing ");
/* output instance name */
fprintf(fp, "%s/",
gen_verilog_one_sb_instance_name(cur_sb_info));
dump_verilog_one_sb_chan_pin(fp, cur_sb_info, wire_rr_node, OUT_PORT);
fprintf(fp, "\n");
return;
}

View File

@ -1,61 +0,0 @@
#ifndef VERILOG_TCL_UTILS_H
#define VERILOG_TCL_UTILS_H
/* Include header files that require by the function declared in the following lines !!!*/
#include "device_coordinator.h"
#include "rr_blocks.h"
void dump_verilog_sdc_file_header(FILE* fp,
char* usage);
void dump_verilog_one_sb_chan_pin(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* cur_rr_node,
enum PORTS port_type);
void dump_verilog_one_sb_chan_pin(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* cur_rr_node,
enum PORTS port_type);
void dump_verilog_one_sb_routing_pin(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* cur_rr_node,
bool is_explicit_mapping);
void dump_verilog_one_sb_routing_pin(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* cur_rr_node,
bool is_explicit_mapping);
DeviceCoordinator get_chan_node_ending_cb(t_rr_node* src_rr_node,
t_rr_node* end_rr_node);
t_cb* get_chan_rr_node_ending_cb(t_rr_node* src_rr_node,
t_rr_node* end_rr_node);
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node);
DeviceCoordinator get_chan_node_ending_sb_coordinator(t_rr_node* src_rr_node,
t_rr_node* end_rr_node);
t_sb* get_chan_rr_node_ending_sb(t_rr_node* src_rr_node,
t_rr_node* end_rr_node);
void restore_disable_timing_one_sb_output(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* wire_rr_node);
void restore_disable_timing_one_sb_output(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* wire_rr_node);
void set_disable_timing_one_sb_output(FILE* fp,
const RRGSB& rr_sb,
t_rr_node* wire_rr_node);
void set_disable_timing_one_sb_output(FILE* fp,
t_sb* cur_sb_info,
t_rr_node* wire_rr_node);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -1,6 +1,8 @@
#ifndef VERILOG_UTILS_H
#define VERILOG_UTILS_H
#include "vpr_types.h"
void init_list_include_verilog_netlists(t_spice* spice);
void init_include_user_defined_verilog_netlists(t_spice spice);

View File

@ -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;
}

View File

@ -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);

View File

@ -128,9 +128,5 @@ void print_verilog_submodule_wires(ModuleManager& module_manager,
fp.close();
/* Add fname to the linked list */
/* Uncomment this when it is ready to be plugged in
*/
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str());
return;
}