diff --git a/.travis/script.sh b/.travis/script.sh
index 10cf00931..fa9e95ea8 100755
--- a/.travis/script.sh
+++ b/.travis/script.sh
@@ -18,5 +18,5 @@ end_section "OpenFPGA.build"
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd -
-python3 openfpga_flow/scripts/run_fpga_task.py blif_vpr_flow --exit_on_fail
+python3 openfpga_flow/scripts/run_fpga_task.py blif_vpr_flow tileable_routing --maxthreads 2
end_section "OpenFPGA.TaskTun"
diff --git a/docs/source/arch_lang/figures/point2point_example.png b/docs/source/arch_lang/figures/point2point_example.png
new file mode 100644
index 000000000..a63df9d38
Binary files /dev/null and b/docs/source/arch_lang/figures/point2point_example.png differ
diff --git a/docs/source/arch_lang/figures/point2point_truthtable.png b/docs/source/arch_lang/figures/point2point_truthtable.png
new file mode 100644
index 000000000..d81bab338
Binary files /dev/null and b/docs/source/arch_lang/figures/point2point_truthtable.png differ
diff --git a/docs/source/arch_lang/index.rst b/docs/source/arch_lang/index.rst
index bafd8f6e2..86edc3886 100644
--- a/docs/source/arch_lang/index.rst
+++ b/docs/source/arch_lang/index.rst
@@ -8,6 +8,8 @@ Extended Architecture Description Language
:maxdepth: 2
generality
+
+ interconnect
spice_sim_setting
diff --git a/docs/source/arch_lang/interconnect.rst b/docs/source/arch_lang/interconnect.rst
new file mode 100644
index 000000000..a6542ccb5
--- /dev/null
+++ b/docs/source/arch_lang/interconnect.rst
@@ -0,0 +1,94 @@
+Interconnection extensions
+==========================
+
+This section introduces extensions on the architecture description file about existing interconnection description.
+
+Directlist
+----------
+
+The original direct connections in the directlist section are documented here_. Its description is given below:
+
+.. _here: http://docs.verilogtorouting.org/en/latest/arch/reference/?highlight=directlist#direct-inter-block-connections
+
+.. code-block:: xml
+
+
+
+
+
+.. note:: These options are required
+
+Our extension include three more options:
+
+.. code-block:: xml
+
+
+
+
+
+.. note:: these options are optional. However, if *interconnection_type* is set *x_dir* and *y_dir* are required.
+
+* **interconnection_type**: [``NONE`` | ``column`` | ``row``], specifies if it applies on a column or a row ot if it doesn't apply.
+
+* **x_dir**: [``positive`` | ``negative``], specifies if the next cell to connect has a bigger or lower x value. Considering a coordinate system where (0,0) is the origin at the bottom left and *x* and *y* are positives:
+
+ * x_dir="positive":
+
+ * interconnection_type="column": a column will be connected to a column on the **right**, if it exists.
+
+ * interconnection_type="row": the most on the **right** cell from a row connection will connect the most on the **left** cell of next row, if it exists.
+
+ * x_dir="negative":
+
+ * interconnection_type="column": a column will be connected to a column on the **left**, if it exists.
+
+ * interconnection_type="row": the most on the **left** cell from a row connection will connect the most on the **right** cell of next row, if it exists.
+
+* **y_dir**: [``positive`` | ``negative``], specifies if the next cell to connect has a bigger or lower x value. Considering a coordinate system where (0,0) is the origin at the bottom left and *x* and *y* are positives:
+
+ * y_dir="positive":
+
+ * interconnection_type="column": the **bottom** cell of a column will be connected to the next column **top** cell, if it exists.
+
+ * interconnection_type="row": a row will be connected on an **above** row, if it exists.
+
+ * y_dir="negative":
+
+ * interconnection_type="column": the **top** cell of a column will be connected to the next column **bottom** cell, if it exists.
+
+ * interconnection_type="row": a row will be connected on a row **below**, if it exists.
+
+Example
+-------
+
+For this example, we will study a scan-chain implementation. The description could be:
+
+.. code-block:: xml
+
+
+
+
+
+:numref:`fig_p2p_exple` is the graphical representation of the above scan-chain description on a 4x4 FPGA.
+
+.. _fig_p2p_exple:
+
+.. figure:: ./figures/point2point_example.png
+
+ An example of scan-chain implementation
+
+
+In this figure, the red arrows represent the initial direct connection. The green arrows represent the point to point connection to connect all the columns of CLB.
+
+Truth table
+-----------
+
+A point to point connection can be applied in different ways than showed in the example section. To help the designer implement his point to point connection, a truth table with our new parameters id provided below.
+
+:numref:`fig_p2p_trtable` provides all possible variable combination and the connection it will generate.
+
+.. _fig_p2p_trtable:
+
+.. figure:: ./figures/point2point_truthtable.png
+
+ Point to point truth table
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
new file mode 100644
index 000000000..fa32d4e41
--- /dev/null
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
@@ -0,0 +1,1042 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 5e-12 5e-12
+
+
+ 10e-12 5e-12 5e-12
+
+
+
+
+
+
+
+
+
+
+ 10e-12 10e-12
+
+
+ 10e-12 10e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+
+
+ 1 1 1 1 1
+ 1 1 1 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 202e-12
+ 202e-12
+ 202e-12
+ 202e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ clb.cin clb.cin_trick clb.regin clb.clk
+ clb.I0[9:0] clb.I1[9:0] clb.O[9:0]
+ clb.cout clb.regout clb.I2[9:0] clb.I3[9:0] clb.O[19:10]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
new file mode 100644
index 000000000..ff9d23ac1
--- /dev/null
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
@@ -0,0 +1,1040 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 5e-12 5e-12
+
+
+ 10e-12 5e-12 5e-12
+
+
+
+
+
+
+
+
+
+
+ 10e-12 10e-12
+
+
+ 10e-12 10e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+
+
+ 1 1 1 1 1
+ 1 1 1 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 202e-12
+ 202e-12
+ 202e-12
+ 202e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ clb.cin clb.cin_trick clb.regin clb.clk
+ clb.I0[9:0] clb.I1[9:0] clb.O[9:0]
+ clb.cout clb.regout clb.I2[9:0] clb.I3[9:0] clb.O[19:10]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
index 57967f2e9..ce1615d0b 100644
--- a/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
+++ b/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
@@ -558,7 +558,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 5e-12 5e-12
+
+
+ 10e-12 5e-12 5e-12
+
+
+
+
+
+
+
+
+
+
+ 10e-12 10e-12
+
+
+ 10e-12 10e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+
+
+ 1 1 1 1 1
+ 1 1 1 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+ 255e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 202e-12
+ 202e-12
+ 202e-12
+ 202e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ clb.cin clb.cin_trick clb.regin clb.clk
+ clb.I0[9:0] clb.I1[9:0] clb.O[9:0]
+ clb.cout clb.regout clb.I2[9:0] clb.I3[9:0] clb.O[19:10]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml b/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml
index 25577a130..4ff2c0800 100644
--- a/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml
+++ b/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml
@@ -202,11 +202,23 @@
+
+ 10e-12
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+ 10e-12
+
@@ -217,10 +229,10 @@
- 10e-12 0e-12 0e-12
+ 10e-12 5e-12 5e-12
- 10e-12 0e-12 0e-12
+ 10e-12 5e-12 5e-12
@@ -230,17 +242,11 @@
-
- 10e-12
+
+ 10e-12 10e-12
-
- 10e-12
-
-
- 10e-12
-
-
- 10e-12
+
+ 10e-12 10e-12
@@ -325,7 +331,7 @@
-
+
@@ -340,7 +346,7 @@
-
+
diff --git a/openfpga_flow/misc/modelsim_template.j2 b/openfpga_flow/misc/modelsim_template.j2
new file mode 100644
index 000000000..cfa43d11c
--- /dev/null
+++ b/openfpga_flow/misc/modelsim_template.j2
@@ -0,0 +1,8 @@
+read_verilog -container r -libname WORK -05 { ${SOURCE_DESIGN} }
+set_top r:${SOURCE_TOP_DIR}
+read_verilog -container i -libname WORK -05 { ${IMPL_DESIGN} }
+
+set_top i:${IMPL_TOP_DIR}
+match
+${MATCH_MODUEL_LIST}
+verify
diff --git a/openfpga_flow/scripts/run_fpga_flow.py b/openfpga_flow/scripts/run_fpga_flow.py
index fcd1d1721..6a203e302 100644
--- a/openfpga_flow/scripts/run_fpga_flow.py
+++ b/openfpga_flow/scripts/run_fpga_flow.py
@@ -659,6 +659,9 @@ def run_standard_vpr(bench_blif, fixed_chan_width, logfile, route_only=False):
if args.vpr_use_tileable_route_chan_width:
command += ["--use_tileable_route_chan_width"]
+ if args.vpr_fpga_x2p_compact_routing_hierarchy:
+ command += ["--fpga_x2p_compact_routing_hierarchy"]
+
# FPGA_Spice Options
if (args.power and args.vpr_fpga_spice):
command += ["--fpga_spice"]
@@ -668,8 +671,6 @@ def run_standard_vpr(bench_blif, fixed_chan_width, logfile, route_only=False):
if args.vpr_fpga_x2p_sim_window_size:
command += ["--fpga_x2p_sim_window_size",
args.vpr_fpga_x2p_sim_window_size]
- if args.vpr_fpga_x2p_compact_routing_hierarchy:
- command += ["--fpga_x2p_compact_routing_hierarchy"]
if args.vpr_fpga_spice_sim_mt_num:
command += ["--fpga_spice_sim_mt_num",
@@ -858,7 +859,9 @@ def run_netlists_verification():
if "Succeed" in output:
logger.info("VVP Simulation Successful")
else:
- logger.info(str(output).split("\n")[-1])
+ logger.error(str(output).split("\n")[-1])
+ if exit_if_fail:
+ clean_up_and_exit("Failed to run VVP verification")
ExecTime["VerificationEnd"] = time.time()
diff --git a/openfpga_flow/scripts/run_fpga_task.py b/openfpga_flow/scripts/run_fpga_task.py
index 06a5358fb..a46c99e79 100644
--- a/openfpga_flow/scripts/run_fpga_task.py
+++ b/openfpga_flow/scripts/run_fpga_task.py
@@ -5,7 +5,7 @@
# Combination of architecture, benchmark and script paramters
# Args : python3 run_fpga_task.py --help
# Author : Ganesh Gore
-#Email : ganeshgore@utah.edu
+# Email : ganeshgore@utah.edu
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
import os
@@ -36,7 +36,7 @@ if sys.version_info[0] < 3:
# Configure logging system
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
logging.basicConfig(level=logging.INFO, stream=sys.stdout,
- format='%(levelname)s (%(threadName)10s) - %(message)s')
+ format='%(levelname)s (%(threadName)15s) - %(message)s')
logger = logging.getLogger('OpenFPGA_Task_logs')
@@ -48,14 +48,19 @@ parser.add_argument('tasks', nargs='+')
parser.add_argument('--maxthreads', type=int, default=2,
help="Number of fpga_flow threads to run default = 2," +
"Typically <= Number of processors on the system")
+parser.add_argument('--remove_run_dir', type=str,
+ help="Remove run dir " +
+ "'all' to remove all." +
+ ", to remove specific run dir" +
+ "- To remove range of directory")
parser.add_argument('--config', help="Override default configuration")
parser.add_argument('--test_run', action="store_true",
help="Dummy run shows final generated VPR commands")
parser.add_argument('--debug', action="store_true",
help="Run script in debug mode")
-parser.add_argument('--exit_on_fail', action="store_true",
+parser.add_argument('--continue_on_fail', action="store_true",
help="Exit script with return code")
-parser.add_argument('--skip_thread_logs', action="store_true",
+parser.add_argument('--show_thread_logs', action="store_true",
help="Skips logs from running thread")
args = parser.parse_args()
@@ -84,6 +89,8 @@ def main():
logger.info("Currently running task %s" % eachtask)
eachtask = eachtask.replace("\\", "/").split("/")
job_run_list = generate_each_task_actions(eachtask)
+ if args.remove_run_dir:
+ continue
eachtask = "_".join(eachtask)
if not args.test_run:
run_actions(job_run_list)
@@ -111,6 +118,40 @@ def validate_command_line_arguments():
logger.info("Set up to run %d Parallel threads", args.maxthreads)
+def remove_run_dir():
+ remove_dir = []
+ try:
+ argval = args.remove_run_dir.lower()
+ if argval == "all":
+ for eachRun in glob.glob("run*"):
+ remove_dir += [eachRun]
+ elif "-" in argval:
+ minval, maxval = map(int, argval.split("-"))
+ if minval > maxval:
+ raise Exception("Enter valid range to remove")
+ for eachRun in glob.glob("run*"):
+ if minval <= int(eachRun[-3:]) <= maxval:
+ remove_dir += [eachRun]
+ elif "," in argval:
+ for eachRun in argval.split(","):
+ remove_dir += ["run%03d" % int(eachRun)]
+ else:
+ logger.error("Unknow argument to --remove_run_dir")
+ except:
+ logger.exception("Failed to parse remove rund_dir options")
+
+ try:
+ for eachdir in remove_dir:
+ logger.info('Removing run_dir %s' % (eachdir))
+ if os.path.exists('latest'):
+ if eachdir == os.readlink('latest'):
+ remove_dir += ["latest"]
+ shutil.rmtree(eachdir, ignore_errors=True)
+ except:
+ logger.exception("Failed to remove %s run directory" %
+ (eachdir or "Unknown"))
+
+
def generate_each_task_actions(taskname):
"""
This script generates all the scripts required for each benchmark
@@ -130,6 +171,9 @@ def generate_each_task_actions(taskname):
# Create run directory for current task run ./runxxx
run_dirs = [int(os.path.basename(x)[-3:]) for x in glob.glob('run*[0-9]')]
curr_run_dir = "run%03d" % (max(run_dirs+[0, ])+1)
+ if args.remove_run_dir:
+ remove_run_dir()
+ return
try:
os.mkdir(curr_run_dir)
if os.path.islink('latest') or os.path.exists('latest'):
@@ -252,10 +296,10 @@ def generate_each_task_actions(taskname):
flow_run_cmd_list.append({
"arch": arch,
"bench": bench,
- "name": "%02d_arch%s_%s" % (indx, bench["top_module"], lbl),
+ "name": "%02d_%s_%s" % (indx, bench["top_module"], lbl),
"run_dir": flow_run_dir,
"commands": command,
- "finished" : False,
+ "finished": False,
"status": False})
logger.info('Found %d Architectures %d Benchmarks & %d Script Parameters' %
@@ -345,14 +389,11 @@ def strip_child_logger_info(line):
def run_single_script(s, eachJob, job_list):
- logger.debug('Added job in pool')
with s:
- logger.debug("Running OpenFPGA flow with " +
- " ".join(eachJob["commands"]))
- name = threading.currentThread().getName()
+ thread_name = threading.currentThread().getName()
eachJob["starttime"] = time.time()
try:
- logfile = "%s_out.log" % name
+ logfile = "%s_out.log" % thread_name
with open(logfile, 'w+') as output:
output.write("* "*20 + '\n')
output.write("RunDirectory : %s\n" % os.getcwd())
@@ -360,46 +401,45 @@ def run_single_script(s, eachJob, job_list):
eachJob["commands"]
output.write(" ".join(command) + '\n')
output.write("* "*20 + '\n')
+ logger.debug("Running OpenFPGA flow with [%s]" % command)
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True)
for line in process.stdout:
- if not args.skip_thread_logs:
+ if args.show_thread_logs:
strip_child_logger_info(line[:-1])
sys.stdout.buffer.flush()
output.write(line)
process.wait()
if process.returncode:
- raise subprocess.CalledProcessError(0, command)
+ raise subprocess.CalledProcessError(0, " ".join(command))
eachJob["status"] = True
except:
logger.exception("Failed to execute openfpga flow - " +
eachJob["name"])
- if args.exit_on_fail:
- clean_up_and_exit("Faile to run task %s exiting" % name)
+ if not args.continue_on_fail:
+ os._exit(1)
eachJob["endtime"] = time.time()
timediff = timedelta(seconds=(eachJob["endtime"]-eachJob["starttime"]))
timestr = humanize.naturaldelta(timediff) if "humanize" in sys.modules \
else str(timediff)
logger.info("%s Finished with returncode %d, Time Taken %s " %
- (name, process.returncode, timestr))
+ (thread_name, process.returncode, timestr))
eachJob["finished"] = True
- no_of_finished_job = sum([ not eachJ["finished"] for eachJ in job_list])
+ no_of_finished_job = sum([not eachJ["finished"] for eachJ in job_list])
logger.info("***** %d runs pending *****" % (no_of_finished_job))
def run_actions(job_list):
thread_sema = threading.Semaphore(args.maxthreads)
- thred_list = []
- for index, eachjob in enumerate(job_list):
- JobID = 'Job_%02d' % (index+1)
- logger.info("Running %s = %s" % (JobID, eachjob["name"]))
- t = threading.Thread(target=run_single_script,
- name=JobID, args=(thread_sema, eachjob, job_list))
+ thread_list = []
+ for _, eachjob in enumerate(job_list):
+ t = threading.Thread(target=run_single_script, name=eachjob["name"],
+ args=(thread_sema, eachjob, job_list))
t.start()
- thred_list.append(t)
- for eachthread in thred_list:
+ thread_list.append(t)
+ for eachthread in thread_list:
eachthread.join()
diff --git a/openfpga_flow/scripts/run_modelsim.py b/openfpga_flow/scripts/run_modelsim.py
new file mode 100644
index 000000000..e8dca5cb4
--- /dev/null
+++ b/openfpga_flow/scripts/run_modelsim.py
@@ -0,0 +1,86 @@
+from string import Template
+import sys
+import os
+import argparse
+import subprocess
+import logging
+from pprint import pprint
+
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# Configure logging system
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+logging.basicConfig(level=logging.INFO, stream=sys.stdout,
+ format='%(levelname)s (%(threadName)10s) - %(message)s')
+logger = logging.getLogger('Modelsim_run_log')
+
+parser = argparse.ArgumentParser()
+parser.add_argument('files', nargs='+')
+parser.add_argument('--modelsim_template', type=str,
+ help="Modelsim verification template file")
+parser.add_argument('--run_sim', action="store_true",
+ help="Execute generated script in formality")
+args = parser.parse_args()
+
+
+if not args.modelsim_template:
+ task_script_dir = os.path.dirname(os.path.abspath(__file__))
+ args.modelsim_template = os.path.join(task_script_dir, os.pardir,
+ "misc", "modelsim_template.j2")
+
+args.modelsim_template = os.path.abspath(args.modelsim_template)
+
+
+def main():
+ for eachFile in args.files:
+ eachFile = os.path.abspath(eachFile)
+ directory = os.path.dirname(eachFile)
+ os.chdir(directory)
+ with open(eachFile, 'r') as fp:
+ lines = fp.read().split("\n")
+ SplitL = [indx for indx, eachL in enumerate(lines) if eachL == ""]
+ SplitL = list(zip([0] + SplitL[:-1], SplitL))
+ for indx, eachSection in enumerate(SplitL):
+ SplitL[indx] = list(filter(None, lines[slice(*eachSection)]))
+
+ match_str = "set_user_match r:%s i:%s -type port -noninverted"
+ lables = {"SOURCE_DESIGN": " ".join(SplitL[0]),
+ "SOURCE_TOP_DIR": "/WORK/" + " ".join(SplitL[1]),
+ "IMPL_DESIGN": " ".join(SplitL[2]),
+ "IMPL_TOP_DIR": "/WORK/" + " ".join(SplitL[3]),
+ "MATCH_MODUEL_LIST": "\n".join([match_str % tuple(eachPort.split()) for eachPort in SplitL[4]])
+ }
+
+ tmpl = Template(open(args.modelsim_template, encoding='utf-8').read())
+ with open("Output.tcl", 'w', encoding='utf-8') as tclout:
+ tclout.write(tmpl.substitute(lables))
+ if args.run_sim:
+ formality_run_string = ["formality", "-file", "Output.tcl"]
+ run_command("Modelsim run", "modelsim_run.log", formality_run_string)
+ else:
+ with open("Output.tcl", 'r', encoding='utf-8') as tclout:
+ print(tclout.read())
+
+
+def run_command(taskname, logfile, command, exit_if_fail=True):
+ logger.info("Launching %s " % taskname)
+ with open(logfile, 'w+') as output:
+ try:
+ output.write(" ".join(command)+"\n")
+ process = subprocess.run(command,
+ check=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True)
+ output.write(process.stdout)
+ if process.returncode:
+ logger.error("%s run failed with returncode %d" %
+ (taskname, process.returncode))
+ except (Exception, subprocess.CalledProcessError) as e:
+ logger.exception("failed to execute %s" % taskname)
+ return None
+ logger.info("%s is written in file %s" % (taskname, logfile))
+ return process.stdout
+
+
+if __name__ == "__main__":
+ main()
diff --git a/openfpga_flow/tasks/blif_vpr_flow/config/task.conf b/openfpga_flow/tasks/blif_vpr_flow/config/task.conf
index 867f75964..cf283f22a 100644
--- a/openfpga_flow/tasks/blif_vpr_flow/config/task.conf
+++ b/openfpga_flow/tasks/blif_vpr_flow/config/task.conf
@@ -17,9 +17,12 @@ fpga_flow=vpr_blif
[ARCHITECTURES]
# arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_DPRAM_template.xml
arch1=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml
-arch2=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml
-arch3=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
-arch4=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
+arch2=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml
+arch3=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_behavioral_verilog_template.xml
+arch4=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_non_lut_intermediate_buffer_template.xml
+arch5=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_1IO_template.xml
+#arch5=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tree_mux_template.xml
+#arch4=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/Test_Modes/test_modes.blif
@@ -30,21 +33,20 @@ bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/Test_Modes/test_mode
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/Test_Modes/test_modes.v
bench0_chan_width = 300
-[SCRIPT_PARAM_FIX_ROUTE_CHAN_WIDTH]
-fix_route_chan_width=300
-vpr_fpga_verilog_include_icarus_simulator=
-vpr_fpga_verilog_formal_verification_top_netlist=
-vpr_fpga_verilog_include_timing=
-vpr_fpga_verilog_include_signal_init=
-vpr_fpga_verilog_print_autocheck_top_testbench=
-vpr_fpga_bitstream_generator=
-vpr_fpga_verilog_print_user_defined_template=
-vpr_fpga_verilog_print_report_timing_tcl=
-vpr_fpga_verilog_print_sdc_pnr=
-vpr_fpga_verilog_print_sdc_analysis=
-vpr_fpga_x2p_compact_routing_hierarchy=
-end_flow_with_test=
-
+#[SCRIPT_PARAM_FIX_ROUTE_CHAN_WIDTH]
+#fix_route_chan_width=300
+#vpr_fpga_verilog_include_icarus_simulator=
+#vpr_fpga_verilog_formal_verification_top_netlist=
+#vpr_fpga_verilog_include_timing=
+#vpr_fpga_verilog_include_signal_init=
+#vpr_fpga_verilog_print_autocheck_top_testbench=
+#vpr_fpga_bitstream_generator=
+#vpr_fpga_verilog_print_user_defined_template=
+#vpr_fpga_verilog_print_report_timing_tcl=
+#vpr_fpga_verilog_print_sdc_pnr=
+#vpr_fpga_verilog_print_sdc_analysis=
+##vpr_fpga_x2p_compact_routing_hierarchy=
+#end_flow_with_test=
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
min_route_chan_width=1.3
@@ -58,7 +60,7 @@ vpr_fpga_verilog_print_user_defined_template=
vpr_fpga_verilog_print_report_timing_tcl=
vpr_fpga_verilog_print_sdc_pnr=
vpr_fpga_verilog_print_sdc_analysis=
-vpr_fpga_x2p_compact_routing_hierarchy=
+#vpr_fpga_x2p_compact_routing_hierarchy=
end_flow_with_test=
diff --git a/openfpga_flow/tasks/tileable_routing/config/task.conf b/openfpga_flow/tasks/tileable_routing/config/task.conf
new file mode 100644
index 000000000..3a7f092a6
--- /dev/null
+++ b/openfpga_flow/tasks/tileable_routing/config/task.conf
@@ -0,0 +1,57 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# Configuration file for running experiments
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
+# Each job execute fpga_flow script on combination of architecture & benchmark
+# timeout_each_job is timeout for each job
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+[GENERAL]
+power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
+power_analysis = true
+spice_output=false
+verilog_output=true
+timeout_each_job = 20*60
+fpga_flow=vpr_blif
+
+[ARCHITECTURES]
+arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml
+
+[BENCHMARKS]
+bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/Test_Modes/test_modes.blif
+
+[SYNTHESIS_PARAM]
+bench0_top = test_modes
+bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/Test_Modes/test_modes.act
+bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/Test_Modes/test_modes.v
+bench0_chan_width = 300
+
+[SCRIPT_PARAM_FIX_ROUTE_CHAN_WIDTH]
+fix_route_chan_width=300
+vpr_fpga_verilog_include_icarus_simulator=
+vpr_fpga_verilog_formal_verification_top_netlist=
+vpr_fpga_verilog_include_timing=
+vpr_fpga_verilog_include_signal_init=
+vpr_fpga_verilog_print_autocheck_top_testbench=
+vpr_fpga_bitstream_generator=
+vpr_fpga_verilog_print_user_defined_template=
+#vpr_fpga_verilog_print_report_timing_tcl=
+vpr_fpga_verilog_print_sdc_pnr=
+vpr_fpga_verilog_print_sdc_analysis=
+vpr_fpga_x2p_compact_routing_hierarchy=
+end_flow_with_test=
+
+#[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
+#min_route_chan_width=1.3
+#vpr_fpga_verilog_include_icarus_simulator=
+#vpr_fpga_verilog_formal_verification_top_netlist=
+#vpr_fpga_verilog_include_timing=
+#vpr_fpga_verilog_include_signal_init=
+#vpr_fpga_verilog_print_autocheck_top_testbench=
+#vpr_fpga_bitstream_generator=
+#vpr_fpga_verilog_print_user_defined_template=
+#vpr_fpga_verilog_print_report_timing_tcl=
+#vpr_fpga_verilog_print_sdc_pnr=
+#vpr_fpga_verilog_print_sdc_analysis=
+#vpr_fpga_x2p_compact_routing_hierarchy=
+#end_flow_with_test=
diff --git a/run_test.sh b/run_test.sh
new file mode 100644
index 000000000..027a1bea4
--- /dev/null
+++ b/run_test.sh
@@ -0,0 +1,133 @@
+# python3 openfpga_flow/scripts/run_fpga_flow.py \
+# ./openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml \
+# ./openfpga_flow/benchmarks/MCNC_Verilog/s298/s298.v \
+# --top_module s298 \
+# --power \
+# --power_tech ./openfpga_flow/tech/PTM_22nm/22nm.xml \
+# --min_route_chan_width 1.3 \
+# --vpr_fpga_verilog \
+# --vpr_fpga_verilog_dir . \
+# --vpr_fpga_x2p_rename_illegal_port \
+# --end_flow_with_test \
+# --vpr_fpga_verilog_include_icarus_simulator \
+# --vpr_fpga_verilog_formal_verification_top_netlist \
+# --vpr_fpga_verilog_include_timing \
+# --vpr_fpga_verilog_include_signal_init \
+# --vpr_fpga_verilog_print_autocheck_top_testbench
+
+# Test popular multi-mode architecture
+python3 openfpga_flow/scripts/run_fpga_flow.py \
+./openfpga_flow/arch/template/k6_N10_sram_chain_HC_template.xml \
+./openfpga_flow/benchmarks/Test_Modes/test_modes.blif \
+--fpga_flow vpr_blif \
+--top_module test_modes \
+--activity_file ./openfpga_flow/benchmarks/Test_Modes/test_modes.act \
+--base_verilog ./openfpga_flow/benchmarks/Test_Modes/test_modes.v \
+--power \
+--power_tech ./openfpga_flow/tech/PTM_45nm/45nm.xml \
+#--fix_route_chan_width 300 \
+--min_route_chan_width 1.3 \
+--vpr_fpga_verilog \
+--vpr_fpga_verilog_dir . \
+--vpr_fpga_x2p_rename_illegal_port \
+--vpr_fpga_verilog_include_icarus_simulator \
+--vpr_fpga_verilog_formal_verification_top_netlist \
+--vpr_fpga_verilog_include_timing \
+--vpr_fpga_verilog_include_signal_init \
+--vpr_fpga_verilog_print_autocheck_top_testbench \
+--debug \
+--vpr_fpga_bitstream_generator \
+--vpr_fpga_verilog_print_user_defined_template \
+--vpr_fpga_verilog_print_report_timing_tcl \
+--vpr_fpga_verilog_print_sdc_pnr \
+--vpr_fpga_verilog_print_sdc_analysis \
+--vpr_fpga_x2p_compact_routing_hierarchy \
+--end_flow_with_test
+
+# Test Standard cell MUX2
+python3 openfpga_flow/scripts/run_fpga_flow.py \
+./openfpga_flow/arch/template/k8_N10_sram_chain_FC_template.xml \
+./openfpga_flow/benchmarks/Test_Modes/test_modes.blif \
+--fpga_flow vpr_blif \
+--top_module test_modes \
+--activity_file ./openfpga_flow/benchmarks/Test_Modes/test_modes.act \
+--base_verilog ./openfpga_flow/benchmarks/Test_Modes/test_modes.v \
+--power \
+--power_tech ./openfpga_flow/tech/PTM_45nm/45nm.xml \
+#--fix_route_chan_width 300 \
+--min_route_chan_width 1.3 \
+--vpr_fpga_verilog \
+--vpr_fpga_verilog_dir . \
+--vpr_fpga_x2p_rename_illegal_port \
+--vpr_fpga_verilog_include_icarus_simulator \
+--vpr_fpga_verilog_formal_verification_top_netlist \
+--vpr_fpga_verilog_include_timing \
+--vpr_fpga_verilog_include_signal_init \
+--vpr_fpga_verilog_print_autocheck_top_testbench \
+--debug \
+--vpr_fpga_bitstream_generator \
+--vpr_fpga_verilog_print_user_defined_template \
+--vpr_fpga_verilog_print_report_timing_tcl \
+--vpr_fpga_verilog_print_sdc_pnr \
+--vpr_fpga_verilog_print_sdc_analysis \
+--vpr_fpga_x2p_compact_routing_hierarchy \
+--end_flow_with_test
+
+# Test local encoder feature
+python3 openfpga_flow/scripts/run_fpga_flow.py \
+./openfpga_flow/arch/template/k6_N10_sram_chain_HC_local_encoder_template.xml \
+./openfpga_flow/benchmarks/Test_Modes/test_modes.blif \
+--fpga_flow vpr_blif \
+--top_module test_modes \
+--activity_file ./openfpga_flow/benchmarks/Test_Modes/test_modes.act \
+--base_verilog ./openfpga_flow/benchmarks/Test_Modes/test_modes.v \
+--power \
+--power_tech ./openfpga_flow/tech/PTM_45nm/45nm.xml \
+--fix_route_chan_width 300 \
+--vpr_fpga_verilog \
+--vpr_fpga_verilog_dir . \
+--vpr_fpga_x2p_rename_illegal_port \
+--vpr_fpga_verilog_include_icarus_simulator \
+--vpr_fpga_verilog_formal_verification_top_netlist \
+--vpr_fpga_verilog_include_timing \
+--vpr_fpga_verilog_include_signal_init \
+--vpr_fpga_verilog_print_autocheck_top_testbench \
+--debug \
+--vpr_fpga_bitstream_generator \
+--vpr_fpga_verilog_print_user_defined_template \
+--vpr_fpga_verilog_print_report_timing_tcl \
+--vpr_fpga_verilog_print_sdc_pnr \
+--vpr_fpga_verilog_print_sdc_analysis \
+--vpr_fpga_x2p_compact_routing_hierarchy \
+--end_flow_with_test
+
+# Test tileable routing feature
+#python3 openfpga_flow/scripts/run_fpga_flow.py \
+#./openfpga_flow/arch/template/k6_N10_sram_chain_HC_tileable_template.xml \
+#./openfpga_flow/benchmarks/Test_Modes/test_modes.blif \
+#--fpga_flow vpr_blif \
+#--top_module test_modes \
+#--activity_file ./openfpga_flow/benchmarks/Test_Modes/test_modes.act \
+#--base_verilog ./openfpga_flow/benchmarks/Test_Modes/test_modes.v \
+#--power \
+#--power_tech ./openfpga_flow/tech/PTM_45nm/45nm.xml \
+##--fix_route_chan_width 300 \
+#--min_route_chan_width 1.3 \
+#--vpr_fpga_verilog \
+#--vpr_fpga_verilog_dir . \
+#--vpr_fpga_x2p_rename_illegal_port \
+#--vpr_fpga_verilog_include_icarus_simulator \
+#--vpr_fpga_verilog_formal_verification_top_netlist \
+#--vpr_fpga_verilog_include_timing \
+#--vpr_fpga_verilog_include_signal_init \
+#--vpr_fpga_verilog_print_autocheck_top_testbench \
+#--debug \
+#--vpr_fpga_bitstream_generator \
+#--vpr_fpga_verilog_print_user_defined_template \
+#--vpr_fpga_verilog_print_report_timing_tcl \
+#--vpr_fpga_verilog_print_sdc_pnr \
+#--vpr_fpga_verilog_print_sdc_analysis \
+#--vpr_fpga_x2p_compact_routing_hierarchy \
+#--vpr_use_tileable_route_chan_width \
+#--end_flow_with_test
+
diff --git a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp
index d32578d2d..f9e3bb9e1 100644
--- a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp
+++ b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.cpp
@@ -286,14 +286,14 @@ size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib,
}
/************************************************************************
- * A function to check the port map of SCFF circuit model
+ * A function to check the port map of CCFF circuit model
***********************************************************************/
-size_t check_scff_circuit_model_ports(const CircuitLibrary& circuit_lib,
+size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model) {
size_t num_err = 0;
/* Check the type of circuit model */
- VTR_ASSERT(SPICE_MODEL_SCFF == circuit_lib.model_type(circuit_model));
+ VTR_ASSERT(SPICE_MODEL_CCFF == circuit_lib.model_type(circuit_model));
/* Check if we have D, Set and Reset */
num_err += check_one_circuit_model_port_type_and_size_required(circuit_lib, circuit_model,
@@ -404,9 +404,9 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) {
* 2. Circuit models have unique prefix
* 3. Check IOPADs have input and output ports
* 4. Check MUXes has been defined and has input and output ports
- * 5. We must have at least one SRAM or SCFF
+ * 5. We must have at least one SRAM or CCFF
* 6. SRAM must have at least an input and an output ports
- * 7. SCFF must have at least a clock, an input and an output ports
+ * 7. CCFF must have at least a clock, an input and an output ports
* 8. FF must have at least a clock, an input and an output ports
* 9. LUT must have at least an input, an output and a SRAM ports
* 10. We must have default circuit models for these types: MUX, channel wires and wires
@@ -456,13 +456,13 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_MUX, mux_port_types_required);
- /* 5. We must have at least one SRAM or SCFF */
+ /* 5. We must have at least one SRAM or CCFF */
if ( ( 0 == circuit_lib.models_by_type(SPICE_MODEL_SRAM).size())
- && ( 0 == circuit_lib.models_by_type(SPICE_MODEL_SCFF).size()) ) {
+ && ( 0 == circuit_lib.models_by_type(SPICE_MODEL_CCFF).size()) ) {
vpr_printf(TIO_MESSAGE_ERROR,
"At least one %s or %s circuit model is required!\n",
CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SRAM)],
- CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_SCFF)]);
+ CIRCUIT_MODEL_TYPE_STRING[size_t(SPICE_MODEL_CCFF)]);
/* Incremental the counter for errors */
num_err++;
}
@@ -474,13 +474,13 @@ void check_circuit_library(const CircuitLibrary& circuit_lib) {
num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SRAM, sram_port_types_required);
- /* 7. SCFF must have at least a clock, an input and an output ports*/
- std::vector scff_port_types_required;
- scff_port_types_required.push_back(SPICE_MODEL_PORT_CLOCK);
- scff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
- scff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
+ /* 7. CCFF must have at least a clock, an input and an output ports*/
+ std::vector ccff_port_types_required;
+ ccff_port_types_required.push_back(SPICE_MODEL_PORT_CLOCK);
+ ccff_port_types_required.push_back(SPICE_MODEL_PORT_INPUT);
+ ccff_port_types_required.push_back(SPICE_MODEL_PORT_OUTPUT);
- num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_SCFF, scff_port_types_required);
+ num_err += check_circuit_model_port_required(circuit_lib, SPICE_MODEL_CCFF, ccff_port_types_required);
/* 8. FF must have at least a clock, an input and an output ports*/
std::vector ff_port_types_required;
diff --git a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.h b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.h
index 2d0bd3f03..dd6114696 100644
--- a/vpr7_x2p/libarchfpga/SRC/check_circuit_library.h
+++ b/vpr7_x2p/libarchfpga/SRC/check_circuit_library.h
@@ -71,7 +71,7 @@ size_t check_one_circuit_model_port_type_and_size_required(const CircuitLibrary&
size_t check_ff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
-size_t check_scff_circuit_model_ports(const CircuitLibrary& circuit_lib,
+size_t check_ccff_circuit_model_ports(const CircuitLibrary& circuit_lib,
const CircuitModelId& circuit_model);
size_t check_sram_circuit_model_ports(const CircuitLibrary& circuit_lib,
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp b/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp
index 6a7d23a64..5b7c7b62d 100644
--- a/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_library.cpp
@@ -612,7 +612,7 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ
}
/* Recursively find all the global ports in the circuit model / sub circuit_model
- * but ignore all the SRAM and SCFF, which are configuration memories
+ * but ignore all the SRAM and CCFF, which are configuration memories
*/
std::vector CircuitLibrary::model_global_ports_by_type(const CircuitModelId& model_id,
const enum e_spice_model_port_type& type,
@@ -621,7 +621,7 @@ std::vector CircuitLibrary::model_global_ports_by_type(const Circ
std::vector ignore_list;
if (true == ignore_config_memories) {
ignore_list.push_back(SPICE_MODEL_SRAM);
- ignore_list.push_back(SPICE_MODEL_SCFF);
+ ignore_list.push_back(SPICE_MODEL_CCFF);
}
return model_global_ports_by_type(model_id, type, recursive, ignore_list);
}
@@ -1875,7 +1875,7 @@ void CircuitLibrary::build_submodels() {
/* Build a unique list */
for (const auto& cand : candidates) {
/* Make sure the model id is unique in the list */
- if (true == is_unique_submodel(model,cand)) {
+ if (true == is_unique_submodel(model, cand)) {
sub_models_[model].push_back(cand);
}
}
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library.h b/vpr7_x2p/libarchfpga/SRC/circuit_library.h
index 56de466a7..8080d2ea3 100644
--- a/vpr7_x2p/libarchfpga/SRC/circuit_library.h
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_library.h
@@ -453,8 +453,8 @@ class CircuitLibrary {
void link_buffer_model(const CircuitModelId& model_id);
void link_pass_gate_logic_model(const CircuitModelId& model_id);
bool is_unique_submodel(const CircuitModelId& model_id, const CircuitModelId& submodel_id);
- void build_submodels();
void build_model_timing_graph(const CircuitModelId& model_id);
+ void build_submodels();
public: /* Public Mutators: builders */
void build_model_links();
void build_timing_graphs();
@@ -471,11 +471,12 @@ class CircuitLibrary {
public: /* Internal mutators: build fast look-ups */
void build_model_lookup();
void build_model_port_lookup();
- private: /* Internal invalidators/validators */
- /* Validators */
+ public: /* Public invalidators/validators */
bool valid_model_id(const CircuitModelId& model_id) const;
bool valid_circuit_port_id(const CircuitPortId& circuit_port_id) const;
bool valid_circuit_pin_id(const CircuitPortId& circuit_port_id, const size_t& pin_id) const;
+ private: /* Internal invalidators/validators */
+ /* Validators */
bool valid_edge_id(const CircuitEdgeId& edge_id) const;
bool valid_delay_type(const CircuitModelId& model_id, const enum spice_model_delay_type& delay_type) const;
bool valid_circuit_edge_id(const CircuitEdgeId& circuit_edge_id) const;
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp
new file mode 100644
index 000000000..63fcb15eb
--- /dev/null
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.cpp
@@ -0,0 +1,93 @@
+/**********************************************************
+ * MIT License
+ *
+ * Copyright (c) 2018 LNIS - The University of Utah
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ ***********************************************************************/
+
+/************************************************************************
+ * Filename: circuit_library_utils.cpp
+ * Created by: Xifan Tang
+ * Change history:
+ * +-------------------------------------+
+ * | Date | Author | Notes
+ * +-------------------------------------+
+ * | 2019/09/27 | Xifan Tang | Created
+ * +-------------------------------------+
+ ***********************************************************************/
+
+/************************************************************************
+ * Function to perform fundamental operation for the circuit library
+ * These functions are not universal methods for the CircuitLibrary class
+ * They are made to ease the development in some specific purposes
+ * Please classify such functions in this file
+ ***********************************************************************/
+
+/* Header files should be included in a sequence */
+/* Standard header files required go first */
+#include
+
+#include "vtr_assert.h"
+
+#include "util.h"
+
+#include "circuit_library_utils.h"
+
+/********************************************************************
+ * Get the model id of a SRAM model that is used to configure
+ * a circuit model
+ *******************************************************************/
+std::vector find_circuit_sram_models(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model) {
+ /* SRAM model id is stored in the sram ports of a circuit model */
+ std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_SRAM);
+ std::vector sram_models;
+
+ /* Create a list of sram models, but avoid duplicated model ids */
+ for (const auto& sram_port : sram_ports) {
+ CircuitModelId sram_model = circuit_lib.port_tri_state_model(sram_port);
+ VTR_ASSERT( true == circuit_lib.valid_model_id(sram_model) );
+ if (sram_models.end() != std::find(sram_models.begin(), sram_models.end(), sram_model)) {
+ continue; /* Already in the list, skip the addition */
+ }
+ /* Not in the list, add it */
+ sram_models.push_back(sram_model);
+ }
+
+ return sram_models;
+}
+
+/********************************************************************
+ * Find regular (not mode select) sram ports of a circuit model
+ *******************************************************************/
+std::vector find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model) {
+ std::vector sram_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_SRAM, true);
+ std::vector regular_sram_ports;
+
+ for (const auto& port : sram_ports) {
+ if (true == circuit_lib.port_is_mode_select(port)) {
+ continue;
+ }
+ regular_sram_ports.push_back(port);
+ }
+
+ return regular_sram_ports;
+}
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h
new file mode 100644
index 000000000..f4323f391
--- /dev/null
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_library_utils.h
@@ -0,0 +1,19 @@
+/********************************************************************
+ * Header file for circuit_library_utils.cpp
+ *******************************************************************/
+#ifndef CIRCUIT_LIBRARY_UTILS_H
+#define CIRCUIT_LIBRARY_UTILS_H
+
+/* Header files should be included in a sequence */
+/* Standard header files required go first */
+
+#include
+#include "circuit_library.h"
+
+std::vector find_circuit_sram_models(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model);
+
+std::vector find_circuit_regular_sram_ports(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model);
+
+#endif
diff --git a/vpr7_x2p/libarchfpga/SRC/circuit_types.h b/vpr7_x2p/libarchfpga/SRC/circuit_types.h
index 92e8b1c61..9a0e72dda 100644
--- a/vpr7_x2p/libarchfpga/SRC/circuit_types.h
+++ b/vpr7_x2p/libarchfpga/SRC/circuit_types.h
@@ -66,7 +66,7 @@ enum e_spice_model_type {
SPICE_MODEL_FF,
SPICE_MODEL_SRAM,
SPICE_MODEL_HARDLOGIC,
- SPICE_MODEL_SCFF,
+ SPICE_MODEL_CCFF,
SPICE_MODEL_IOPAD,
SPICE_MODEL_INVBUF,
SPICE_MODEL_PASSGATE,
@@ -74,7 +74,7 @@ enum e_spice_model_type {
NUM_CIRCUIT_MODEL_TYPES
};
/* Strings correspond to each port type */
-constexpr std::array CIRCUIT_MODEL_TYPE_STRING = {{"CHAN_WIRE", "WIRE", "MUX", "LUT", "FF", "SRAM", "HARDLOGIC", "SCFF", "IOPAD", "INVBUF", "PASSGATE", "GATE"}};
+constexpr std::array CIRCUIT_MODEL_TYPE_STRING = {{"CHAN_WIRE", "WIRE", "MUX", "LUT", "FF", "SRAM", "HARDLOGIC", "CCFF", "IOPAD", "INVBUF", "PASSGATE", "GATE"}};
enum e_spice_model_design_tech {
SPICE_MODEL_DESIGN_CMOS,
diff --git a/vpr7_x2p/libarchfpga/SRC/device_port.cpp b/vpr7_x2p/libarchfpga/SRC/device_port.cpp
index 2de15172d..38241f198 100644
--- a/vpr7_x2p/libarchfpga/SRC/device_port.cpp
+++ b/vpr7_x2p/libarchfpga/SRC/device_port.cpp
@@ -136,10 +136,14 @@ void BasicPort::revert() {
/* rotate: increase both lsb and msb by an offset */
bool BasicPort::rotate(const size_t& offset) {
- /* If current port is invalid or offset is 0,
- * we do nothing
- */
- if ((0 == offset) || (0 == get_width())) {
+ /* If offset is 0, we do nothing */
+ if (0 == offset) {
+ return true;
+ }
+
+ /* If current width is 0, we set a width using the offset! */
+ if (0 == get_width()) {
+ set_width(offset);
return true;
}
/* check if leads to overflow:
diff --git a/vpr7_x2p/libarchfpga/SRC/physical_types.h b/vpr7_x2p/libarchfpga/SRC/physical_types.h
index 81de09866..e9fb0745e 100644
--- a/vpr7_x2p/libarchfpga/SRC/physical_types.h
+++ b/vpr7_x2p/libarchfpga/SRC/physical_types.h
@@ -924,6 +924,10 @@ typedef struct s_direct_inf {
int y_offset;
int z_offset;
int line;
+ /* Aurelien: point to point support in direct connection from directlist */
+ enum e_point2point_interconnection_type interconnection_type;
+ enum e_point2point_interconnection_dir x_dir;
+ enum e_point2point_interconnection_dir y_dir;
/* Xifan Tang: FPGA-SPICE support */
char* spice_model_name;
t_spice_model* spice_model;
diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c b/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c
index d852e07dd..55a05bba9 100644
--- a/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c
+++ b/vpr7_x2p/libarchfpga/SRC/read_xml_arch_file.c
@@ -3578,6 +3578,9 @@ static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs,
const char *direct_name;
const char *from_pin_name;
const char *to_pin_name;
+ const char *point2point_type;
+ const char *x_dir;
+ const char *y_dir;
ezxml_t Node;
@@ -3632,6 +3635,77 @@ static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs,
ezxml_set_attr(Node, "y_offset", NULL);
ezxml_set_attr(Node, "z_offset", NULL);
+ // Aurelien: Read point to point connection parameters
+ if((!FindProperty(Node, "interconnection_type", FALSE)) ||
+ (0 == strcmp(FindProperty(Node, "interconnection_type", FALSE), "NONE"))) {
+ (*Directs)[i].interconnection_type = NO_P2P;
+ } else if(0 == strcmp(FindProperty(Node, "interconnection_type", FALSE), "column")) {
+ (*Directs)[i].interconnection_type = P2P_DIRECT_COLUMN;
+ } else if(0 == strcmp(FindProperty(Node, "interconnection_type", FALSE), "row")) {
+ (*Directs)[i].interconnection_type = P2P_DIRECT_ROW;
+ } else {
+ (*Directs)[i].interconnection_type = NUM_POINT2POINT_INTERCONNECT_TYPE;
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "Invalid point to point connection '%s' in directlist. '%s' value should be '%s', '%s' or '%s' !\n",
+ (*Directs)[i].name,
+ "interconnection_type",
+ "column",
+ "row",
+ "NONE" );
+ exit(1);
+ }
+ if((P2P_DIRECT_COLUMN == (*Directs)[i].interconnection_type) ||
+ (P2P_DIRECT_ROW == (*Directs)[i].interconnection_type)){
+ if(0 == strcmp(FindProperty(Node, "x_dir", TRUE), "positive")){
+ (*Directs)[i].x_dir = POSITIVE_DIR;
+ } else if(0 == strcmp(FindProperty(Node, "x_dir", TRUE), "negative")){
+ (*Directs)[i].x_dir = NEGATIVE_DIR;
+ } else {
+ (*Directs)[i].x_dir = NUM_POINT2POINT_INTERCONNECT_DIR;
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "Invalid point to point connection '%s' in directlist. '%s' value should be '%s' or '%s' !\n",
+ (*Directs)[i].name,
+ "x_dir",
+ "positive",
+ "negative" );
+ }
+ if(0 == strcmp(FindProperty(Node, "y_dir", TRUE), "positive")){
+ (*Directs)[i].y_dir = POSITIVE_DIR;
+ } else if(0 == strcmp(FindProperty(Node, "y_dir", TRUE), "negative")){
+ (*Directs)[i].y_dir = NEGATIVE_DIR;
+ } else {
+ (*Directs)[i].y_dir = NUM_POINT2POINT_INTERCONNECT_DIR;
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "Invalid point to point connection '%s' in directlist. '%s' value should be '%s' or '%s' !\n",
+ (*Directs)[i].name,
+ "y_dir",
+ "positive",
+ "negative" );
+ }
+ } else {
+ if(NULL == FindProperty(Node, "x_dir", FALSE)){
+ (*Directs)[i].x_dir = NUM_POINT2POINT_INTERCONNECT_DIR;
+ } else if(0 == strcmp(FindProperty(Node, "x_dir", FALSE), "positive")){
+ (*Directs)[i].x_dir = POSITIVE_DIR;
+ } else if(0 == strcmp(FindProperty(Node, "x_dir", FALSE), "negative")){
+ (*Directs)[i].x_dir = NEGATIVE_DIR;
+ } else {
+ (*Directs)[i].x_dir = NUM_POINT2POINT_INTERCONNECT_DIR;
+ }
+ if(NULL == FindProperty(Node, "y_dir", FALSE)){
+ (*Directs)[i].y_dir = NUM_POINT2POINT_INTERCONNECT_DIR;
+ } else if(0 == strcmp(FindProperty(Node, "y_dir", FALSE), "positive")){
+ (*Directs)[i].y_dir = POSITIVE_DIR;
+ } else if(0 == strcmp(FindProperty(Node, "y_dir", FALSE), "negative")){
+ (*Directs)[i].y_dir = NEGATIVE_DIR;
+ } else {
+ (*Directs)[i].y_dir = NUM_POINT2POINT_INTERCONNECT_DIR;
+ }
+ }
+ ezxml_set_attr(Node, "x_dir", NULL);
+ ezxml_set_attr(Node, "y_dir", NULL);
+ ezxml_set_attr(Node, "interconnection_type", NULL);
+
/* Check that the direct chain connection is not zero in both direction */
if ((*Directs)[i].x_offset == 0 && (*Directs)[i].y_offset == 0) {
vpr_printf(TIO_MESSAGE_ERROR,
diff --git a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c
index 10c4b2bbe..c630dc37f 100644
--- a/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c
+++ b/vpr7_x2p/libarchfpga/SRC/read_xml_spice.c
@@ -915,7 +915,7 @@ static void ProcessSpiceModel(ezxml_t Parent,
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"hard_logic")) {
spice_model->type = SPICE_MODEL_HARDLOGIC;
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"sff")) {
- spice_model->type = SPICE_MODEL_SCFF;
+ spice_model->type = SPICE_MODEL_CCFF;
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"iopad")) {
spice_model->type = SPICE_MODEL_IOPAD;
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"inv_buf")) {
@@ -1417,7 +1417,7 @@ static void check_spice_models(int num_spice_model,
}
}
/* Check scan-chain dff has input and output, clock ports*/
- if (SPICE_MODEL_SCFF == spice_models[i].type) {
+ if (SPICE_MODEL_CCFF == spice_models[i].type) {
has_sram = 1;
has_clock_port = 0;
has_in_port = 0;
diff --git a/vpr7_x2p/libarchfpga/SRC/spice_types.h b/vpr7_x2p/libarchfpga/SRC/spice_types.h
index 42ecbb3f2..26f30b164 100644
--- a/vpr7_x2p/libarchfpga/SRC/spice_types.h
+++ b/vpr7_x2p/libarchfpga/SRC/spice_types.h
@@ -5,6 +5,20 @@
#include "linkedlist.h"
#include "circuit_library.h"
+/* Aurelien: point to point connection */
+enum e_point2point_interconnection_type {
+ NO_P2P,
+ P2P_DIRECT_COLUMN,
+ P2P_DIRECT_ROW,
+ NUM_POINT2POINT_INTERCONNECT_TYPE
+};
+
+enum e_point2point_interconnection_dir {
+ POSITIVE_DIR,
+ NEGATIVE_DIR,
+ NUM_POINT2POINT_INTERCONNECT_DIR
+};
+
/* Xifan TANG: Spice support*/
enum e_spice_tech_lib_type {
SPICE_LIB_INDUSTRY,
@@ -476,12 +490,12 @@ struct s_mem_bank_info {
};
/* Scan-chain Flip-flops information */
-typedef struct s_scff_info t_scff_info;
-struct s_scff_info {
+typedef struct s_ccff_info t_ccff_info;
+struct s_ccff_info {
t_spice_model* mem_model; /* SPICE model of a memory bit */
int num_mem_bit; /* Number of memory bits in total */
- int num_scff; /* Number of Scan-chain flip-flops */
- /* TODO: More to be added, SCFF support is naive now */
+ int num_ccff; /* Number of Scan-chain flip-flops */
+ /* TODO: More to be added, CCFF support is naive now */
};
/* Standalone SRAMs information */
@@ -495,7 +509,7 @@ struct s_standalone_sram_info {
struct s_sram_orgz_info {
enum e_sram_orgz type;
t_mem_bank_info* mem_bank_info; /* Only be allocated when orgz type is memory bank */
- t_scff_info* scff_info; /* Only be allocated when orgz type is scan-chain */
+ t_ccff_info* ccff_info; /* Only be allocated when orgz type is scan-chain */
t_standalone_sram_info* standalone_sram_info; /* Only be allocated when orgz type is standalone */
/* Head of configuration bits,
diff --git a/vpr7_x2p/vpr/SRC/base/vpr_types.h b/vpr7_x2p/vpr/SRC/base/vpr_types.h
index 4b039d5c8..820ee7126 100755
--- a/vpr7_x2p/vpr/SRC/base/vpr_types.h
+++ b/vpr7_x2p/vpr/SRC/base/vpr_types.h
@@ -1123,6 +1123,10 @@ typedef struct s_clb_to_clb_directs {
t_type_descriptor *to_clb_type;
int to_clb_pin_start_index;
int to_clb_pin_end_index;
+ /* Aurelien: point to point support in direct connection from directlist */
+ enum e_point2point_interconnection_type interconnection_type;
+ enum e_point2point_interconnection_dir x_dir;
+ enum e_point2point_interconnection_dir y_dir;
/* Xifan Tang: add useful addition info to this struct */
int x_offset;
int y_offset;
diff --git a/vpr7_x2p/vpr/SRC/device/decoder_library_utils.cpp b/vpr7_x2p/vpr/SRC/device/decoder_library_utils.cpp
index ca773819e..47ec9a9a9 100644
--- a/vpr7_x2p/vpr/SRC/device/decoder_library_utils.cpp
+++ b/vpr7_x2p/vpr/SRC/device/decoder_library_utils.cpp
@@ -27,12 +27,14 @@
* We plus 1, which is all-zero condition for outputs
***************************************************************************************/
size_t find_mux_local_decoder_addr_size(const size_t& data_size) {
- /* Make sure we have a encoder which is at least 2 ! */
+ /* if data size is 1, it is an corner case for the decoder (addr = 1) */
+ if (1 == data_size) {
+ return 1;
+ }
VTR_ASSERT (2 <= data_size);
return ceil(log(data_size) / log(2));
}
-
/***************************************************************************************
* Try to find if the decoder already exists in the library,
* If there is no such decoder, add it to the library
diff --git a/vpr7_x2p/vpr/SRC/device/decoder_library_utils.h b/vpr7_x2p/vpr/SRC/device/decoder_library_utils.h
index f0719f2e6..100f04da7 100644
--- a/vpr7_x2p/vpr/SRC/device/decoder_library_utils.h
+++ b/vpr7_x2p/vpr/SRC/device/decoder_library_utils.h
@@ -6,6 +6,8 @@
#include "decoder_library.h"
+bool need_mux_local_decoder(const size_t& data_size);
+
size_t find_mux_local_decoder_addr_size(const size_t& data_size);
DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib,
diff --git a/vpr7_x2p/vpr/SRC/device/mux_graph.cpp b/vpr7_x2p/vpr/SRC/device/mux_graph.cpp
index 91105ddbf..608ffa4b5 100644
--- a/vpr7_x2p/vpr/SRC/device/mux_graph.cpp
+++ b/vpr7_x2p/vpr/SRC/device/mux_graph.cpp
@@ -65,6 +65,14 @@ MuxGraph::mem_range MuxGraph::memories() const {
return vtr::make_range(mem_ids_.begin(), mem_ids_.end());
}
+std::vector MuxGraph::levels() const {
+ std::vector graph_levels;
+ for (size_t lvl = 0; lvl < num_levels(); ++lvl) {
+ graph_levels.push_back(lvl);
+ }
+ return graph_levels;
+}
+
/**************************************************
* Public Accessors: Data query
*************************************************/
@@ -158,6 +166,14 @@ size_t MuxGraph::num_memory_bits() const {
return mem_ids_.size();
}
+/* Find the number of SRAMs at a level in the MUX graph */
+size_t MuxGraph::num_memory_bits_at_level(const size_t& level) const {
+ /* need to check if the graph is valid or not */
+ VTR_ASSERT_SAFE(valid_level(level));
+ VTR_ASSERT_SAFE(valid_mux_graph());
+ return mem_lookup_[level].size();
+}
+
/* Find the number of nodes at a given level in the MUX graph */
size_t MuxGraph::num_nodes_at_level(const size_t& level) const {
/* validate the level numbers */
@@ -310,6 +326,7 @@ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const {
}
/* Not found, we add a memory bit and record in the mem-to-mem map */
MuxMemId mem_subgraph = mux_graph.add_mem();
+ mux_graph.set_mem_level(mem_subgraph, 0);
mem2mem_map[mem_origin] = mem_subgraph;
/* configure the edge */
mux_graph.edge_mem_ids_[edge2edge_map[edge_origin]] = mem_subgraph;
@@ -317,6 +334,7 @@ MuxGraph MuxGraph::subgraph(const MuxNodeId& root_node) const {
/* Since the graph is finalized, it is time to build the fast look-up */
mux_graph.build_node_lookup();
+ mux_graph.build_mem_lookup();
return mux_graph;
}
@@ -519,11 +537,20 @@ MuxMemId MuxGraph::add_mem() {
MuxMemId mem = MuxMemId(mem_ids_.size());
/* Push to the node list */
mem_ids_.push_back(mem);
+ mem_levels_.push_back(size_t(-1));
/* Resize the other node-related vectors */
return mem;
}
+/* Configure the level of a memory */
+void MuxGraph::set_mem_level(const MuxMemId& mem, const size_t& level) {
+ /* Make sure we have valid edge and mem */
+ VTR_ASSERT( valid_mem_id(mem) );
+
+ mem_levels_[mem] = level;
+}
+
/* Link an edge to a memory bit */
void MuxGraph::set_edge_mem_id(const MuxEdgeId& edge, const MuxMemId& mem) {
/* Make sure we have valid edge and mem */
@@ -593,8 +620,11 @@ void MuxGraph::build_multilevel_mux_graph(const size_t& mux_size,
num_mems_per_level = 1;
}
/* Number of memory bits is definite, add them */
- for (size_t i = 0; i < num_mems_per_level * num_levels; ++i) {
- add_mem();
+ for (size_t ilvl = 0; ilvl < num_levels; ++ilvl) {
+ for (size_t imem = 0; imem < num_mems_per_level; ++imem) {
+ MuxMemId mem = add_mem();
+ mem_levels_[mem] = ilvl;
+ }
}
/* Create a fast node lookup locally.
@@ -747,6 +777,7 @@ void MuxGraph::build_onelevel_mux_graph(const size_t& mux_size,
/* Create a memory bit*/
MuxMemId mem = add_mem();
+ mem_levels_[mem] = 0;
/* Link the edge to a memory bit */
set_edge_mem_id(edge, mem);
}
@@ -863,6 +894,7 @@ void MuxGraph::build_mux_graph(const CircuitLibrary& circuit_lib,
/* Since the graph is finalized, it is time to build the fast look-up */
build_node_lookup();
+ build_mem_lookup();
/* For fracturable LUTs, we need to add more outputs to the MUX graph */
if ( (SPICE_MODEL_LUT == circuit_lib.model_type(circuit_model))
@@ -895,10 +927,34 @@ void MuxGraph::build_node_lookup() {
}
}
+/* Build fast mem lookup */
+void MuxGraph::build_mem_lookup() {
+ /* Invalidate the mem lookup if necessary */
+ invalidate_mem_lookup();
+
+ /* Find the maximum number of levels */
+ size_t num_levels = 0;
+ for (auto mem : memories()) {
+ num_levels = std::max((int)mem_levels_[mem], (int)num_levels);
+ }
+
+ /* Resize mem_lookup */
+ mem_lookup_.resize(num_levels + 1);
+ for (auto mem : memories()) {
+ /* Categorize mem nodes into mem_lookup */
+ mem_lookup_[mem_levels_[mem]].push_back(mem);
+ }
+}
+
/* Invalidate (empty) the node fast lookup*/
void MuxGraph::invalidate_node_lookup() {
node_lookup_.clear();
}
+
+/* Invalidate (empty) the mem fast lookup*/
+void MuxGraph::invalidate_mem_lookup() {
+ mem_lookup_.clear();
+}
/**************************************************
* Private validators
diff --git a/vpr7_x2p/vpr/SRC/device/mux_graph.h b/vpr7_x2p/vpr/SRC/device/mux_graph.h
index 856c7e0b1..ddb80e6f4 100644
--- a/vpr7_x2p/vpr/SRC/device/mux_graph.h
+++ b/vpr7_x2p/vpr/SRC/device/mux_graph.h
@@ -62,6 +62,7 @@ class MuxGraph {
std::vector non_input_nodes() const;
edge_range edges() const;
mem_range memories() const;
+ std::vector levels() const;
public: /* Public accessors: Data query */
/* Find the number of inputs in the MUX graph */
size_t num_inputs() const;
@@ -76,6 +77,8 @@ class MuxGraph {
size_t num_node_levels() const;
/* Find the number of SRAMs in the MUX graph */
size_t num_memory_bits() const;
+ /* Find the number of SRAMs at a level in the MUX graph */
+ size_t num_memory_bits_at_level(const size_t& level) const;
/* Find the number of nodes at a given level in the MUX graph */
size_t num_nodes_at_level(const size_t& level) const;
/* Find the level of a node */
@@ -112,6 +115,8 @@ class MuxGraph {
MuxEdgeId add_edge(const MuxNodeId& from_node, const MuxNodeId& to_node);
/* Add a memory bit to the MuxGraph */
MuxMemId add_mem();
+ /* Configure the level of a memory */
+ void set_mem_level(const MuxMemId& mem, const size_t& level);
/* Link an edge to a mem */
void set_edge_mem_id(const MuxEdgeId& edge, const MuxMemId& mem);
private: /* Private mutators : graph builders */
@@ -130,6 +135,8 @@ class MuxGraph {
const CircuitModelId& circuit_model);
/* Build fast node lookup */
void build_node_lookup();
+ /* Build fast mem lookup */
+ void build_mem_lookup();
private: /* Private validators */
/* valid ids */
bool valid_node_id(const MuxNodeId& node) const;
@@ -141,6 +148,7 @@ class MuxGraph {
/* validate/invalidate node lookup */
bool valid_node_lookup() const;
void invalidate_node_lookup();
+ void invalidate_mem_lookup();
/* validate graph */
bool valid_mux_graph() const;
private: /* Internal data */
@@ -161,10 +169,13 @@ class MuxGraph {
vtr::vector edge_inv_mem_; /* if the edge is controlled by an inverted output of a memory bit */
vtr::vector mem_ids_; /* ids of configuration memories */
+ vtr::vector mem_levels_; /* ids of configuration memories */
/* fast look-up */
typedef std::vector>> NodeLookup;
mutable NodeLookup node_lookup_; /* [num_levels][num_types][num_nodes_per_level] */
+ typedef std::vector> MemLookup;
+ mutable MemLookup mem_lookup_; /* [num_levels][num_mems_per_level] */
};
#endif
diff --git a/vpr7_x2p/vpr/SRC/device/mux_library.h b/vpr7_x2p/vpr/SRC/device/mux_library.h
index 93e004252..7e38f27b1 100644
--- a/vpr7_x2p/vpr/SRC/device/mux_library.h
+++ b/vpr7_x2p/vpr/SRC/device/mux_library.h
@@ -32,8 +32,9 @@ class MuxLibrary {
public: /* Public mutators */
/* Add a mux to the library */
void add_mux(const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model, const size_t& mux_size);
- private: /* Private accessors */
+ public: /* Public validators */
bool valid_mux_id(const MuxId& mux) const;
+ private: /* Private accessors */
bool valid_mux_lookup() const;
bool valid_mux_circuit_model_id(const CircuitModelId& circuit_model) const;
bool valid_mux_size(const CircuitModelId& circuit_model, const size_t& mux_size) const;
diff --git a/vpr7_x2p/vpr/SRC/device/mux_utils.cpp b/vpr7_x2p/vpr/SRC/device/mux_utils.cpp
index 3fafb1998..53e71f1f8 100644
--- a/vpr7_x2p/vpr/SRC/device/mux_utils.cpp
+++ b/vpr7_x2p/vpr/SRC/device/mux_utils.cpp
@@ -3,10 +3,12 @@
* that are used to implement a multiplexer
*************************************************/
#include
+#include
#include "spice_types.h"
#include "util.h"
#include "vtr_assert.h"
+#include "decoder_library_utils.h"
#include "mux_utils.h"
/* Validate the number of inputs for a multiplexer implementation,
@@ -177,9 +179,15 @@ std::vector build_mux_intermediate_buffer_location_map(const CircuitLibrar
std::string location_map_str;
/* ONLY for LUTs: intermediate buffers may exist if specified */
- if (SPICE_MODEL_LUT == circuit_lib.model_type(circuit_model)) {
+ if (SPICE_MODEL_LUT != circuit_lib.model_type(circuit_model)) {
+ return location_map;
+ }
+
+ /* Get location map when the flag of intermediate buffer is on */
+ if (true == circuit_lib.is_lut_intermediate_buffered(circuit_model)) {
location_map_str = circuit_lib.lut_intermediate_buffer_location_map(circuit_model);
}
+
/* If no location map is specified, we can return here */
if (location_map_str.empty()) {
return location_map;
@@ -231,3 +239,150 @@ MuxLibrary convert_mux_arch_to_library(const CircuitLibrary& circuit_lib, t_llis
return mux_lib;
}
+
+/**************************************************
+ * Find the number of reserved configuration bits for a multiplexer
+ * The reserved configuration bits is only used by ReRAM-based multiplexers
+ * It is actually the shared BL/WLs among ReRAMs
+ *************************************************/
+size_t find_mux_num_reserved_config_bits(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const MuxGraph& mux_graph) {
+ if (SPICE_MODEL_DESIGN_RRAM != circuit_lib.design_tech_type(mux_model)) {
+ return 0;
+ }
+
+ std::vector mux_branch_sizes = mux_graph.branch_sizes();
+ /* For tree-like multiplexers: they have two shared configuration bits */
+ if ( (1 == mux_branch_sizes.size())
+ && (2 == mux_branch_sizes[0]) ) {
+ return mux_branch_sizes[0];
+ }
+ /* One-level multiplexer */
+ if ( 1 == mux_graph.num_levels() ) {
+ return mux_graph.num_inputs();
+ }
+ /* Multi-level multiplexers: TODO: This should be better tested and clarified
+ * Now the multi-level multiplexers are treated as cascaded one-level multiplexers
+ * Use the maximum branch sizes and multiply it by the number of levels
+ */
+ std::vector::iterator max_mux_branch_size = std::max_element(mux_branch_sizes.begin(), mux_branch_sizes.end());
+ return mux_graph.num_levels() * (*max_mux_branch_size);
+}
+
+/**************************************************
+ * Find the number of configuration bits for a CMOS multiplexer
+ * In general, the number of configuration bits is
+ * the number of memory bits for a mux_graph
+ * However, when local decoders are used,
+ * the number of configuration bits are reduced to log2(X)
+ *************************************************/
+static
+size_t find_cmos_mux_num_config_bits(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const MuxGraph& mux_graph,
+ const e_sram_orgz& sram_orgz_type) {
+ size_t num_config_bits = 0;
+
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_MEMORY_BANK:
+ case SPICE_SRAM_SCAN_CHAIN:
+ case SPICE_SRAM_STANDALONE:
+ num_config_bits = mux_graph.num_memory_bits();
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(FILE:%s,LINE[%d])Invalid type of SRAM organization!\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ if (false == circuit_lib.mux_use_local_encoder(mux_model)) {
+ return num_config_bits;
+ }
+
+ num_config_bits = 0;
+ /* Multiplexer local encoders are applied to memory bits at each stage */
+ for (const auto& lvl : mux_graph.levels()) {
+ num_config_bits += find_mux_local_decoder_addr_size(mux_graph.num_memory_bits_at_level(lvl));
+ }
+
+ return num_config_bits;
+}
+
+/**************************************************
+ * Find the number of configuration bits for a RRAM multiplexer
+ * In general, the number of configuration bits is
+ * the number of levels for a mux_graph
+ * This is due to only the last BL/WL of the multiplexer is
+ * independent from each other
+ * However, when local decoders are used,
+ * the number of configuration bits should be consider all the
+ * shared(reserved) configuration bits and independent bits
+ *************************************************/
+static
+size_t find_rram_mux_num_config_bits(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const MuxGraph& mux_graph,
+ const e_sram_orgz& sram_orgz_type) {
+ size_t num_config_bits = 0;
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_MEMORY_BANK:
+ /* In memory bank, by intensively share the Bit/Word Lines,
+ * we only need 1 additional BL and WL for each MUX level.
+ */
+ num_config_bits = mux_graph.num_levels();
+ break;
+ case SPICE_SRAM_SCAN_CHAIN:
+ case SPICE_SRAM_STANDALONE:
+ /* Currently we DO NOT SUPPORT THESE, given an invalid number */
+ num_config_bits = size_t(-1);
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(FILE:%s,LINE[%d])Invalid type of SRAM organization!\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ if (true == circuit_lib.mux_use_local_encoder(mux_model)) {
+ /* TODO: this is a to-do work for ReRAM-based multiplexers and FPGAs
+ * The number of states of a local decoder only depends on how many
+ * memory bits that the multiplexer will have
+ * This may NOT be correct!!!
+ */
+ return find_mux_local_decoder_addr_size(mux_graph.num_memory_bits());
+ }
+
+ return num_config_bits;
+}
+
+/**************************************************
+ * Find the number of configuration bits for
+ * a routing multiplexer
+ * Two cases are considered here.
+ * They are placed in different branches (sub-functions)
+ * in order to be easy in extending to new technology!
+ *************************************************/
+size_t find_mux_num_config_bits(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const MuxGraph& mux_graph,
+ const e_sram_orgz& sram_orgz_type) {
+ size_t num_config_bits = size_t(-1);
+
+ switch (circuit_lib.design_tech_type(mux_model)) {
+ case SPICE_MODEL_DESIGN_CMOS:
+ num_config_bits = find_cmos_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type);
+ break;
+ case SPICE_MODEL_DESIGN_RRAM:
+ num_config_bits = find_rram_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type);
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(FILE:%s,LINE[%d])Invalid design_technology of MUX(name: %s)\n",
+ __FILE__, __LINE__, circuit_lib.model_name(mux_model).c_str());
+ exit(1);
+ }
+
+ return num_config_bits;
+}
diff --git a/vpr7_x2p/vpr/SRC/device/mux_utils.h b/vpr7_x2p/vpr/SRC/device/mux_utils.h
index c61db23c8..9fa1f12ca 100644
--- a/vpr7_x2p/vpr/SRC/device/mux_utils.h
+++ b/vpr7_x2p/vpr/SRC/device/mux_utils.h
@@ -37,4 +37,13 @@ std::vector build_mux_intermediate_buffer_location_map(const CircuitLibrar
MuxLibrary convert_mux_arch_to_library(const CircuitLibrary& circuit_lib, t_llist* muxes_head);
+size_t find_mux_num_reserved_config_bits(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const MuxGraph& mux_graph);
+
+size_t find_mux_num_config_bits(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const MuxGraph& mux_graph,
+ const e_sram_orgz& sram_orgz_type);
+
#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/bitstream_context.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/bitstream_context.h
new file mode 100644
index 000000000..6ee011182
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/bitstream_context.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * This file introduces a data structure to store bitstream-related information
+ ******************************************************************************/
+#ifndef BITSTREAM_CONTEXT_H
+#define BITSTREAM_CONTEXT_H
+
+#include "vtr_vector.h"
+#include "bitstream_context_fwd.h"
+
+class BitstreamContext {
+ private: /* Internal data */
+ enum e_sram_orgz config_scheme_; /* The type of configuration protocol */
+ CircuitModelId& sram_model_; /* The memory circuit model used by the Bitstream generation */
+ size_t num_memory_bits_; /* Number of memory bits */
+ size_t num_bls_; /* Number of Bit Lines */
+ size_t num_wls_; /* Number of Word Lines */
+
+ size_t num_reserved_bls_; /* Number of reserved Bit Lines, ONLY applicable to RRAM-based FPGA */
+ size_t num_reserved_wls_; /* Number of reserved Word Lines, ONLY applicable to RRAM-based FPGA */
+ /* Unique id of a bit in the Bitstream */
+ vtr::vector bit_ids_;
+ /* Bit line address of a bit in the Bitream: ONLY applicable to memory-decoders */
+ vtr::vector bl_addr_;
+ /* Word line address of a bit in the Bitream: ONLY applicable to memory-decoders */
+ vtr::vector wl_addr_;
+ /* value of a bit in the Bitream */
+ vtr::vector bit_val_;
+};
+
+#endif
+
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/bitstream_context_fwd.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/bitstream_context_fwd.h
new file mode 100644
index 000000000..29d85580e
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/bitstream_context_fwd.h
@@ -0,0 +1,18 @@
+/**************************************************
+ * This file includes only declarations for
+ * the data structures for module managers
+ * Please refer to module_manager.h for more details
+ *************************************************/
+#ifndef MODULE_MANAGER_FWD_H
+#define MODULE_MANAGER_FWD_H
+
+#include "vtr_strong_id.h"
+
+/* Strong Ids for ModuleManager */
+struct config_bit_id_tag;
+
+typedef vtr::StrongId ConfigBitId;
+
+class BitstreamContext;
+
+#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.c
index 844eb16e3..a4c87afa8 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.c
@@ -270,7 +270,7 @@ int count_num_sram_bits_one_spice_model(t_spice_model* cur_spice_model,
case SPICE_MODEL_FF:
case SPICE_MODEL_SRAM:
case SPICE_MODEL_HARDLOGIC:
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
case SPICE_MODEL_IOPAD:
return count_num_sram_bits_one_generic_spice_model(cur_spice_model);
default:
@@ -336,7 +336,7 @@ int count_num_mode_bits_one_spice_model(t_spice_model* cur_spice_model) {
case SPICE_MODEL_FF:
case SPICE_MODEL_SRAM:
case SPICE_MODEL_HARDLOGIC:
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
case SPICE_MODEL_IOPAD:
return count_num_mode_bits_one_generic_spice_model(cur_spice_model);
default:
@@ -528,7 +528,7 @@ int count_num_reserved_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
case SPICE_MODEL_FF:
case SPICE_MODEL_SRAM:
case SPICE_MODEL_HARDLOGIC:
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
case SPICE_MODEL_IOPAD:
/* Other block, we just count the number SRAM ports defined by user */
num_reserved_conf_bits = 0;
@@ -829,7 +829,7 @@ int count_num_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
case SPICE_MODEL_FF:
case SPICE_MODEL_SRAM:
case SPICE_MODEL_HARDLOGIC:
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
case SPICE_MODEL_IOPAD:
return count_num_conf_bits_one_generic_spice_model(cur_spice_model, cur_sram_orgz_type);
default:
@@ -919,7 +919,7 @@ int count_num_reserved_conf_bit_one_interc(t_interconnect* cur_interc,
/* add configuration bits of a MUX to linked-list
* when SRAM organization type is scan-chain */
void
-add_mux_scff_conf_bits_to_llist(int mux_size,
+add_mux_ccff_conf_bits_to_llist(int mux_size,
t_sram_orgz_info* cur_sram_orgz_info,
int num_mux_sram_bits, int* mux_sram_bits,
t_spice_model* mux_spice_model) {
@@ -1134,7 +1134,7 @@ add_mux_conf_bits_to_llist(int mux_size,
switch (cur_sram_orgz_info->type) {
case SPICE_SRAM_STANDALONE:
case SPICE_SRAM_SCAN_CHAIN:
- add_mux_scff_conf_bits_to_llist(mux_size, cur_sram_orgz_info,
+ add_mux_ccff_conf_bits_to_llist(mux_size, cur_sram_orgz_info,
num_mux_sram_bits, mux_sram_bits,
mux_spice_model);
break;
@@ -1152,9 +1152,9 @@ add_mux_conf_bits_to_llist(int mux_size,
return;
}
-/* Add SCFF configutration bits to a linked list*/
+/* Add CCFF configutration bits to a linked list*/
static
-void add_sram_scff_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info,
+void add_sram_ccff_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info,
int num_sram_bits, int* sram_bits) {
int ibit, cur_mem_bit;
t_conf_bit** sram_bit = NULL;
@@ -1304,7 +1304,7 @@ add_sram_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info, int mem_index,
switch (cur_sram_orgz_info->type) {
case SPICE_SRAM_STANDALONE:
case SPICE_SRAM_SCAN_CHAIN:
- add_sram_scff_conf_bits_to_llist(cur_sram_orgz_info,
+ add_sram_ccff_conf_bits_to_llist(cur_sram_orgz_info,
num_sram_bits, sram_bits);
break;
case SPICE_SRAM_MEMORY_BANK:
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.h
index 2ce9546a5..e32bb520a 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_bitstream_utils.h
@@ -30,7 +30,7 @@ int count_num_reserved_conf_bit_one_interc(t_interconnect* cur_interc,
enum e_sram_orgz cur_sram_orgz_type);
void
-add_mux_scff_conf_bits_to_llist(int mux_size,
+add_mux_ccff_conf_bits_to_llist(int mux_size,
t_sram_orgz_info* cur_sram_orgz_info,
int num_mux_sram_bits, int* mux_sram_bits,
t_spice_model* mux_spice_model);
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mux_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mux_utils.c
index 5e031e0c3..40c60d776 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mux_utils.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_mux_utils.c
@@ -189,20 +189,20 @@ int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
/***************************************************************************************
* Find the number of inputs for a encoder with a given output size
- * Inputs
- * | | | | |
- * +-----------+
- * / \
- * / Encoder \
- * +-----------------+
- * | | | | | | | |
- * Outputs
- *
- * The outputs are assumes to be one-hot codes (at most only one '1' exist)
- * Considering this fact, there are only num_of_outputs + 1 conditions to be encoded.
- * Therefore, the number of inputs is ceil(log(num_of_outputs+1)/log(2))
- * We plus 1, which is all-zero condition for outputs
- ***************************************************************************************/
+ * Inputs
+ * | | | | |
+ * +-----------+
+ * / \
+ * / Encoder \
+ * +-----------------+
+ * | | | | | | | |
+ * Outputs
+ *
+ * The outputs are assumes to be one-hot codes (at most only one '1' exist)
+ * Considering this fact, there are only num_of_outputs + 1 conditions to be encoded.
+ * Therefore, the number of inputs is ceil(log(num_of_outputs+1)/log(2))
+ * We plus 1, which is all-zero condition for outputs
+ ****************************************************************************************/
int determine_mux_local_encoder_num_inputs(int num_outputs) {
return ceil(log(num_outputs) / log(2));
}
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp
index 66a28eff3..d39d4961a 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp
@@ -1,13 +1,15 @@
/********************************************************************
- * This file includes functions to
- * generate module/port names for Verilog
- * and SPICE netlists
+ * This file includes functions to generate module/port names for
+ * Verilog and SPICE netlists
*
* IMPORTANT: keep all the naming functions in this file to be
* generic for both Verilog and SPICE generators
********************************************************************/
#include "vtr_assert.h"
+#include "sides.h"
+#include "fpga_x2p_utils.h"
+#include "circuit_library_utils.h"
#include "fpga_x2p_naming.h"
/************************************************
@@ -17,8 +19,8 @@
* Case 1 : If there is NO intermediate buffer followed by,
* the node name will be mux_l_in
***********************************************/
-std::string generate_verilog_mux_node_name(const size_t& node_level,
- const bool& add_buffer_postfix) {
+std::string generate_mux_node_name(const size_t& node_level,
+ const bool& add_buffer_postfix) {
/* Generate the basic node_name */
std::string node_name = "mux_l" + std::to_string(node_level) + "_in";
@@ -37,10 +39,10 @@ std::string generate_verilog_mux_node_name(const size_t& node_level,
* 1. LUTs are named as _mux
* 2. MUXes are named as _size
***********************************************/
-std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib,
- const CircuitModelId& circuit_model,
- const size_t& mux_size,
- const std::string& postfix) {
+std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model,
+ const size_t& mux_size,
+ const std::string& postfix) {
std::string module_name = circuit_lib.model_name(circuit_model);
/* Check the model type and give different names */
if (SPICE_MODEL_MUX == circuit_lib.model_type(circuit_model)) {
@@ -63,11 +65,11 @@ std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib,
* Generate the module name of a branch for a
* multiplexer in Verilog format
***********************************************/
-std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
- const CircuitModelId& circuit_model,
- const size_t& mux_size,
- const size_t& branch_mux_size,
- const std::string& postfix) {
+std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model,
+ const size_t& mux_size,
+ const size_t& branch_mux_size,
+ const std::string& postfix) {
/* If the tgate spice model of this MUX is a MUX2 standard cell,
* the mux_subckt name will be the name of the standard cell
*/
@@ -78,7 +80,7 @@ std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circui
}
std::string branch_postfix = postfix + "_size" + std::to_string(branch_mux_size);
- return generate_verilog_mux_subckt_name(circuit_lib, circuit_model, mux_size, branch_postfix);
+ return generate_mux_subckt_name(circuit_lib, circuit_model, mux_size, branch_postfix);
}
/************************************************
@@ -139,3 +141,459 @@ std::string generate_memory_module_name(const CircuitLibrary& circuit_lib,
return std::string( circuit_lib.model_name(circuit_model) + "_" + circuit_lib.model_name(sram_model) + postfix );
}
+/*********************************************************************
+ * Generate the netlist name for a unique routing block
+ * It could be
+ * 1. Routing channel
+ * 2. Connection block
+ * 3. Switch block
+ * A unique block id should be given
+ *********************************************************************/
+std::string generate_routing_block_netlist_name(const std::string& prefix,
+ const size_t& block_id,
+ const std::string& postfix) {
+ return std::string( prefix + std::to_string(block_id) + postfix );
+}
+
+/*********************************************************************
+ * Generate the netlist name for a routing block with a given coordinate
+ * It could be
+ * 1. Routing channel
+ * 2. Connection block
+ * 3. Switch block
+ *********************************************************************/
+std::string generate_routing_block_netlist_name(const std::string& prefix,
+ const vtr::Point& coordinate,
+ const std::string& postfix) {
+ return std::string( prefix + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + postfix );
+}
+
+/*********************************************************************
+ * Generate the module name for a unique routing channel
+ *********************************************************************/
+std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
+ const size_t& block_id) {
+ /* Channel must be either CHANX or CHANY */
+ VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
+
+ /* Create a map between chan_type and module_prefix */
+ std::map module_prefix_map;
+ /* TODO: use a constexpr string to replace the fixed name? */
+ module_prefix_map[CHANX] = std::string("chanx");
+ module_prefix_map[CHANY] = std::string("chany");
+
+ return std::string( module_prefix_map[chan_type] + std::string("_") + std::to_string(block_id) + std::string("_") );
+}
+
+/*********************************************************************
+ * Generate the module name for a routing channel with a given coordinate
+ *********************************************************************/
+std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
+ const vtr::Point& coordinate) {
+ /* Channel must be either CHANX or CHANY */
+ VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
+
+ /* Create a map between chan_type and module_prefix */
+ std::map module_prefix_map;
+ /* TODO: use a constexpr string to replace the fixed name? */
+ module_prefix_map[CHANX] = std::string("chanx");
+ module_prefix_map[CHANY] = std::string("chany");
+
+ return std::string( module_prefix_map[chan_type] + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + std::string("_") );
+}
+
+/*********************************************************************
+ * Generate the port name for a routing track with a given coordinate
+ * and port direction
+ *********************************************************************/
+std::string generate_routing_track_port_name(const t_rr_type& chan_type,
+ const vtr::Point& coordinate,
+ const size_t& track_id,
+ const PORTS& port_direction) {
+ /* Channel must be either CHANX or CHANY */
+ VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
+
+ /* Create a map between chan_type and module_prefix */
+ std::map module_prefix_map;
+ /* TODO: use a constexpr string to replace the fixed name? */
+ module_prefix_map[CHANX] = std::string("chanx");
+ module_prefix_map[CHANY] = std::string("chany");
+
+ std::string port_name = module_prefix_map[chan_type];
+ port_name += std::string("_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("__"));
+
+ switch (port_direction) {
+ case OUT_PORT:
+ port_name += std::string("out_");
+ break;
+ case IN_PORT:
+ port_name += std::string("in_");
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File: %s [LINE%d]) Invalid direction of chan_rr_node!\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ /* Add the track id to the port name */
+ port_name += std::to_string(track_id) + std::string("_");
+
+ return port_name;
+}
+
+/*********************************************************************
+ * Generate the module name for a switch block with a given coordinate
+ *********************************************************************/
+std::string generate_switch_block_module_name(const vtr::Point& coordinate) {
+ return std::string( "sb_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") );
+}
+
+/*********************************************************************
+ * Generate the port name for a Grid
+ * TODO: add more comments about why we need different names for
+ * top and non-top netlists
+ *********************************************************************/
+std::string generate_grid_port_name(const vtr::Point& coordinate,
+ const size_t& height,
+ const e_side& side,
+ const size_t& pin_id,
+ const bool& for_top_netlist) {
+ if (true == for_top_netlist) {
+ std::string port_name = std::string("grid_");
+ port_name += std::to_string(coordinate.x());
+ port_name += std::string("__");
+ port_name += std::to_string(coordinate.y());
+ port_name += std::string("__pin_");
+ port_name += std::to_string(height);
+ port_name += std::string("__");
+ port_name += std::to_string(size_t(side));
+ port_name += std::string("__");
+ port_name += std::to_string(pin_id);
+ port_name += std::string("_");
+ return port_name;
+ }
+ /* For non-top netlist */
+ VTR_ASSERT( false == for_top_netlist );
+ Side side_manager(side);
+ std::string port_name = std::string(side_manager.to_string());
+ port_name += std::string("_height_");
+ port_name += std::to_string(height);
+ port_name += std::string("__pin_");
+ port_name += std::to_string(pin_id);
+ port_name += std::string("_");
+ return port_name;
+}
+
+
+/*********************************************************************
+ * Generate the port name for a reserved sram port, i.e., BLB/WL port
+ * When port_type is BLB, a string denoting to the reserved BLB port is generated
+ * When port_type is WL, a string denoting to the reserved WL port is generated
+ *
+ * DO NOT put any SRAM organization check codes HERE!!!
+ * Even though the reserved BLB/WL ports are used by RRAM-based FPGA only,
+ * try to keep this function does simple job.
+ * Check codes should be added outside, when print the ports to files!!!
+ *********************************************************************/
+std::string generate_reserved_sram_port_name(const e_spice_model_port_type& port_type) {
+ VTR_ASSERT( (port_type == SPICE_MODEL_PORT_BLB) || (port_type == SPICE_MODEL_PORT_WL) );
+
+ if (SPICE_MODEL_PORT_BLB == port_type) {
+ return std::string("reserved_blb");
+ }
+ return std::string("reserved_wl");
+}
+
+/*********************************************************************
+ * Generate the port name for a sram port, used for formal verification
+ * The port name is named after the cell name of SRAM in circuit library
+ *********************************************************************/
+std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model) {
+ std::string port_name = circuit_lib.model_name(sram_model) + std::string("_out_fm");
+
+ return port_name;
+}
+
+/*********************************************************************
+ * Generate the head port name of a configuration chain
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_configuration_chain_head_name() {
+ return std::string("ccff_head");
+}
+
+/*********************************************************************
+ * Generate the tail port name of a configuration chain
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_configuration_chain_tail_name() {
+ return std::string("ccff_tail");
+}
+
+/*********************************************************************
+ * Generate the memory output port name of a configuration chain
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_configuration_chain_data_out_name() {
+ return std::string("mem_out");
+}
+
+/*********************************************************************
+ * Generate the inverted memory output port name of a configuration chain
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_configuration_chain_inverted_data_out_name() {
+ return std::string("mem_outb");
+}
+
+/*********************************************************************
+ * Generate the addr port (input) for a local decoder of a multiplexer
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_mux_local_decoder_addr_port_name() {
+ return std::string("addr");
+}
+
+/*********************************************************************
+ * Generate the data port (output) for a local decoder of a multiplexer
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_mux_local_decoder_data_port_name() {
+ return std::string("data");
+}
+
+/*********************************************************************
+ * Generate the inverted data port (output) for a local decoder of a multiplexer
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_mux_local_decoder_data_inv_port_name() {
+ return std::string("data_inv");
+}
+
+/*********************************************************************
+ * Generate the port name of a local configuration bus
+ * TODO: This could be replaced as a constexpr string
+ *********************************************************************/
+std::string generate_local_config_bus_port_name() {
+ return std::string("config_bus");
+}
+
+/*********************************************************************
+ * Generate the port name for a regular sram port which appears in the
+ * port list of a module
+ * The port name is named after the cell name of SRAM in circuit library
+ *********************************************************************/
+std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const e_sram_orgz& sram_orgz_type,
+ const e_spice_model_port_type& port_type) {
+ std::string port_name = circuit_lib.model_name(sram_model) + std::string("_");
+
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_STANDALONE: {
+ /* Two types of ports are available:
+ * (1) Regular output of a SRAM, enabled by port type of INPUT
+ * (2) Inverted output of a SRAM, enabled by port type of OUTPUT
+ */
+ if (SPICE_MODEL_PORT_INPUT == port_type) {
+ port_name += std::string("out");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
+ port_name += std::string("outb");
+ }
+ break;
+ }
+ case SPICE_SRAM_SCAN_CHAIN:
+ /* Two types of ports are available:
+ * (1) Head of a chain of Configuration-chain Flip-Flops (CCFFs), enabled by port type of INPUT
+ * (2) Tail of a chian of Configuration-chain Flip-flops (CCFFs), enabled by port type of OUTPUT
+ * +------+ +------+ +------+
+ * Head --->| CCFF |--->| CCFF |--->| CCFF |---> Tail
+ * +------+ +------+ +------+
+ */
+ if (SPICE_MODEL_PORT_INPUT == port_type) {
+ port_name += std::string("ccff_head");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
+ port_name += std::string("ccff_tail");
+ }
+ break;
+ case SPICE_SRAM_MEMORY_BANK:
+ /* Four types of ports are available:
+ * (1) Bit Lines (BLs) of a SRAM cell, enabled by port type of BL
+ * (2) Word Lines (WLs) of a SRAM cell, enabled by port type of WL
+ * (3) Inverted Bit Lines (BLBs) of a SRAM cell, enabled by port type of BLB
+ * (4) Inverted Word Lines (WLBs) of a SRAM cell, enabled by port type of WLB
+ *
+ * BL BLB WL WLB BL BLB WL WLB BL BLB WL WLB
+ * [0] [0] [0] [0] [1] [1] [1] [1] [i] [i] [i] [i]
+ * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
+ * | | | | | | | | | | | |
+ * +----------+ +----------+ +----------+
+ * | SRAM | | SRAM | ... | SRAM |
+ * +----------+ +----------+ +----------+
+ */
+ if (SPICE_MODEL_PORT_BL == port_type) {
+ port_name += std::string("bl");
+ } else if (SPICE_MODEL_PORT_WL == port_type) {
+ port_name += std::string("wl");
+ } else if (SPICE_MODEL_PORT_BLB == port_type) {
+ port_name += std::string("blb");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_WLB == port_type );
+ port_name += std::string("wlb");
+ }
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ return port_name;
+}
+
+/*********************************************************************
+ * Generate the port name for a regular sram port which is an internal
+ * wire of a module
+ * The port name is named after the cell name of SRAM in circuit library
+ *********************************************************************/
+std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const e_sram_orgz& sram_orgz_type,
+ const e_spice_model_port_type& port_type) {
+ std::string port_name = circuit_lib.model_name(sram_model) + std::string("_");
+
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_STANDALONE: {
+ /* Two types of ports are available:
+ * (1) Regular output of a SRAM, enabled by port type of INPUT
+ * (2) Inverted output of a SRAM, enabled by port type of OUTPUT
+ */
+ if (SPICE_MODEL_PORT_INPUT == port_type) {
+ port_name += std::string("out_local_bus");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
+ port_name += std::string("outb_local_bus");
+ }
+ break;
+ }
+ case SPICE_SRAM_SCAN_CHAIN:
+ /* Three types of ports are available:
+ * (1) Input of Configuration-chain Flip-Flops (CCFFs), enabled by port type of INPUT
+ * (2) Output of a chian of Configuration-chain Flip-flops (CCFFs), enabled by port type of OUTPUT
+ * (2) Inverted output of a chian of Configuration-chain Flip-flops (CCFFs), enabled by port type of INOUT
+ * +------+ +------+ +------+
+ * Head --->| CCFF |--->| CCFF |--->| CCFF |---> Tail
+ * +------+ +------+ +------+
+ */
+ if (SPICE_MODEL_PORT_INPUT == port_type) {
+ port_name += std::string("ccff_in_local_bus");
+ } else if ( SPICE_MODEL_PORT_OUTPUT == port_type ) {
+ port_name += std::string("ccff_out_local_bus");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_INOUT == port_type );
+ port_name += std::string("ccff_outb_local_bus");
+ }
+ break;
+ case SPICE_SRAM_MEMORY_BANK: {
+ /* Two types of ports are available:
+ * (1) Regular output of a SRAM, enabled by port type of INPUT
+ * (2) Inverted output of a SRAM, enabled by port type of OUTPUT
+ */
+ if (SPICE_MODEL_PORT_INPUT == port_type) {
+ port_name += std::string("out_local_bus");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
+ port_name += std::string("outb_local_bus");
+ }
+ break;
+ }
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ return port_name;
+}
+
+/*********************************************************************
+ * Generate the port name for the input bus of a routing multiplexer
+ * This is very useful in Verilog code generation where the inputs of
+ * a routing multiplexer may come from different ports.
+ * On the other side, the datapath input of a routing multiplexer
+ * is defined as a bus port.
+ * Therefore, to interface, a bus port is required, and this function
+ * give a name to the bus port
+ * To keep the bus port name unique to each multiplexer we will instance,
+ * a mux_instance_id should be provided by user
+ *********************************************************************/
+std::string generate_mux_input_bus_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const size_t& mux_size,
+ const size_t& mux_instance_id) {
+ std::string postfix = std::string("_") + std::to_string(mux_instance_id) + std::string("_inbus");
+ return generate_mux_subckt_name(circuit_lib, mux_model, mux_size, postfix);
+}
+
+/*********************************************************************
+ * Generate the name of a bus port which is wired to the configuration
+ * ports of a routing multiplexer
+ * This port is supposed to be used locally inside a Verilog/SPICE module
+ *********************************************************************/
+std::string generate_mux_config_bus_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const size_t& mux_size,
+ const size_t& bus_id,
+ const bool& inverted) {
+ std::string postfix = std::string("_configbus") + std::to_string(bus_id);
+ /* Add a bar to the end of the name for inverted bus ports */
+ if (true == inverted) {
+ postfix += std::string("_b");
+ }
+
+ return generate_mux_subckt_name(circuit_lib, mux_model, mux_size, postfix);
+}
+
+/*********************************************************************
+ * Generate the port name for a SRAM port of a circuit
+ * This name is used for local wires that connecting SRAM ports
+ * of a circuit model inside a Verilog/SPICE module
+ * Note that the SRAM ports share the same naming
+ * convention regardless of their configuration style
+ *********************************************************************/
+std::string generate_local_sram_port_name(const std::string& port_prefix,
+ const size_t& instance_id,
+ const e_spice_model_port_type& port_type) {
+ std::string port_name = port_prefix + std::string("_") + std::to_string(instance_id) + std::string("_");
+
+ if (SPICE_MODEL_PORT_INPUT == port_type) {
+ port_name += std::string("out");
+ } else {
+ VTR_ASSERT( SPICE_MODEL_PORT_OUTPUT == port_type );
+ port_name += std::string("outb");
+ }
+
+ return port_name;
+}
+
+/*********************************************************************
+ * Generate the port name for a SRAM port of a routing multiplexer
+ * This name is used for local wires that connecting SRAM ports
+ * of routing multiplexers inside a Verilog/SPICE module
+ * Note that the SRAM ports of routing multiplexers share the same naming
+ * convention regardless of their configuration style
+ **********************************************************************/
+std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const size_t& mux_size,
+ const size_t& mux_instance_id,
+ const e_spice_model_port_type& port_type) {
+ std::string prefix = generate_mux_subckt_name(circuit_lib, mux_model, mux_size, std::string());
+ return generate_local_sram_port_name(prefix, mux_instance_id, port_type);
+}
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h
index dbf6abff5..6d7f9c88c 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h
@@ -9,21 +9,23 @@
#include
+#include "vtr_geometry.h"
#include "circuit_library.h"
+#include "vpr_types.h"
-std::string generate_verilog_mux_node_name(const size_t& node_level,
- const bool& add_buffer_postfix);
+std::string generate_mux_node_name(const size_t& node_level,
+ const bool& add_buffer_postfix);
-std::string generate_verilog_mux_subckt_name(const CircuitLibrary& circuit_lib,
- const CircuitModelId& circuit_model,
- const size_t& mux_size,
- const std::string& posfix) ;
+std::string generate_mux_subckt_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model,
+ const size_t& mux_size,
+ const std::string& posfix) ;
-std::string generate_verilog_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
- const CircuitModelId& circuit_model,
- const size_t& mux_size,
- const size_t& branch_mux_size,
- const std::string& posfix);
+std::string generate_mux_branch_subckt_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& circuit_model,
+ const size_t& mux_size,
+ const size_t& branch_mux_size,
+ const std::string& posfix);
std::string generate_mux_local_decoder_subckt_name(const size_t& addr_size,
const size_t& data_size);
@@ -38,4 +40,83 @@ std::string generate_memory_module_name(const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const std::string& postfix);
+std::string generate_routing_block_netlist_name(const std::string& prefix,
+ const size_t& block_id,
+ const std::string& postfix);
+
+std::string generate_routing_block_netlist_name(const std::string& prefix,
+ const vtr::Point& block_id,
+ const std::string& postfix);
+
+std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
+ const size_t& block_id);
+
+std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
+ const vtr::Point& coordinate);
+
+std::string generate_routing_track_port_name(const t_rr_type& chan_type,
+ const vtr::Point& coordinate,
+ const size_t& track_id,
+ const PORTS& port_direction);
+
+std::string generate_switch_block_module_name(const vtr::Point& coordinate);
+
+std::string generate_grid_port_name(const vtr::Point& coordinate,
+ const size_t& height,
+ const e_side& side,
+ const size_t& pin_id,
+ const bool& for_top_netlist);
+
+std::string generate_reserved_sram_port_name(const e_spice_model_port_type& port_type);
+
+std::string generate_formal_verification_sram_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model);
+
+std::string generate_configuration_chain_head_name();
+
+std::string generate_configuration_chain_tail_name();
+
+std::string generate_configuration_chain_data_out_name();
+
+std::string generate_configuration_chain_inverted_data_out_name();
+
+std::string generate_mux_local_decoder_addr_port_name();
+
+std::string generate_mux_local_decoder_data_port_name();
+
+std::string generate_mux_local_decoder_data_inv_port_name();
+
+std::string generate_local_config_bus_port_name();
+
+std::string generate_sram_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const e_sram_orgz& sram_orgz_type,
+ const e_spice_model_port_type& port_type);
+
+std::string generate_sram_local_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const e_sram_orgz& sram_orgz_type,
+ const e_spice_model_port_type& port_type);
+
+std::string generate_mux_input_bus_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const size_t& mux_size,
+ const size_t& mux_instance_id);
+
+std::string generate_mux_config_bus_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const size_t& mux_size,
+ const size_t& bus_id,
+ const bool& inverted);
+
+std::string generate_local_sram_port_name(const std::string& port_prefix,
+ const size_t& instance_id,
+ const e_spice_model_port_type& port_type);
+
+std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib,
+ const CircuitModelId& mux_model,
+ const size_t& mux_size,
+ const size_t& mux_instance_id,
+ const e_spice_model_port_type& port_type);
+
#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c
index 90690e48d..d88a27658 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c
@@ -344,7 +344,7 @@ void init_and_check_one_sram_inf_orgz(t_sram_inf_orgz* cur_sram_inf_orgz,
break;
case SPICE_SRAM_SCAN_CHAIN:
vpr_printf(TIO_MESSAGE_INFO, "INFO: Checking if SRAM spice model fit scan-chain organization...\n");
- if (SPICE_MODEL_SCFF != cur_sram_inf_orgz->spice_model->type) {
+ if (SPICE_MODEL_CCFF != cur_sram_inf_orgz->spice_model->type) {
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,LINE[%d]) Scan-chain SRAM organization requires a SPICE model(type=sff)!\n",
__FILE__, __LINE__);
exit(1);
@@ -548,7 +548,6 @@ void init_check_arch_spice_models(t_arch* arch,
get_default_spice_model(SPICE_MODEL_WIRE,
arch->spice->num_spice_model,
arch->spice->spice_models);
- continue;
} else {
arch->Directs[i].spice_model =
find_name_matched_spice_model(arch->Directs[i].spice_model_name,
@@ -562,7 +561,7 @@ void init_check_arch_spice_models(t_arch* arch,
arch->Directs[i].spice_model_name,
arch->Directs[i].name);
exit(1);
- } else if (SPICE_MODEL_CHAN_WIRE != arch->Directs[i].spice_model->type) {
+ } else if (SPICE_MODEL_WIRE != arch->Directs[i].spice_model->type) {
vpr_printf(TIO_MESSAGE_ERROR, "(FILE:%s, LINE[%d])Invalid SPICE model(%s) type of CLB to CLB Direct Connection (name=%s)! Should be chan_wire!\n",
__FILE__ , __LINE__,
arch->Directs[i].spice_model_name,
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c
index bdc3bbfbb..9f73bc651 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c
@@ -1094,7 +1094,7 @@ char* generate_string_spice_model_type(enum e_spice_model_type spice_model_type)
case SPICE_MODEL_IOPAD:
ret = "iopad";
break;
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
ret = "Scan-chain Flip-flop";
break;
default:
@@ -2220,7 +2220,7 @@ void check_sram_spice_model_ports(t_spice_model* cur_spice_model,
}
void check_ff_spice_model_ports(t_spice_model* cur_spice_model,
- boolean is_scff) {
+ boolean is_ccff) {
int iport;
int num_input_ports;
t_spice_model_port** input_ports = NULL;
@@ -2232,22 +2232,22 @@ void check_ff_spice_model_ports(t_spice_model* cur_spice_model,
int num_err = 0;
/* Check the type of SPICE model */
- if (FALSE == is_scff) {
+ if (FALSE == is_ccff) {
assert(SPICE_MODEL_FF == cur_spice_model->type);
} else {
- assert(SPICE_MODEL_SCFF == cur_spice_model->type);
+ assert(SPICE_MODEL_CCFF == cur_spice_model->type);
}
/* Check if we have D, Set and Reset */
input_ports = find_spice_model_ports(cur_spice_model, SPICE_MODEL_PORT_INPUT, &num_input_ports, FALSE);
- if (TRUE == is_scff) {
+ if (TRUE == is_ccff) {
if (1 > num_input_ports) {
- vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) SCFF SPICE MODEL should at least have an input port!\n",
+ vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) CCFF SPICE MODEL should at least have an input port!\n",
__FILE__, __LINE__);
num_err++;
}
for (iport = 0; iport < num_input_ports; iport++) {
if (1 != input_ports[iport]->size) {
- vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) SCFF SPICE MODEL: each input port with size 1!\n",
+ vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) CCFF SPICE MODEL: each input port with size 1!\n",
__FILE__, __LINE__);
num_err++;
}
@@ -2269,20 +2269,20 @@ void check_ff_spice_model_ports(t_spice_model* cur_spice_model,
/* Check if we have clock */
clock_ports = find_spice_model_ports(cur_spice_model, SPICE_MODEL_PORT_CLOCK, &num_clock_ports, FALSE);
if (1 > num_clock_ports) {
- vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) [FF|SCFF] SPICE MODEL should have at least 1 clock port!\n",
+ vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) [FF|CCFF] SPICE MODEL should have at least 1 clock port!\n",
__FILE__, __LINE__);
num_err++;
}
for (iport = 0; iport < num_clock_ports; iport++) {
if (1 != clock_ports[iport]->size) {
- vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) [FF|SCFF] SPICE MODEL: 1 clock port with size 1!\n",
+ vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) [FF|CCFF] SPICE MODEL: 1 clock port with size 1!\n",
__FILE__, __LINE__);
num_err++;
}
}
/* Check if we have output */
output_ports = find_spice_model_ports(cur_spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_ports, TRUE);
- if (FALSE == is_scff) {
+ if (FALSE == is_ccff) {
if (1 != output_ports[0]->size) {
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) FF SPICE MODEL: each output port with size 1!\n",
__FILE__, __LINE__);
@@ -2290,12 +2290,12 @@ void check_ff_spice_model_ports(t_spice_model* cur_spice_model,
}
} else {
if (2 != num_output_ports) {
- vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) SCFF SPICE MODEL should have 2 output ports!\n",
+ vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) CCFF SPICE MODEL should have 2 output ports!\n",
__FILE__, __LINE__);
num_err++;
for (iport = 0; iport < num_output_ports; iport++) {
if (1 != output_ports[iport]->size) {
- vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) SCFF SPICE MODEL: the output port (%s) should have a size of 1!\n",
+ vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d]) CCFF SPICE MODEL: the output port (%s) should have a size of 1!\n",
__FILE__, __LINE__, output_ports[iport]->prefix);
num_err++;
}
@@ -2462,11 +2462,11 @@ void free_one_mem_bank_info(t_mem_bank_info* mem_bank_info) {
return;
}
-t_scff_info* alloc_one_scff_info() {
- return (t_scff_info*)my_malloc(sizeof(t_scff_info));
+t_ccff_info* alloc_one_ccff_info() {
+ return (t_ccff_info*)my_malloc(sizeof(t_ccff_info));
}
-void free_one_scff_info(t_scff_info* scff_info) {
+void free_one_ccff_info(t_ccff_info* ccff_info) {
return;
}
@@ -2501,23 +2501,23 @@ void update_mem_bank_info_num_mem_bit(t_mem_bank_info* cur_mem_bank_info,
return;
}
-void init_scff_info(t_scff_info* cur_scff_info,
+void init_ccff_info(t_ccff_info* cur_ccff_info,
t_spice_model* cur_mem_model) {
- assert(NULL != cur_scff_info);
+ assert(NULL != cur_ccff_info);
assert(NULL != cur_mem_model);
- cur_scff_info->mem_model = cur_mem_model;
- cur_scff_info->num_mem_bit = 0;
- cur_scff_info->num_scff = 0;
+ cur_ccff_info->mem_model = cur_mem_model;
+ cur_ccff_info->num_mem_bit = 0;
+ cur_ccff_info->num_ccff = 0;
return;
}
-void update_scff_info_num_mem_bit(t_scff_info* cur_scff_info,
+void update_ccff_info_num_mem_bit(t_ccff_info* cur_ccff_info,
int num_mem_bit) {
- assert(NULL != cur_scff_info);
+ assert(NULL != cur_ccff_info);
- cur_scff_info->num_mem_bit = num_mem_bit;
+ cur_ccff_info->num_mem_bit = num_mem_bit;
return;
}
@@ -2573,8 +2573,8 @@ void init_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
num_bl_per_sram, num_wl_per_sram);
break;
case SPICE_SRAM_SCAN_CHAIN:
- cur_sram_orgz_info->scff_info = alloc_one_scff_info();
- init_scff_info(cur_sram_orgz_info->scff_info, cur_mem_model);
+ cur_sram_orgz_info->ccff_info = alloc_one_ccff_info();
+ init_ccff_info(cur_sram_orgz_info->ccff_info, cur_mem_model);
break;
case SPICE_SRAM_STANDALONE:
cur_sram_orgz_info->standalone_sram_info = alloc_one_standalone_sram_info();
@@ -2624,7 +2624,7 @@ void free_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
free_one_mem_bank_info(cur_sram_orgz_info->mem_bank_info);
break;
case SPICE_SRAM_SCAN_CHAIN:
- free_one_scff_info(cur_sram_orgz_info->scff_info);
+ free_one_ccff_info(cur_sram_orgz_info->ccff_info);
break;
case SPICE_SRAM_STANDALONE:
free_one_standalone_sram_info(cur_sram_orgz_info->standalone_sram_info);
@@ -2831,7 +2831,7 @@ int get_sram_orgz_info_num_mem_bit(t_sram_orgz_info* cur_sram_orgz_info) {
case SPICE_SRAM_STANDALONE:
return cur_sram_orgz_info->standalone_sram_info->num_mem_bit;
case SPICE_SRAM_SCAN_CHAIN:
- return cur_sram_orgz_info->scff_info->num_mem_bit;
+ return cur_sram_orgz_info->ccff_info->num_mem_bit;
case SPICE_SRAM_MEMORY_BANK:
return cur_sram_orgz_info->mem_bank_info->num_mem_bit;
default:
@@ -2854,7 +2854,7 @@ void update_sram_orgz_info_num_mem_bit(t_sram_orgz_info* cur_sram_orgz_info,
update_standalone_sram_info_num_mem_bit(cur_sram_orgz_info->standalone_sram_info, new_num_mem_bit);
break;
case SPICE_SRAM_SCAN_CHAIN:
- update_scff_info_num_mem_bit(cur_sram_orgz_info->scff_info, new_num_mem_bit);
+ update_ccff_info_num_mem_bit(cur_sram_orgz_info->ccff_info, new_num_mem_bit);
break;
case SPICE_SRAM_MEMORY_BANK:
update_mem_bank_info_num_mem_bit(cur_sram_orgz_info->mem_bank_info, new_num_mem_bit);
@@ -2903,7 +2903,7 @@ void get_sram_orgz_info_mem_model(t_sram_orgz_info* cur_sram_orgz_info,
(*mem_model_ptr) = cur_sram_orgz_info->standalone_sram_info->mem_model;
break;
case SPICE_SRAM_SCAN_CHAIN:
- (*mem_model_ptr) = cur_sram_orgz_info->scff_info->mem_model;
+ (*mem_model_ptr) = cur_sram_orgz_info->ccff_info->mem_model;
break;
case SPICE_SRAM_MEMORY_BANK:
(*mem_model_ptr) = cur_sram_orgz_info->mem_bank_info->mem_model;
@@ -2929,7 +2929,7 @@ void update_sram_orgz_info_mem_model(t_sram_orgz_info* cur_sram_orgz_info,
cur_sram_orgz_info->standalone_sram_info->mem_model = cur_mem_model;
break;
case SPICE_SRAM_SCAN_CHAIN:
- cur_sram_orgz_info->scff_info->mem_model = cur_mem_model;
+ cur_sram_orgz_info->ccff_info->mem_model = cur_mem_model;
break;
case SPICE_SRAM_MEMORY_BANK:
cur_sram_orgz_info->mem_bank_info->mem_model = cur_mem_model;
@@ -3179,6 +3179,10 @@ void config_circuit_models_sram_port_to_default_sram_model(CircuitLibrary& circu
}
}
}
+ /* TODO: this should be done right after XML parsing!!!
+ * Rebuild the submodels for circuit_library, because we have created links for ports
+ */
+ circuit_lib.build_model_links();
}
void determine_sb_port_coordinator(t_sb cur_sb_info, int side,
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h
index 8a5a0a9e4..114d2d604 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h
@@ -235,7 +235,7 @@ void check_sram_spice_model_ports(t_spice_model* cur_spice_model,
boolean include_bl_wl);
void check_ff_spice_model_ports(t_spice_model* cur_spice_model,
- boolean is_scff);
+ boolean is_ccff);
/* Functions to manipulate t_conf_bit and t_conf_bit_info */
void free_conf_bit(t_conf_bit* conf_bit);
@@ -270,9 +270,9 @@ t_mem_bank_info* alloc_one_mem_bank_info();
void free_one_mem_bank_info(t_mem_bank_info* mem_bank_info);
-t_scff_info* alloc_one_scff_info();
+t_ccff_info* alloc_one_ccff_info();
-void free_one_scff_info(t_scff_info* scff_info);
+void free_one_ccff_info(t_ccff_info* ccff_info);
t_standalone_sram_info* alloc_one_standalone_sram_info();
@@ -299,10 +299,10 @@ void get_sram_orgz_info_reserved_blwl(t_sram_orgz_info* cur_sram_orgz_info,
void update_mem_bank_info_num_mem_bit(t_mem_bank_info* cur_mem_bank_info,
int num_mem_bit);
-void init_scff_info(t_scff_info* cur_scff_info,
+void init_ccff_info(t_ccff_info* cur_ccff_info,
t_spice_model* cur_mem_model);
-void update_scff_info_num_mem_bit(t_scff_info* cur_scff_info,
+void update_ccff_info_num_mem_bit(t_ccff_info* cur_ccff_info,
int num_mem_bit);
void init_standalone_sram_info(t_standalone_sram_info* cur_standalone_sram_info,
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp
index 342524903..8e1848932 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/link_arch_circuit_lib.cpp
@@ -114,7 +114,7 @@ CircuitModelId link_circuit_model_by_name_and_type(const char* circuit_model_nam
/************************************************************************
* Link circuit model to the SRAM organization
* Case 1: standalone organization required a SRAM circuit model
- * Case 1: scan-chain organization required a SCFF circuit model
+ * Case 1: configuration-chain organization required a CCFF circuit model
* Case 1: memory-bank organization required a SRAM circuit model
***********************************************************************/
static
@@ -128,9 +128,9 @@ void link_one_sram_inf_orgz(t_sram_inf_orgz* cur_sram_inf_orgz,
/* Check the type of SRAM_Ciruit_MODEL required by different sram organization */
/* check SRAM ports
* Checker for circuit models used by the SRAM organization
- * either SRAMs or SCFFs
- * 1. It will check the basic port required for SRAMs and SCFFs
- * 2. It will check any special ports required for SRAMs and SCFFs
+ * either SRAMs or CCFFs
+ * 1. It will check the basic port required for SRAMs and CCFFs
+ * 2. It will check any special ports required for SRAMs and CCFFs
*/
switch (cur_sram_inf_orgz->type) {
case SPICE_SRAM_STANDALONE:
@@ -145,8 +145,8 @@ void link_one_sram_inf_orgz(t_sram_inf_orgz* cur_sram_inf_orgz,
break;
case SPICE_SRAM_SCAN_CHAIN:
/* check Scan-chain Flip-flop ports */
- cur_sram_inf_orgz->circuit_model = link_circuit_model_by_name_and_type(cur_sram_inf_orgz->spice_model_name, circuit_lib, SPICE_MODEL_SCFF);
- check_scff_circuit_model_ports(circuit_lib, cur_sram_inf_orgz->circuit_model);
+ cur_sram_inf_orgz->circuit_model = link_circuit_model_by_name_and_type(cur_sram_inf_orgz->spice_model_name, circuit_lib, SPICE_MODEL_CCFF);
+ check_ccff_circuit_model_ports(circuit_lib, cur_sram_inf_orgz->circuit_model);
break;
case SPICE_SRAM_LOCAL_ENCODER:
/* Wipe out LOCAL ENCODER, it is not supported here ! */
@@ -482,7 +482,7 @@ void link_circuit_library_to_arch(t_arch* arch,
/* Check Circuit models first*/
VTR_ASSERT_SAFE( (NULL != arch) && (NULL != arch->spice) );
- /* 1. Link the spice model defined in pb_types and routing switches */
+ /* 1. Link the circuit model defined in pb_types and routing switches */
/* Step A: Check routing switches, connection blocks*/
if (0 >= arch->num_cb_switch) {
vpr_printf(TIO_MESSAGE_ERROR,
@@ -500,7 +500,7 @@ void link_circuit_library_to_arch(t_arch* arch,
__FILE__, __LINE__, arch->cb_switches[i].spice_model_name, arch->cb_switches[i].name);
exit(1);
}
- /* Check the spice model structure is matched with the structure in switch_inf */
+ /* Check the circuit model structure is matched with the structure in switch_inf */
if (0 < check_circuit_model_structure_match_switch_inf(arch->cb_switches[i], arch->spice->circuit_lib)) {
exit(1);
}
@@ -544,7 +544,7 @@ void link_circuit_library_to_arch(t_arch* arch,
/* Step C: Find SRAM Model*/
link_sram_inf(&(arch->sram_inf), arch->spice->circuit_lib);
- /* Step D: Find the segment spice_model*/
+ /* Step D: Find the segment circuit_model*/
for (int i = 0; i < arch->num_segments; i++) {
arch->Segments[i].circuit_model = link_circuit_model_by_name_and_type(arch->Segments[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_CHAN_WIRE);
@@ -562,7 +562,7 @@ void link_circuit_library_to_arch(t_arch* arch,
for (int i = 0; i < arch->num_directs; i++) {
arch->Directs[i].circuit_model = link_circuit_model_by_name_and_type(arch->Directs[i].spice_model_name,
arch->spice->circuit_lib, SPICE_MODEL_WIRE);
- /* Check SPICE model type */
+ /* Check Circuit model type */
if (CircuitModelId::INVALID() == arch->Directs[i].circuit_model) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s, LINE[%d])Invalid circuit model name(%s) of CLB to CLB Direct Connection (name=%s) is undefined in circuit models!\n",
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp
index 8743b2ebb..2a89a748c 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp
@@ -106,6 +106,13 @@ bool ModuleManager::port_is_register(const ModuleId& module, const ModulePortId&
return port_is_register_[module][port];
}
+/* Return the pre-processing flag of a port */
+std::string ModuleManager::port_preproc_flag(const ModuleId& module, const ModulePortId& port) const {
+ /* validate both module id and port id*/
+ VTR_ASSERT(valid_module_port_id(module, port));
+ return port_preproc_flags_[module][port];
+}
+
/******************************************************************************
* Public Mutators
******************************************************************************/
@@ -131,6 +138,7 @@ ModuleId ModuleManager::add_module(const std::string& name) {
ports_.emplace_back();
port_types_.emplace_back();
port_is_register_.emplace_back();
+ port_preproc_flags_.emplace_back();
/* Register in the name-to-id map */
name_id_map_[name] = module;
@@ -155,6 +163,7 @@ ModulePortId ModuleManager::add_port(const ModuleId& module,
ports_[module].push_back(port_info);
port_types_[module].push_back(port_type);
port_is_register_[module].push_back(false);
+ port_preproc_flags_[module].emplace_back(); /* Create an empty string for the pre-processing flags */
/* Update fast look-up for port */
port_lookup_[module][port_type].push_back(port);
@@ -178,6 +187,13 @@ void ModuleManager::set_port_is_register(const ModuleId& module, const std::stri
port_is_register_[module][port] = is_register;
}
+/* Set the preprocessing flag for a port */
+void ModuleManager::set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag) {
+ /* Must find something, otherwise drop an error */
+ VTR_ASSERT(valid_module_port_id(module, port));
+ port_preproc_flags_[module][port] = preproc_flag;
+}
+
/* Add a child module to a parent module */
void ModuleManager::add_child_module(const ModuleId& parent_module, const ModuleId& child_module) {
/* Validate the id of both parent and child modules */
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h
index 5a9fcd507..297046059 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h
@@ -48,6 +48,8 @@ class ModuleManager {
size_t num_instance(const ModuleId& parent_module, const ModuleId& child_module) const;
/* Find if a port is register */
bool port_is_register(const ModuleId& module, const ModulePortId& port) const;
+ /* Return the pre-processing flag of a port */
+ std::string port_preproc_flag(const ModuleId& module, const ModulePortId& port) const;
public: /* Public mutators */
/* Add a module */
ModuleId add_module(const std::string& name);
@@ -58,11 +60,14 @@ class ModuleManager {
void set_module_name(const ModuleId& module, const std::string& name);
/* Set a port to be a register */
void set_port_is_register(const ModuleId& module, const std::string& port_name, const bool& is_register);
+ /* Set the preprocessing flag for a port */
+ void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port, const std::string& preproc_flag);
/* Add a child module to a parent module */
void add_child_module(const ModuleId& parent_module, const ModuleId& child_module);
- private: /* Private validators/invalidators */
+ public: /* Public validators/invalidators */
bool valid_module_id(const ModuleId& module) const;
bool valid_module_port_id(const ModuleId& module, const ModulePortId& port) const;
+ private: /* Private validators/invalidators */
void invalidate_name2id_map();
void invalidate_port_lookup();
private: /* Internal data */
@@ -76,6 +81,7 @@ class ModuleManager {
vtr::vector> ports_; /* List of ports for each Module */
vtr::vector> port_types_; /* Type of ports */
vtr::vector> port_is_register_; /* If the port is a register, use for Verilog port definition. If enabled: reg */
+ vtr::vector> port_preproc_flags_; /* If a port is available only when a pre-processing flag is enabled. This is to record the pre-processing flags */
/* fast look-up for module */
std::map name_id_map_;
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp
index 7faf4a054..e442b0223 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp
@@ -12,6 +12,9 @@
#include "circuit_library.h"
#include "module_manager.h"
+
+#include "fpga_x2p_naming.h"
+
#include "module_manager_utils.h"
/******************************************************************************
@@ -72,3 +75,285 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
return add_circuit_model_to_module_manager(module_manager, circuit_lib, circuit_model, circuit_lib.model_name(circuit_model));
}
+/********************************************************************
+ * Add a list of ports that are used for reserved SRAM ports to a module
+ * in the module manager
+ * The reserved SRAM ports are mainly designed for RRAM-based FPGA,
+ * which are shared across modules.
+ * Note that different modules may require different size of reserved
+ * SRAM ports but their LSB must all start from 0
+ * +---------+
+ * reserved_sram_port[0:X] --->| ModuleA |
+ * +---------+
+ *
+ * +---------+
+ * reserved_sram_port[0:Y] --->| ModuleB |
+ * +---------+
+ *
+ ********************************************************************/
+void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager,
+ const ModuleId& module_id,
+ const size_t& port_size) {
+ /* Add a reserved BLB port to the module */
+ std::string blb_port_name = generate_reserved_sram_port_name(SPICE_MODEL_PORT_BLB);
+ BasicPort blb_module_port(blb_port_name, port_size);
+ /* Add generated ports to the ModuleManager */
+ module_manager.add_port(module_id, blb_module_port, ModuleManager::MODULE_INPUT_PORT);
+
+ /* Add a reserved BLB port to the module */
+ std::string wl_port_name = generate_reserved_sram_port_name(SPICE_MODEL_PORT_WL);
+ BasicPort wl_module_port(wl_port_name, port_size);
+ /* Add generated ports to the ModuleManager */
+ module_manager.add_port(module_id, wl_module_port, ModuleManager::MODULE_INPUT_PORT);
+}
+
+/********************************************************************
+ * Add a list of ports that are used for formal verification to a module
+ * in the module manager
+ *
+ * The formal verification port will appear only when a pre-processing flag is defined
+ * This function will add the pre-processing flag along with the port
+ ********************************************************************/
+void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_manager,
+ const ModuleId& module_id,
+ const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const std::string& preproc_flag,
+ const size_t& port_size) {
+ /* Create a port */
+ std::string port_name = generate_formal_verification_sram_port_name(circuit_lib, sram_model);
+ BasicPort module_port(port_name, port_size);
+ /* Add generated ports to the ModuleManager */
+ ModulePortId port_id = module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add pre-processing flag if defined */
+ module_manager.set_port_preproc_flag(module_id, port_id, preproc_flag);
+}
+
+/********************************************************************
+ * Add a list of ports that are used for SRAM configuration to a module
+ * in the module manager
+ * The type and names of added ports strongly depend on the
+ * organization of SRAMs.
+ * 1. Standalone SRAMs:
+ * two ports will be added, which are regular output and inverted output
+ * 2. Scan-chain Flip-flops:
+ * two ports will be added, which are the head of scan-chain
+ * and the tail of scan-chain
+ * IMPORTANT: the port size will be forced to 1 in this case
+ * because the head and tail are both 1-bit ports!!!
+ * 3. Memory decoders:
+ * 2-4 ports will be added, depending on the ports available in the SRAM
+ * Among these, two ports are mandatory: BL and WL
+ * The other two ports are optional: BLB and WLB
+ * Note that the constraints are correletated to the checking rules
+ * in check_circuit_library()
+ ********************************************************************/
+void add_sram_ports_to_module_manager(ModuleManager& module_manager,
+ const ModuleId& module_id,
+ const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const e_sram_orgz sram_orgz_type,
+ const size_t& port_size) {
+ /* Prepare a list of port types to be added, the port type will be used to create port names */
+ std::vector model_port_types;
+ /* Prepare a list of module port types to be added, the port type will be used to specify the port type in Verilog/SPICE module */
+ std::vector module_port_types;
+ /* Actual port size may be different from user specification. Think about CCFF */
+ size_t sram_port_size = port_size;
+
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_STANDALONE:
+ model_port_types.push_back(SPICE_MODEL_PORT_INPUT);
+ module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
+ model_port_types.push_back(SPICE_MODEL_PORT_OUTPUT);
+ module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
+ break;
+ case SPICE_SRAM_SCAN_CHAIN:
+ model_port_types.push_back(SPICE_MODEL_PORT_INPUT);
+ module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
+ model_port_types.push_back(SPICE_MODEL_PORT_OUTPUT);
+ module_port_types.push_back(ModuleManager::MODULE_OUTPUT_PORT);
+ /* CCFF head/tail are single-bit ports */
+ sram_port_size = 1;
+ break;
+ case SPICE_SRAM_MEMORY_BANK: {
+ std::vector ports_to_search;
+ ports_to_search.push_back(SPICE_MODEL_PORT_BL);
+ ports_to_search.push_back(SPICE_MODEL_PORT_WL);
+ ports_to_search.push_back(SPICE_MODEL_PORT_BLB);
+ ports_to_search.push_back(SPICE_MODEL_PORT_WLB);
+ /* Try to find a BL/WL/BLB/WLB port and update the port types/module port types to be added */
+ for (const auto& port_to_search : ports_to_search) {
+ std::vector found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search);
+ if (0 == found_port.size()) {
+ continue;
+ }
+ model_port_types.push_back(port_to_search);
+ module_port_types.push_back(ModuleManager::MODULE_INPUT_PORT);
+ }
+ break;
+ }
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s,[LINE%d])Invalid type of SRAM organization !\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ /* Add ports to the module manager */
+ for (size_t iport = 0; iport < model_port_types.size(); ++iport) {
+ /* Create a port */
+ std::string port_name = generate_sram_port_name(circuit_lib, sram_model, sram_orgz_type, model_port_types[iport]);
+ BasicPort module_port(port_name, sram_port_size);
+ /* Add generated ports to the ModuleManager */
+ module_manager.add_port(module_id, module_port, module_port_types[iport]);
+ }
+}
+
+/*********************************************************************
+ * Create a port-to-port map for a CMOS memory module
+ *
+ * Configuration Chain
+ * -------------------
+ *
+ * config_bus (head) config_bus (tail)
+ * | ^
+ * v |
+ * +-------------------------------------+
+ * | CMOS-based Memory Module |
+ * +-------------------------------------+
+ * | |
+ * v v
+ * sram_out sram_outb
+ *
+ *
+ * Memory bank
+ * -----------
+ *
+ * config_bus (BL) config_bus (WL)
+ * | |
+ * v v
+ * +-------------------------------------+
+ * | CMOS-based Memory Module |
+ * +-------------------------------------+
+ * | |
+ * v v
+ * sram_out sram_outb
+ *
+ **********************************************************************/
+static
+std::map generate_cmos_mem_module_port2port_map(const ModuleManager& module_manager,
+ const ModuleId& mem_module,
+ const std::vector& config_bus_ports,
+ const std::vector& mem_output_bus_ports,
+ const e_sram_orgz& sram_orgz_type) {
+ std::map port2port_name_map;
+
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_STANDALONE:
+ /* Nothing to do */
+ break;
+ case SPICE_SRAM_SCAN_CHAIN: {
+ /* Link the head port of the memory module:
+ * the LSB of config bus port is the head port index
+ */
+ VTR_ASSERT( 1 == config_bus_ports.size() );
+ BasicPort head_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_lsb(), config_bus_ports[0].get_lsb());
+ port2port_name_map[generate_configuration_chain_head_name()] = head_port;
+
+ /* Link the tail port of the memory module:
+ * the MSB of config bus port is the tail port index
+ */
+ BasicPort tail_port(config_bus_ports[0].get_name(), config_bus_ports[0].get_msb(), config_bus_ports[0].get_msb());
+ port2port_name_map[generate_configuration_chain_tail_name()] = tail_port;
+
+ /* Link the SRAM output ports of the memory module */
+ VTR_ASSERT( 2 == mem_output_bus_ports.size() );
+ port2port_name_map[generate_configuration_chain_data_out_name()] = mem_output_bus_ports[0];
+ port2port_name_map[generate_configuration_chain_inverted_data_out_name()] = mem_output_bus_ports[1];
+ break;
+ }
+ case SPICE_SRAM_MEMORY_BANK:
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ return port2port_name_map;
+}
+
+/*********************************************************************
+ * Create a port-to-port map for a ReRAM-based memory module
+ * Memory bank
+ * -----------
+ *
+ * config_bus (BL) config_bus (WL)
+ * | |
+ * v v
+ * +-------------------------------------+
+ * | ReRAM-based Memory Module |
+ * +-------------------------------------+
+ * | |
+ * v v
+ * Mem_out Mem_outb
+ **********************************************************************/
+static
+std::map generate_rram_mem_module_port2port_map(const ModuleManager& module_manager,
+ const ModuleId& mem_module,
+ const e_sram_orgz& sram_orgz_type) {
+ std::map port2port_name_map;
+
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_STANDALONE:
+ /* Not supported */
+ break;
+ case SPICE_SRAM_SCAN_CHAIN:
+ /* TODO: to be supported */
+ break;
+ case SPICE_SRAM_MEMORY_BANK:
+ /* TODO: link BL/WL/Reserved Ports to the inputs of a memory module */
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s,[LINE%d])Invalid type of SRAM organization!\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ return port2port_name_map;
+}
+
+/*********************************************************************
+ * Create a port-to-port map for a memory module
+ * The content of the port-to-port map will depend not only
+ * the design technology of the memory cells but also the
+ * configuration styles of FPGA fabric.
+ * Here we will branch on the design technology
+ **********************************************************************/
+std::map generate_mem_module_port2port_map(const ModuleManager& module_manager,
+ const ModuleId& mem_module,
+ const std::vector& config_bus_ports,
+ const std::vector& mem_output_bus_ports,
+ const e_spice_model_design_tech& mem_design_tech,
+ const e_sram_orgz& sram_orgz_type) {
+ std::map port2port_name_map;
+
+ switch (mem_design_tech) {
+ case SPICE_MODEL_DESIGN_CMOS:
+ port2port_name_map = generate_cmos_mem_module_port2port_map(module_manager, mem_module, config_bus_ports, mem_output_bus_ports, sram_orgz_type);
+ break;
+ case SPICE_MODEL_DESIGN_RRAM:
+ port2port_name_map = generate_rram_mem_module_port2port_map(module_manager, mem_module, sram_orgz_type);
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s,[LINE%d])Invalid type of memory design technology !\n",
+ __FILE__, __LINE__);
+ exit(1);
+ }
+
+ return port2port_name_map;
+}
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h
index c117b5a6c..bee3e7ff8 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.h
@@ -7,6 +7,9 @@
#define MODULE_MANAGER_UTILS_H
/* Include other header files which are dependency on the function declared below */
+#include
+#include "device_port.h"
+#include "spice_types.h"
#include "circuit_library.h"
#include "module_manager.h"
@@ -17,5 +20,30 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib, const CircuitModelId& circuit_model);
+void add_reserved_sram_ports_to_module_manager(ModuleManager& module_manager,
+ const ModuleId& module_id,
+ const size_t& port_size);
+
+void add_formal_verification_sram_ports_to_module_manager(ModuleManager& module_manager,
+ const ModuleId& module_id,
+ const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const std::string& preproc_flag,
+ const size_t& port_size);
+
+void add_sram_ports_to_module_manager(ModuleManager& module_manager,
+ const ModuleId& module_id,
+ const CircuitLibrary& circuit_lib,
+ const CircuitModelId& sram_model,
+ const e_sram_orgz sram_orgz_type,
+ const size_t& port_size);
+
+std::map generate_mem_module_port2port_map(const ModuleManager& module_manager,
+ const ModuleId& mem_module,
+ const std::vector& config_bus_ports,
+ const std::vector& mem_output_bus_ports,
+ const e_spice_model_design_tech& mem_design_tech,
+ const e_sram_orgz& sram_orgz_type);
+
#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp
new file mode 100644
index 000000000..197da9c8b
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.cpp
@@ -0,0 +1,94 @@
+/********************************************************************
+ * This file includes most utilized function for rr_block data structures
+ *******************************************************************/
+#include
+#include
+
+#include "vtr_assert.h"
+#include "vpr_types.h"
+#include "fpga_x2p_types.h"
+#include "rr_blocks_utils.h"
+
+/*********************************************************************
+ * This function will find the global ports required by a Switch Block
+ * module. It will find all the circuit models in the circuit library
+ * that may be included in the Switch Block
+ * Collect the global ports from the circuit_models and merge with the same name
+ ********************************************************************/
+std::vector find_switch_block_global_ports(const RRGSB& rr_gsb,
+ const CircuitLibrary& circuit_lib,
+ const std::vector& switch_lib) {
+ std::vector sub_models;
+ /* Walk through the OUTPUT nodes at each side of a GSB,
+ * get the switch id of incoming edges
+ * and get the circuit model linked to the switch id
+ */
+ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
+ Side side_manager(side);
+ for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
+ if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
+ continue;
+ }
+ /* Find the driver switch of the node */
+ short driver_switch = rr_gsb.get_chan_node(side_manager.get_side(), itrack)->drive_switches[DEFAULT_SWITCH_ID];
+ /* Find the circuit model id of the driver switch */
+ VTR_ASSERT( (size_t)driver_switch < switch_lib.size() );
+ /* Get the model, and try to add to the sub_model list */
+ CircuitModelId switch_circuit_model = switch_lib[driver_switch].circuit_model;
+ /* Make sure it is a valid id */
+ VTR_ASSERT( CircuitModelId::INVALID() != switch_circuit_model );
+ /* Get the model, and try to add to the sub_model list */
+ if (sub_models.end() == std::find(sub_models.begin(), sub_models.end(), switch_circuit_model)) {
+ /* Not yet in the list, add it */
+ sub_models.push_back(switch_circuit_model);
+ }
+ }
+ }
+
+ std::vector global_ports;
+ /* Iterate over the model list, and add the global ports*/
+ for (const auto& model : sub_models) {
+ std::vector temp_global_ports = circuit_lib.model_global_ports(model, true);
+ /* Add the temp_global_ports to the list to be returned, make sure we do not have any duplicated ports */
+ for (const auto& port_candidate : temp_global_ports) {
+ if (global_ports.end() == std::find(global_ports.begin(), global_ports.end(), port_candidate)) {
+ /* Not yet in the list, add it */
+ global_ports.push_back(port_candidate);
+ }
+ }
+ }
+
+ return global_ports;
+}
+
+/*********************************************************************
+ * This function will find the number of multiplexers required by
+ * a Switch Block module.
+ ********************************************************************/
+size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb) {
+ size_t num_muxes = 0;
+ /* Walk through the OUTPUT nodes at each side of a GSB,
+ * get the switch id of incoming edges
+ * and get the circuit model linked to the switch id
+ */
+ for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
+ Side side_manager(side);
+ for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
+ if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
+ continue;
+ }
+ /* Check if this node is just a passing wire */
+ if (true == rr_gsb.is_sb_node_passing_wire(side_manager.get_side(), itrack)) {
+ continue;
+ }
+ /* Check if this node has more than 2 drivers */
+ if (2 > rr_gsb.get_chan_node(side_manager.get_side(), itrack)->num_drive_rr_nodes) {
+ continue;
+ }
+ /* This means we need a multiplexer, update the counter */
+ num_muxes++;
+ }
+ }
+ return num_muxes;
+}
+
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.h
new file mode 100644
index 000000000..d49a55539
--- /dev/null
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks_utils.h
@@ -0,0 +1,19 @@
+/********************************************************************
+ * Header file for rr_block_utils.cpp
+ *******************************************************************/
+#ifndef RR_BLOCKS_UTILS_H
+#define RR_BLOCKS_UTILS_H
+
+/* Include other header file required by the function declaration */
+#include
+#include "physical_types.h"
+#include "circuit_library.h"
+#include "rr_blocks.h"
+
+std::vector find_switch_block_global_ports(const RRGSB& rr_gsb,
+ const CircuitLibrary& circuit_lib,
+ const std::vector& switch_lib);
+
+size_t find_switch_block_number_of_muxes(const RRGSB& rr_gsb);
+
+#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_utils.c
index d24a6bcba..a75da71a7 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_utils.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/spice/spice_utils.c
@@ -351,10 +351,10 @@ void fprint_spice_sram_one_outport(FILE* fp,
break;
case SPICE_SRAM_SCAN_CHAIN:
if (0 == port_type_index) {
- port_name = "scff_out";
+ port_name = "ccff_out";
} else {
assert(1 == port_type_index);
- port_name = "scff_outb";
+ port_name = "ccff_outb";
}
break;
case SPICE_SRAM_MEMORY_BANK:
@@ -696,7 +696,7 @@ void fprint_global_pad_ports_spice_model(FILE* fp,
case SPICE_MODEL_LUT:
case SPICE_MODEL_FF:
case SPICE_MODEL_HARDLOGIC:
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
case SPICE_MODEL_INVBUF:
case SPICE_MODEL_PASSGATE:
case SPICE_MODEL_GATE:
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c
index 19c80b25e..f35a024aa 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_api.c
@@ -40,6 +40,8 @@
#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_routing.h"
#include "verilog_compact_netlist.h"
@@ -266,10 +268,21 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
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 */
- dump_verilog_routing_resources(sram_verilog_orgz_info, src_dir_path, rr_dir_path, Arch, &vpr_setup.RoutingArch,
- num_rr_nodes, rr_node, rr_node_indices, rr_indexed_data,
- vpr_setup.FPGA_SPICE_Opts);
+ print_verilog_routing_resources(module_manager, mux_lib, 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);
/* Dump logic blocks
* Branches to go:
@@ -280,10 +293,18 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
lb_dir_path, &Arch,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog);
- /* Dump internal structures of submodules */
- 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);
+ /* 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);
/* Dump top-level verilog */
dump_compact_verilog_top_netlist(sram_verilog_orgz_info, chomped_circuit_name,
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_compact_netlist.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_compact_netlist.c
index 112335c0b..96aea8d43 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_compact_netlist.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_compact_netlist.c
@@ -79,7 +79,7 @@ char* generate_compact_verilog_grid_module_name(t_type_ptr phy_block_type,
/* ONLY for compact Verilog netlists:
* Update the grid_index_low and grid_index_high for each spice_models
- * Currently, we focus on three spice_models: SRAMs/SCFFs/IOPADs
+ * Currently, we focus on three spice_models: SRAMs/CCFFs/IOPADs
*/
static
void compact_verilog_update_one_spice_model_grid_index(t_type_ptr phy_block_type,
@@ -102,7 +102,7 @@ void compact_verilog_update_one_spice_model_grid_index(t_type_ptr phy_block_type
case SPICE_MODEL_HARDLOGIC:
case SPICE_MODEL_GATE:
break;
- case SPICE_MODEL_SCFF:
+ case SPICE_MODEL_CCFF:
case SPICE_MODEL_SRAM:
stamped_cnt = spice_model[i].cnt;
spice_model[i].grid_index_low[grid_x][grid_y] = stamped_cnt;
@@ -158,7 +158,7 @@ void compact_verilog_update_sram_orgz_info_grid_index(t_sram_orgz_info* cur_sram
/* ONLY for compact Verilog netlists:
* Update the grid_index_low and grid_index_high for each spice_models
- * Currently, we focus on three spice_models: SRAMs/SCFFs/IOPADs
+ * Currently, we focus on three spice_models: SRAMs/CCFFs/IOPADs
* IMPORTANT: The sequence of for loop should be consistent with
* 1. bitstream logic block
* 2. verilog pbtypes logic block
@@ -653,7 +653,7 @@ void dump_compact_verilog_defined_one_grid(t_sram_orgz_info* cur_sram_orgz_info,
}
/* Dump ports only visible during formal verification*/
- if (0 < (cur_sram_orgz_info->grid_conf_bits_msb[ix][iy] - 1
+ if (0 < (cur_sram_orgz_info->grid_conf_bits_msb[ix][iy]
- cur_sram_orgz_info->grid_conf_bits_lsb[ix][iy])) {
fprintf(fp, "\n");
fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag);
@@ -1097,9 +1097,11 @@ void dump_compact_verilog_defined_one_channel(FILE* fp,
fprintf(fp, "(");
fprintf(fp, "\n");
/* dump global ports */
+ /*
if (0 < dump_verilog_global_ports(fp, global_ports_head, FALSE, is_explicit_mapping)) {
fprintf(fp, ",\n");
}
+ */
/* LEFT/BOTTOM side port of CHANX/CHANY */
/* We apply an opposite port naming rule than function: fprint_routing_chan_subckt
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoder.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoder.c
index 4204a24f5..410e5d366 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoder.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoder.c
@@ -241,7 +241,7 @@ void dump_verilog_decoder(FILE* fp,
}
/* For standalone-SRAM configuration organization:
- * Dump the module of configuration module which connect configuration ports to SRAMs/SCFFs
+ * Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
*/
static
void dump_verilog_standalone_sram_config_module(FILE* fp,
@@ -288,7 +288,7 @@ void dump_verilog_standalone_sram_config_module(FILE* fp,
/* For scan-chain configuration organization:
- * Dump the module of configuration module which connect configuration ports to SRAMs/SCFFs
+ * Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
*/
static
void dump_verilog_scan_chain_config_module(FILE* fp,
@@ -331,7 +331,7 @@ void dump_verilog_scan_chain_config_module(FILE* fp,
fprintf(fp, ";\n");
/* Verilog Module body */
- /* Connect the head of current scff to the tail of previous scff*/
+ /* 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);
@@ -405,7 +405,7 @@ void dump_verilog_membank_one_inv_module(FILE* fp,
}
/* For Memory-bank configuration organization:
- * Dump the module of configuration module which connect configuration ports to SRAMs/SCFFs
+ * Dump the module of configuration module which connect configuration ports to SRAMs/CCFFs
*/
static
void dump_verilog_membank_config_module(FILE* fp,
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.cpp
index 47255c250..4e3a7c422 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.cpp
@@ -59,17 +59,17 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp,
VTR_ASSERT(ModuleId::INVALID() != module_id);
/* Add module ports */
/* Add each input port */
- BasicPort addr_port("addr", addr_size);
+ BasicPort addr_port(generate_mux_local_decoder_addr_port_name(), addr_size);
module_manager.add_port(module_id, addr_port, ModuleManager::MODULE_INPUT_PORT);
/* Add each output port */
- BasicPort data_port("data", data_size);
+ BasicPort data_port(generate_mux_local_decoder_data_port_name(), data_size);
module_manager.add_port(module_id, data_port, ModuleManager::MODULE_OUTPUT_PORT);
/* Data port is registered. It should be outputted as
* output reg [lsb:msb] data
*/
module_manager.set_port_is_register(module_id, data_port.get_name(), true);
/* Add data_in port */
- BasicPort data_inv_port("data_inv", data_size);
+ BasicPort data_inv_port(generate_mux_local_decoder_data_inv_port_name(), data_size);
VTR_ASSERT(true == decoder_lib.use_data_inv_port(decoder));
module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT);
@@ -81,6 +81,20 @@ void print_verilog_mux_local_decoder_module(std::fstream& fp,
/* Print the truth table of this decoder */
/* Internal logics */
+ /* Early exit: Corner case for data size = 1 the logic is very simple:
+ * data = addr;
+ * data_inv = ~data_inv
+ */
+ if (1 == data_size) {
+ print_verilog_wire_connection(fp, addr_port, data_port, false);
+ print_verilog_wire_connection(fp, data_inv_port, data_port, true);
+ print_verilog_comment(fp, std::string("----- END Verilog codes for Decoder convert " + std::to_string(addr_size) + "-bit addr to " + std::to_string(data_size) + "-bit data -----"));
+
+ /* Put an end to the Verilog module */
+ print_verilog_module_end(fp, module_name);
+ return;
+ }
+
/* We use a magic number -1 as the addr=1 should be mapped to ...1
* Otherwise addr will map addr=1 to ..10
* Note that there should be a range for the shift operators
@@ -194,7 +208,7 @@ void print_verilog_submodule_mux_local_decoders(ModuleManager& module_manager,
* Note that only when there are >=2 memories, a decoder is needed
*/
size_t decoder_data_size = branch_mux_graph.num_memory_bits();
- if (2 > decoder_data_size) {
+ if (0 == decoder_data_size) {
continue;
}
/* Try to find if the decoder already exists in the library,
@@ -216,3 +230,150 @@ void print_verilog_submodule_mux_local_decoders(ModuleManager& module_manager,
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_fname.c_str());
}
+/***************************************************************************************
+ * For scan-chain configuration organization:
+ * Generate the Verilog module of configuration module
+ * which connect configuration ports to SRAMs/CCFFs in a chain:
+ *
+ * +------+ +------+ +------+
+ * cc_in--->| CCFF |--->| CCFF |---> ... --->| CCFF |----> sc_out
+ * +------+ +------+ +------+
+ ***************************************************************************************/
+static
+void print_verilog_scan_chain_config_module(ModuleManager& module_manager,
+ std::fstream& fp,
+ t_sram_orgz_info* cur_sram_orgz_info) {
+ /* Validate the FILE handler */
+ check_file_handler(fp);
+
+ /* Get the total memory bits */
+ int num_mem_bits = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info);
+
+ /* Create a module definition for the configuration chain */
+ print_verilog_comment(fp, std::string("----- BEGIN Configuration Peripheral for Scan-chain FFs -----"));
+
+ /* Create a Verilog Module based on the circuit model, and add to module manager */
+ ModuleId module_id = module_manager.add_module(std::string(verilog_config_peripheral_prefix));
+ VTR_ASSERT(ModuleId::INVALID() != module_id);
+ /* Add module ports */
+ /* Add the head of scan-chain: a 1-bit input port */
+ BasicPort sc_head_port(std::string(top_netlist_scan_chain_head_prefix), 1);
+ module_manager.add_port(module_id, sc_head_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add the inputs of scan-chain FFs, which are the outputs of the module */
+ BasicPort cc_input_port(std::string("chain_input"), num_mem_bits);
+ module_manager.add_port(module_id, cc_input_port, ModuleManager::MODULE_OUTPUT_PORT);
+ /* Add the outputs of scan-chain FFs, which are inputs of the module */
+ BasicPort sc_output_port(std::string("chain_output"), num_mem_bits);
+ module_manager.add_port(module_id, sc_output_port, ModuleManager::MODULE_INPUT_PORT);
+
+ /* dump module definition + ports */
+ print_verilog_module_declaration(fp, module_manager, module_id);
+ /* Finish dumping ports */
+
+ /* Declare the sc_output_port is a wire */
+ fp << generate_verilog_port(VERILOG_PORT_WIRE, sc_output_port) << ";" << std::endl;
+ fp << std::endl;
+
+ /* Connect scan-chain input to the first scan-chain input */
+ BasicPort sc_first_input_port(cc_input_port.get_name(), 1);
+ print_verilog_wire_connection(fp, sc_first_input_port, sc_head_port, false);
+
+ /* Connect the head of current ccff to the tail of previous ccff*/
+ BasicPort chain_output_port(cc_input_port.get_name(), 1, num_mem_bits - 1);
+ BasicPort chain_input_port(sc_output_port.get_name(), 0, num_mem_bits - 2);
+ print_verilog_wire_connection(fp, chain_output_port, chain_input_port, false);
+
+ print_verilog_comment(fp, std::string("----- END Configuration Peripheral for Scan-chain FFs -----"));
+
+ /* Put an end to the Verilog module */
+ print_verilog_module_end(fp, module_manager.module_name(module_id));
+
+ return;
+}
+
+/***************************************************************************************
+ * Generate the configuration peripheral circuits for the top-level Verilog netlist
+ * This function will create Verilog modules depending on the configuration scheme:
+ * 1. Scan-chain:
+ * It will create a module which connects the Scan-Chain Flip-Flops (CCFFs)
+ * as a chain:
+ *
+ * +------+ +------+ +------+
+ * cc_in--->| CCFF |--->| CCFF |---> ... --->| CCFF |----> sc_out
+ * +------+ +------+ +------+
+ *
+ * 2. Memory bank:
+ * It will create a BL decoder and a WL decoder which will configure the SRAMs
+ * as a memory bank
+ *
+ * +------------------------+
+ * | WL Decoder |
+ * +------------------------+
+ * | | | ... | |
+ * v v v v v
+ * +---------+ +------------------------+
+ * | |--->| |
+ * | | | |
+ * | BL |--->| |
+ * | Decoder | .. | FPGA Core logic |
+ * | | .. | |
+ * | |--->| |
+ * +---------+ +------------------------+
+ ***************************************************************************************/
+void print_verilog_config_peripherals(ModuleManager& module_manager,
+ t_sram_orgz_info* cur_sram_orgz_info,
+ const std::string& verilog_dir,
+ const std::string& submodule_dir) {
+ std::string verilog_fname(submodule_dir + config_peripheral_verilog_file_name);
+ 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 out debugging information for if the file is not opened/created properly */
+ vpr_printf(TIO_MESSAGE_INFO,
+ "Creating Verilog netlist for configuration peripherals (%s)...\n",
+ verilog_fname.c_str());
+
+ print_verilog_file_header(fp, "Configuration Peripheral Circuits");
+
+ print_verilog_include_defines_preproc_file(fp, verilog_dir);
+
+ /* Create a library for decoders */
+ DecoderLibrary decoder_lib;
+
+ switch(cur_sram_orgz_info->type) {
+ case SPICE_SRAM_STANDALONE:
+ break;
+ case SPICE_SRAM_SCAN_CHAIN:
+ print_verilog_scan_chain_config_module(module_manager, fp, cur_sram_orgz_info);
+ break;
+ case SPICE_SRAM_MEMORY_BANK:
+ /* TODO: Finish refactoring this part after the sram_orgz_info ! */
+ /*
+ 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 stream */
+ fp.close();
+
+ /* Add fname to the linked list when debugging is finished */
+ /* TODO: 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;
+}
+
+
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.h
index 88877b9e0..8f4a52816 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_decoders.h
@@ -21,4 +21,9 @@ void print_verilog_submodule_mux_local_decoders(ModuleManager& module_manager,
const std::string& verilog_dir,
const std::string& submodule_dir);
+void print_verilog_config_peripherals(ModuleManager& module_manager,
+ t_sram_orgz_info* cur_sram_orgz_info,
+ const std::string& verilog_dir,
+ const std::string& submodule_dir);
+
#endif
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_formality_autodeck.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_formality_autodeck.c
index db4de023d..0be59a137 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_formality_autodeck.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_formality_autodeck.c
@@ -39,203 +39,217 @@
#include "verilog_routing.h"
#include "verilog_tcl_utils.h"
-
-static void searching_used_latch(FILE *fp, t_pb * pb, int pb_index, char* chomped_circuit_name, char* inst_name){
- int i, j;
-// char* tmp = NULL;
- const t_pb_type *pb_type;
- t_mode *mode;
- t_pb_graph_node * node;
-// char* index = NULL;
+static void searching_used_latch(FILE *fp, t_pb *pb, int pb_index, char *chomped_circuit_name, char *inst_name)
+{
+ int i, j;
+ // 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];
+ 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), "_"));
+ // 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) );
- }
- //free(tmp); //Looks like is the cause of a double free, once free executated next iteration as no value in tmp
- return;
+ 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));
+ }
+ //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;
+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;
+ x_pos = block[h].x;
+ y_pos = block[h].y;
- pb = (t_pb*) block[h].pb;
+ pb = (t_pb *)block[h].pb;
- pb_type = pb->pb_graph_node->pb_type;
- mode = &pb_type->modes[pb->mode];
+ 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), "_"));
+ 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;
+ 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) {
+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",
+ 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) {
+ 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);
+ fprintf(fp, "%s \n", spice.include_netlists[i].path);
spice.include_netlists[i].included = 1;
- } else {
+ }
+ 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;
- char* formality_script_file_name = NULL;
- char* benchmark_path = NULL;
- char* original_output_name = NULL;
-/* int output_length; */
-/* int pos; */
- FILE* fp = NULL;
+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, h;
+ char *formScriptfp = NULL;
+ char *benchmark_path = NULL;
+ char *original_output_name = NULL;
+ /* int output_length; */
+ /* int pos; */
+ FILE *fp = NULL;
- if(TRUE == fpga_verilog_opts.print_autocheck_top_testbench){
+ if (TRUE == fpga_verilog_opts.print_autocheck_top_testbench)
+ {
benchmark_path = fpga_verilog_opts.reference_verilog_benchmark_file;
- } else {
+ }
+ 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);
- }
+ formScriptfp = my_strcat(fm_dir_formatted,
+ my_strcat(chomped_circuit_name,
+ formality_script_name_postfix));
+ fp = fopen(formScriptfp, "w");
+ if (NULL == fp)
+ {
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(FILE:%s,LINE[%d])Failure in create formality script %s",
+ __FILE__, __LINE__, formScriptfp);
+ exit(1);
+ }
/* Load Verilog benchmark as reference */
- fprintf(fp, "read_verilog -container r -libname WORK -05 { %s }\n", benchmark_path);
+ fprintf(fp, "%s\n\n", benchmark_path);
+
/* Set reference top */
- fprintf(fp, "set_top r:/WORK/%s\n", chomped_circuit_name);
+ fprintf(fp, "%s\n\n", 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);
- fprintf(fp, "%s%s%s ", src_dir_formatted,
- chomped_circuit_name,
- formal_verification_verilog_file_postfix);
+ fprintf(fp, "%s%s%s\n", src_dir_formatted, chomped_circuit_name,
+ verilog_top_postfix);
+
+ fprintf(fp, "%s%s%s\n", src_dir_formatted,
+ chomped_circuit_name,
+ formal_verification_verilog_file_postfix);
+
init_include_user_defined_verilog_netlists(spice);
formality_include_user_defined_verilog_netlists(fp, spice);
- fprintf(fp, "%s%s%s ", src_dir_formatted,
- default_rr_dir_name,
- routing_verilog_file_name);
- fprintf(fp, "%s%s%s ", src_dir_formatted,
- default_lb_dir_name,
- logic_block_verilog_file_name);
- fprintf(fp, "%s%s%s ", src_dir_formatted,
- default_submodule_dir_name,
- submodule_verilog_file_name);
- fprintf(fp, "}\n");
+ fprintf(fp, "%s%s%s\n", src_dir_formatted,
+ default_rr_dir_name,
+ routing_verilog_file_name);
+ fprintf(fp, "%s%s%s\n", src_dir_formatted,
+ default_lb_dir_name,
+ logic_block_verilog_file_name);
+ fprintf(fp, "%s%s%s\n", src_dir_formatted,
+ default_submodule_dir_name,
+ submodule_verilog_file_name);
+ fprintf(fp, "\n");
+
/* Set implementation top */
- fprintf(fp, "set_top i:/WORK/%s\n", my_strcat(chomped_circuit_name, formal_verification_top_postfix));
+ fprintf(fp, "%s\n", my_strcat(chomped_circuit_name, formal_verification_top_postfix));
/* Run matching */
- fprintf(fp, "match\n");
+ fprintf(fp, "\n");
/* Add manual matching for the outputs */
- for (iblock = 0; iblock < num_logical_blocks; iblock++) {
+ for (iblock = 0; iblock < num_logical_blocks; iblock++)
+ {
original_output_name = NULL;
- if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
+ 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){
+ 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",
+ // fprintf(fp, "set_user_match r:/WORK/%s/%s i:/WORK/%s/%s[0] -type port -noninverted\n",
+ fprintf(fp, "/WORK/%s/%s /WORK/%s/%s[0]\n",
chomped_circuit_name,
- original_output_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));
+ my_strcat(logical_block[iblock].name, formal_verification_top_module_port_postfix));
}
}
}
- match_registers(fp, chomped_circuit_name);
+
+ for (h = 0; h < copy_nb_clusters; h++)
+ clb_iteration(fp, chomped_circuit_name, h);
+
/* Run verification */
- fprintf(fp, "verify\n");
+ fprintf(fp, "\n");
/* Script END */
fclose(fp);
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c
index 7bc682ad7..c6d563c37 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_global.c
@@ -131,7 +131,7 @@ char* top_netlist_normal_bl_port_postfix = "_bl";
char* top_netlist_normal_wl_port_postfix = "_wl";
char* top_netlist_normal_blb_port_postfix = "_blb";
char* top_netlist_normal_wlb_port_postfix = "_wlb";
-char* top_netlist_scan_chain_head_prefix = "sc_in";
+char* top_netlist_scan_chain_head_prefix = "cc_in";
char* top_tb_reset_port_name = "greset";
char* top_tb_set_port_name = "gset";
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c
index dba96bb84..72b250231 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_include_netlists.c
@@ -113,6 +113,9 @@ void write_include_netlists (char* src_dir_formatted,
fprintf(fp, "`include \"%s%s%s\"\n", src_dir_formatted,
default_submodule_dir_name,
submodule_verilog_file_name);
+ fprintf(fp, "`include \"%s%s%s\"\n", src_dir_formatted,
+ default_submodule_dir_name,
+ config_peripheral_verilog_file_name);
init_include_user_defined_verilog_netlists(spice);
include_netlists_include_user_defined_verilog_netlists(fp, spice);
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp
index 5adc9a558..5c7e27449 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_lut.cpp
@@ -299,7 +299,7 @@ void print_verilog_submodule_lut(ModuleManager& module_manager,
/* Instanciate the multiplexing structure for the LUT */
print_verilog_comment(fp, std::string("---- BEGIN Instanciation of LUT multiplexer module -----"));
/* Find the name of LUT MUX: no need to provide a mux size, just give an invalid number (=-1) */
- std::string lut_mux_module_name = generate_verilog_mux_subckt_name(circuit_lib, circuit_model, size_t(-1), std::string(""));
+ std::string lut_mux_module_name = generate_mux_subckt_name(circuit_lib, circuit_model, size_t(-1), std::string(""));
/* Find the module id of LUT MUX in the module manager */
ModuleId lut_mux_module_id = module_manager.find_module(lut_mux_module_name);
/* We must have a valid id */
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp
index cb6754cea..09c2501f3 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.cpp
@@ -14,6 +14,7 @@
#include "module_manager.h"
#include "physical_types.h"
#include "vpr_types.h"
+#include "circuit_library_utils.h"
#include "mux_utils.h"
/* FPGA-X2P context header files */
@@ -27,10 +28,7 @@
#include "verilog_memory.h"
/*********************************************************************
- * Generate Verilog modules for the memories that are used
- * by CMOS (SRAM-based) multiplexers
- * We support:
- * 1. Flat memory modules
+ * Flat memory modules
*
* in[0] in[1] in[N]
* | | |
@@ -43,68 +41,15 @@
* v v v
* +------------------------------------+
* | Multiplexer Configuration port |
- *
- * 2. TODO: Local decoders
- *
- * in[0] in[1] in[N]
- * | | |
- * v v v
- * +-------+ +-------+ +-------+
- * | SRAM | | SRAM | ... | SRAM |
- * | [0] | | [1] | | [N-1] |
- * +-------+ +-------+ +-------+
- * | | ... |
- * v v v
- * +------------------------------------+
- * | Local decoders |
- * +------------------------------------+
- * | | ... |
- * v v v
- * +------------------------------------+
- * | Multiplexer Configuration port |
- *
- * 3. TODO: Scan-chain organization
- *
- * in[0] in[1] in[N]
- * | | |
- * v v v
- * +-------+ +-------+ +-------+
- * scan-chain--->| SRAM |--->| SRAM |--->... --->| SRAM |---->scan-chain
- * input&clock | [0] | | [1] | | [N-1] | output
- * +-------+ +-------+ +-------+
- * | | ... |
- * v v v
- * +-----------------------------------------+
- * | Multiplexer Configuration port |
- *
- * 4. TODO: Memory bank organization
- *
- * Bit lines Word lines
- * | |
- * v v
- * +------------------------------------+
- * | Multiplexer Configuration port |
- * +------------------------------------+
- * | | |
- * v v v
- * +-------+ +-------+ +-------+
- * | SRAM | | SRAM | ... | SRAM |
- * | [0] | | [1] | | [N-1] |
- * +-------+ +-------+ +-------+
- * | | ... |
- * v v v
- * +------------------------------------+
- * | Multiplexer Configuration port |
-
*
********************************************************************/
static
-void print_verilog_memory_module(ModuleManager& module_manager,
- const CircuitLibrary& circuit_lib,
- std::fstream& fp,
- const std::string& module_name,
- const CircuitModelId& sram_model,
- const size_t& num_mems) {
+void print_verilog_memory_standalone_module(ModuleManager& module_manager,
+ const CircuitLibrary& circuit_lib,
+ std::fstream& fp,
+ const std::string& module_name,
+ const CircuitModelId& sram_model,
+ const size_t& num_mems) {
/* Make sure we have a valid file handler*/
check_file_handler(fp);
@@ -120,6 +65,236 @@ void print_verilog_memory_module(ModuleManager& module_manager,
std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_INPUT, true);
/* Get the output ports from the SRAM */
std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_OUTPUT, true);
+
+ /* Add module ports: the ports come from the SRAM modules */
+ /* Add each global port */
+ for (const auto& port : sram_global_ports) {
+ /* Configure each global port: global ports are shared among the SRAMs, so it is independent from the memory size */
+ BasicPort global_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
+ module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT);
+ }
+ /* Add each input port */
+ for (const auto& port : sram_input_ports) {
+ BasicPort input_port(circuit_lib.port_lib_name(port), num_mems);
+ module_manager.add_port(module_id, input_port, ModuleManager::MODULE_INPUT_PORT);
+ }
+ /* Add each output port: port width should match the number of memories */
+ for (const auto& port : sram_output_ports) {
+ BasicPort output_port(circuit_lib.port_lib_name(port), num_mems);
+ module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT);
+ }
+
+ /* dump module definition + ports */
+ print_verilog_module_declaration(fp, module_manager, module_id);
+ /* Finish dumping ports */
+
+ /* Find the sram module in the module manager */
+ ModuleId sram_module_id = module_manager.find_module(circuit_lib.model_name(sram_model));
+
+ /* Instanciate each submodule */
+ for (size_t i = 0; i < num_mems; ++i) {
+ /* Create a port-to-port map */
+ std::map port2port_name_map;
+ /* Map instance inputs [i] to SRAM module input */
+ for (const auto& port : sram_input_ports) {
+ BasicPort instance_input_port(circuit_lib.port_lib_name(port), i, i);
+ port2port_name_map[circuit_lib.port_lib_name(port)] = instance_input_port;
+ }
+ /* Map instance outputs [i] to SRAM module input */
+ for (const auto& port : sram_output_ports) {
+ BasicPort instance_output_port(circuit_lib.port_lib_name(port), i, i);
+ port2port_name_map[circuit_lib.port_lib_name(port)] = instance_output_port;
+ }
+
+ /* Output an instance of the module */
+ print_verilog_module_instance(fp, module_manager, module_id, sram_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(sram_model));
+ /* IMPORTANT: this update MUST be called after the instance outputting!!!!
+ * update the module manager with the relationship between the parent and child modules
+ */
+ module_manager.add_child_module(module_id, sram_module_id);
+ }
+
+ /* Put an end to the Verilog module */
+ print_verilog_module_end(fp, module_name);
+}
+
+/*********************************************************************
+ * Scan-chain organization
+ *
+ * +-------+ +-------+ +-------+
+ * scan-chain--->| CCFF |--->| CCFF |--->... --->| CCFF |---->scan-chain
+ * input&clock | [0] | | [1] | | [N-1] | output
+ * +-------+ +-------+ +-------+
+ * | | ... |
+ * v v v
+ * +-----------------------------------------+
+ * | Multiplexer Configuration port |
+ *
+ ********************************************************************/
+static
+void print_verilog_memory_chain_module(ModuleManager& module_manager,
+ const CircuitLibrary& circuit_lib,
+ std::fstream& fp,
+ const std::string& module_name,
+ const CircuitModelId& sram_model,
+ const size_t& num_mems) {
+ /* Make sure we have a valid file handler*/
+ check_file_handler(fp);
+
+ /* Create a module and add to the module manager */
+ ModuleId module_id = module_manager.add_module(module_name);
+ VTR_ASSERT(ModuleId::INVALID() != module_id);
+ /* Get the global ports required by the SRAM */
+ std::vector global_port_types;
+ global_port_types.push_back(SPICE_MODEL_PORT_CLOCK);
+ global_port_types.push_back(SPICE_MODEL_PORT_INPUT);
+ std::vector sram_global_ports = circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, false);
+ /* Get the input ports from the SRAM */
+ std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_INPUT, true);
+ /* Should have only 1 input port */
+ VTR_ASSERT( 1 == sram_input_ports.size() );
+ /* Get the output ports from the SRAM */
+ std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_OUTPUT, true);
+ /* Should have only 1 or 2 output port */
+ VTR_ASSERT( (1 == sram_output_ports.size()) || ( 2 == sram_output_ports.size()) );
+
+ /* Add module ports: the ports come from the SRAM modules */
+ /* Add each global port */
+ for (const auto& port : sram_global_ports) {
+ /* Configure each global port: global ports are shared among the SRAMs, so it is independent from the memory size */
+ BasicPort global_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
+ module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT);
+ }
+ /* Add an input port, which is the head of configuration chain in the module */
+ /* TODO: restriction!!!
+ * consider only the first input of the CCFF model as the D port,
+ * which will be connected to the head of the chain
+ */
+ BasicPort chain_head_port(generate_configuration_chain_head_name(),
+ circuit_lib.port_size(sram_input_ports[0]));
+ module_manager.add_port(module_id, chain_head_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add an output port, which is the tail of configuration chain in the module */
+ /* TODO: restriction!!!
+ * consider only the first output of the CCFF model as the Q port,
+ * which will be connected to the tail of the chain
+ */
+ BasicPort chain_tail_port(generate_configuration_chain_tail_name(),
+ circuit_lib.port_size(sram_output_ports[0]));
+ module_manager.add_port(module_id, chain_tail_port, ModuleManager::MODULE_INPUT_PORT);
+ /* Add each output port: port width should match the number of memories */
+ for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) {
+ std::string port_name;
+ if (0 == iport) {
+ port_name = generate_configuration_chain_data_out_name();
+ } else {
+ VTR_ASSERT( 1 == iport);
+ port_name = generate_configuration_chain_inverted_data_out_name();
+ }
+ BasicPort output_port(port_name, num_mems);
+ module_manager.add_port(module_id, output_port, ModuleManager::MODULE_OUTPUT_PORT);
+ }
+
+ /* dump module definition + ports */
+ print_verilog_module_declaration(fp, module_manager, module_id);
+ /* Finish dumping ports */
+
+ /* Find the sram module in the module manager */
+ ModuleId sram_module_id = module_manager.find_module(circuit_lib.model_name(sram_model));
+
+ /* Instanciate each submodule */
+ for (size_t i = 0; i < num_mems; ++i) {
+ /* Create a port-to-port map */
+ std::map port2port_name_map;
+ /* Map instance inputs [i] to SRAM module input */
+ for (const auto& port : sram_input_ports) {
+ BasicPort instance_input_port(circuit_lib.port_lib_name(port), i, i);
+ port2port_name_map[circuit_lib.port_lib_name(port)] = instance_input_port;
+ }
+ /* Map instance outputs [i] to SRAM module input */
+ for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) {
+ std::string port_name;
+ if (0 == iport) {
+ port_name = generate_configuration_chain_data_out_name();
+ } else {
+ VTR_ASSERT( 1 == iport);
+ port_name = generate_configuration_chain_inverted_data_out_name();
+ }
+ BasicPort instance_output_port(port_name, i, i);
+ port2port_name_map[circuit_lib.port_lib_name(sram_output_ports[iport])] = instance_output_port;
+ }
+
+ /* Output an instance of the module */
+ print_verilog_module_instance(fp, module_manager, module_id, sram_module_id, port2port_name_map, circuit_lib.dump_explicit_port_map(sram_model));
+ /* IMPORTANT: this update MUST be called after the instance outputting!!!!
+ * update the module manager with the relationship between the parent and child modules
+ */
+ module_manager.add_child_module(module_id, sram_module_id);
+ }
+
+ /* Wire the memory cells into a chain
+ * The head of the chain will be wired to the input port of the first CCFF
+ * The tail of the chain will be wired to the output port of the last CCFF
+ * The output of each CCFF will be wired to the input of the next CCFFF in the chain
+ */
+ BasicPort first_ccff_input_port(circuit_lib.port_lib_name(sram_input_ports[0]), 0, 0);
+ print_verilog_wire_connection(fp, first_ccff_input_port, chain_head_port, false);
+
+ BasicPort last_ccff_output_port(generate_configuration_chain_data_out_name(), num_mems - 1, num_mems - 1);
+ print_verilog_wire_connection(fp, chain_tail_port, last_ccff_output_port, false);
+
+ BasicPort chain_output_port(generate_configuration_chain_data_out_name(), 0, num_mems - 2);
+ BasicPort chain_input_port(circuit_lib.port_lib_name(sram_input_ports[0]), 1, num_mems - 1);
+ print_verilog_wire_connection(fp, chain_input_port, chain_output_port, false);
+
+ /* Put an end to the Verilog module */
+ print_verilog_module_end(fp, module_name);
+}
+
+/*********************************************************************
+ * Memory bank organization
+ *
+ * Bit lines(BL/BLB) Word lines (WL/WLB)
+ * | |
+ * v v
+ * +------------------------------------+
+ * | Memory Module Configuration port |
+ * +------------------------------------+
+ * | | |
+ * v v v
+ * +-------+ +-------+ +-------+
+ * | SRAM | | SRAM | ... | SRAM |
+ * | [0] | | [1] | | [N-1] |
+ * +-------+ +-------+ +-------+
+ * | | ... |
+ * v v v
+ * +------------------------------------+
+ * | Multiplexer Configuration port |
+ *
+ ********************************************************************/
+static
+void print_verilog_memory_bank_module(ModuleManager& module_manager,
+ const CircuitLibrary& circuit_lib,
+ std::fstream& fp,
+ const std::string& module_name,
+ const CircuitModelId& sram_model,
+ const size_t& num_mems) {
+ /* Make sure we have a valid file handler*/
+ check_file_handler(fp);
+
+ /* Create a module and add to the module manager */
+ ModuleId module_id = module_manager.add_module(module_name);
+ VTR_ASSERT(ModuleId::INVALID() != module_id);
+ /* Get the global ports required by the SRAM */
+ std::vector global_port_types;
+ global_port_types.push_back(SPICE_MODEL_PORT_CLOCK);
+ global_port_types.push_back(SPICE_MODEL_PORT_INPUT);
+ std::vector sram_global_ports = circuit_lib.model_global_ports_by_type(sram_model, global_port_types, true, false);
+ /* Get the input ports from the SRAM */
+ std::vector sram_input_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_INPUT, true);
+ /* A SRAM cell with BL/WL should not have any input */
+ VTR_ASSERT( 0 == sram_input_ports.size() );
+ /* Get the output ports from the SRAM */
+ std::vector sram_output_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_OUTPUT, true);
/* Get the BL/WL ports from the SRAM */
std::vector sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_BL, true);
std::vector sram_blb_ports = circuit_lib.model_ports_by_type(sram_model, SPICE_MODEL_PORT_BLB, true);
@@ -133,7 +308,7 @@ void print_verilog_memory_module(ModuleManager& module_manager,
BasicPort global_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
module_manager.add_port(module_id, global_port, ModuleManager::MODULE_GLOBAL_PORT);
}
- /* Add each input port: port width should match the number of memories */
+ /* Add each input port */
for (const auto& port : sram_input_ports) {
BasicPort input_port(circuit_lib.port_lib_name(port), num_mems);
module_manager.add_port(module_id, input_port, ModuleManager::MODULE_INPUT_PORT);
@@ -208,10 +383,52 @@ void print_verilog_memory_module(ModuleManager& module_manager,
module_manager.add_child_module(module_id, sram_module_id);
}
+ /* TODO: if a local memory decoder is required, instanciate it here */
+
/* Put an end to the Verilog module */
print_verilog_module_end(fp, module_name);
}
+
+/*********************************************************************
+ * Generate Verilog modules for the memories that are used
+ * by a circuit model
+ * The organization of memory circuit will depend on the style of
+ * configuration protocols
+ * Currently, we support
+ * 1. Flat SRAM organization
+ * 2. Configuration chain
+ * 3. Memory bank (memory decoders)
+ ********************************************************************/
+static
+void print_verilog_memory_module(ModuleManager& module_manager,
+ const CircuitLibrary& circuit_lib,
+ const e_sram_orgz& sram_orgz_type,
+ std::fstream& fp,
+ const std::string& module_name,
+ const CircuitModelId& sram_model,
+ const size_t& num_mems) {
+ switch (sram_orgz_type) {
+ case SPICE_SRAM_STANDALONE:
+ print_verilog_memory_standalone_module(module_manager, circuit_lib, fp,
+ module_name, sram_model, num_mems);
+ break;
+ case SPICE_SRAM_SCAN_CHAIN:
+ print_verilog_memory_chain_module(module_manager, circuit_lib, fp,
+ module_name, sram_model, num_mems);
+ break;
+ case SPICE_SRAM_MEMORY_BANK:
+ print_verilog_memory_bank_module(module_manager, circuit_lib, fp,
+ module_name, sram_model, num_mems);
+ break;
+ default:
+ vpr_printf(TIO_MESSAGE_ERROR,
+ "(File:%s, LINE%d) Invalid SRAM organization!\n",
+ __FILE__, __LINE__);
+ }
+}
+
+
/*********************************************************************
* Generate Verilog modules for the memories that are used
* by multiplexers
@@ -228,28 +445,27 @@ void print_verilog_memory_module(ModuleManager& module_manager,
static
void print_verilog_mux_memory_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
+ const e_sram_orgz& sram_orgz_type,
std::fstream& fp,
const CircuitModelId& mux_model,
const MuxGraph& mux_graph) {
+ /* Find the actual number of configuration bits, based on the mux graph
+ * Due to the use of local decoders inside mux, this may be
+ */
+ size_t num_config_bits = find_mux_num_config_bits(circuit_lib, mux_model, mux_graph, sram_orgz_type);
/* Multiplexers built with different technology is in different organization */
switch (circuit_lib.design_tech_type(mux_model)) {
case SPICE_MODEL_DESIGN_CMOS: {
/* Generate module name */
- std::string module_name = generate_verilog_mux_subckt_name(circuit_lib, mux_model,
- find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()),
- std::string(verilog_mem_posfix));
+ std::string module_name = generate_mux_subckt_name(circuit_lib, mux_model,
+ find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()),
+ std::string(verilog_mem_posfix));
/* Get the sram ports from the mux */
- std::vector mux_sram_ports = circuit_lib.model_ports_by_type(mux_model, SPICE_MODEL_PORT_SRAM, true);
- VTR_ASSERT( 1 == mux_sram_ports.size() );
- /* Get the circuit model for the memory circuit used by the multiplexer */
- CircuitModelId sram_model = circuit_lib.port_tri_state_model(mux_sram_ports[0]);
- VTR_ASSERT(CircuitModelId::INVALID() != sram_model);
+ std::vector sram_models = find_circuit_sram_models(circuit_lib, mux_model);
+ VTR_ASSERT( 1 == sram_models.size() );
- /* Find the number of SRAMs in the module, this is also the port width */
- size_t num_mems = mux_graph.num_memory_bits();
-
- print_verilog_memory_module(module_manager, circuit_lib, fp, module_name, sram_model, num_mems);
+ print_verilog_memory_module(module_manager, circuit_lib, sram_orgz_type, fp, module_name, sram_models[0], num_config_bits);
break;
}
case SPICE_MODEL_DESIGN_RRAM:
@@ -286,6 +502,7 @@ void print_verilog_mux_memory_module(ModuleManager& module_manager,
void print_verilog_submodule_memories(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
+ const e_sram_orgz& sram_orgz_type,
const std::string& verilog_dir,
const std::string& submodule_dir) {
/* Plug in with the mux subckt */
@@ -319,7 +536,7 @@ void print_verilog_submodule_memories(ModuleManager& module_manager,
continue;
}
/* Create a Verilog module for the memories used by the multiplexer */
- print_verilog_mux_memory_module(module_manager, circuit_lib, fp, mux_model, mux_graph);
+ print_verilog_mux_memory_module(module_manager, circuit_lib, sram_orgz_type, fp, mux_model, mux_graph);
}
/* Create the memory circuits for non-MUX circuit models.
@@ -361,7 +578,7 @@ void print_verilog_submodule_memories(ModuleManager& module_manager,
std::string module_name = generate_memory_module_name(circuit_lib, model, sram_models[0], std::string(verilog_mem_posfix));
/* Create a Verilog module for the memories used by the circuit model */
- print_verilog_memory_module(module_manager, circuit_lib, fp, module_name, sram_models[0], num_mems);
+ print_verilog_memory_module(module_manager, circuit_lib, sram_orgz_type, fp, module_name, sram_models[0], num_mems);
}
/* Close the file stream */
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.h
index 08ecc4ec3..eee29cb23 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.h
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_memory.h
@@ -16,6 +16,7 @@
void print_verilog_submodule_memories(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
+ const e_sram_orgz& sram_orgz_type,
const std::string& verilog_dir,
const std::string& submodule_dir);
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp
index 3244cce1b..0f4b10579 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_mux.cpp
@@ -17,6 +17,8 @@
#include "physical_types.h"
#include "vpr_types.h"
#include "mux_utils.h"
+#include "circuit_library_utils.h"
+#include "decoder_library_utils.h"
/* FPGA-X2P context header files */
#include "spice_types.h"
@@ -691,7 +693,7 @@ void generate_verilog_mux_branch_module(ModuleManager& module_manager,
const CircuitModelId& circuit_model,
const size_t& mux_size,
const MuxGraph& mux_graph) {
- std::string module_name = generate_verilog_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, mux_graph.num_inputs(), verilog_mux_basis_posfix);
+ std::string module_name = generate_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, mux_graph.num_inputs(), verilog_mux_basis_posfix);
/* Multiplexers built with different technology is in different organization */
switch (circuit_lib.design_tech_type(circuit_model)) {
@@ -760,13 +762,13 @@ void generate_verilog_cmos_mux_module_mux2_multiplexing_structure(ModuleManager&
/* Print local wires which are the nodes in the mux graph */
for (size_t level = 0; level < mux_graph.num_levels(); ++level) {
/* Print the internal wires located at this level */
- BasicPort internal_wire_port(generate_verilog_mux_node_name(level, false), mux_graph.num_nodes_at_level(level));
+ BasicPort internal_wire_port(generate_mux_node_name(level, false), mux_graph.num_nodes_at_level(level));
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_port) << ";" << std::endl;
/* Identify if an intermediate buffer is needed */
if (false == inter_buffer_location_map[level]) {
continue;
}
- BasicPort internal_wire_buffered_port(generate_verilog_mux_node_name(level, true), mux_graph.num_nodes_at_level(level));
+ BasicPort internal_wire_buffered_port(generate_mux_node_name(level, true), mux_graph.num_nodes_at_level(level));
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_buffered_port) << std::endl;
}
print_verilog_comment(fp, std::string("---- END Internal wires of a CMOS MUX module -----"));
@@ -832,7 +834,7 @@ void generate_verilog_cmos_mux_module_mux2_multiplexing_structure(ModuleManager&
/* Generate the port info of each input node */
size_t input_node_level = mux_graph.node_level(input_node);
size_t input_node_index_at_level = mux_graph.node_index_at_level(input_node);
- BasicPort instance_input_port(generate_verilog_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level);
+ BasicPort instance_input_port(generate_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level);
/* Link nodes to input ports for the branch module */
std::string module_input_port_name = circuit_lib.port_lib_name(std_cell_input_ports[&input_node - &input_nodes[0]]);
@@ -841,7 +843,7 @@ void generate_verilog_cmos_mux_module_mux2_multiplexing_structure(ModuleManager&
/* Build the link between output_node[0] and std_cell_output_port[0] */
{ /* Create a code block to accommodate the local variables */
- BasicPort instance_output_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort instance_output_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
std::string module_output_port_name = circuit_lib.port_lib_name(std_cell_output_ports[0]);
port2port_name_map[module_output_port_name] = instance_output_port;
}
@@ -853,6 +855,10 @@ void generate_verilog_cmos_mux_module_mux2_multiplexing_structure(ModuleManager&
/* Generate the port info of each mem node */
BasicPort instance_mem_port(circuit_lib.port_lib_name(mux_regular_sram_ports[0]), size_t(mem), size_t(mem));
std::string module_mem_port_name = circuit_lib.port_lib_name(std_cell_input_ports[2]);
+ /* If use local decoders, we should use another name for the mem port */
+ if (true == circuit_lib.mux_use_local_encoder(circuit_model)) {
+ instance_mem_port.set_name(generate_mux_local_decoder_data_port_name());
+ }
port2port_name_map[module_mem_port_name] = instance_mem_port;
}
@@ -876,8 +882,8 @@ void generate_verilog_cmos_mux_module_mux2_multiplexing_structure(ModuleManager&
/* We must have a valid model id */
VTR_ASSERT(CircuitModelId::INVALID() != buffer_model);
- BasicPort buffer_instance_input_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
- BasicPort buffer_instance_output_port(generate_verilog_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level);
+ BasicPort buffer_instance_input_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort buffer_instance_output_port(generate_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level);
print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, buffer_model, buffer_instance_input_port, buffer_instance_output_port);
@@ -910,19 +916,8 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
/* Find the actual mux size */
size_t mux_size = find_mux_num_datapath_inputs(circuit_lib, circuit_model, mux_graph.num_inputs());
- /* TODO: these are duplicated codes, find a way to simplify it!!!
- * Get the regular (non-mode-select) sram ports from the mux
- */
- std::vector mux_regular_sram_ports;
- for (const auto& port : circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_SRAM, true)) {
- /* Multiplexing structure does not mode_sram_ports, they are handled in LUT modules
- * Here we just bypass it.
- */
- if (true == circuit_lib.port_is_mode_select(port)) {
- continue;
- }
- mux_regular_sram_ports.push_back(port);
- }
+ /* Get the regular (non-mode-select) sram ports from the mux */
+ std::vector mux_regular_sram_ports = find_circuit_regular_sram_ports(circuit_lib, circuit_model);
VTR_ASSERT(1 == mux_regular_sram_ports.size());
/* Build the location map of intermediate buffers */
@@ -934,13 +929,13 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
/* Print local wires which are the nodes in the mux graph */
for (size_t level = 0; level < mux_graph.num_levels(); ++level) {
/* Print the internal wires located at this level */
- BasicPort internal_wire_port(generate_verilog_mux_node_name(level, false), mux_graph.num_nodes_at_level(level));
+ BasicPort internal_wire_port(generate_mux_node_name(level, false), mux_graph.num_nodes_at_level(level));
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_port) << ";" << std::endl;
/* Identify if an intermediate buffer is needed */
if (false == inter_buffer_location_map[level]) {
continue;
}
- BasicPort internal_wire_buffered_port(generate_verilog_mux_node_name(level, true), mux_graph.num_nodes_at_level(level));
+ BasicPort internal_wire_buffered_port(generate_mux_node_name(level, true), mux_graph.num_nodes_at_level(level));
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_buffered_port) << std::endl;
}
print_verilog_comment(fp, std::string("---- END Internal wires of a CMOS MUX module -----"));
@@ -982,7 +977,7 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
/* Instanciate the branch module which is a tgate-based module
*/
- std::string branch_module_name= generate_verilog_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, branch_size, verilog_mux_basis_posfix);
+ std::string branch_module_name= generate_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, branch_size, verilog_mux_basis_posfix);
/* Get the moduleId for the submodule */
ModuleId branch_module_id = module_manager.find_module(branch_module_name);
/* We must have one */
@@ -998,13 +993,13 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
/* Generate the port info of each input node */
size_t input_node_level = mux_graph.node_level(input_node);
size_t input_node_index_at_level = mux_graph.node_index_at_level(input_node);
- BasicPort branch_node_input_port(generate_verilog_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level);
+ BasicPort branch_node_input_port(generate_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level);
branch_node_input_ports.push_back(branch_node_input_port);
}
/* Create the port info for the input */
/* TODO: the naming could be more flexible? */
- BasicPort instance_input_port = generate_verilog_bus_port(branch_node_input_ports, std::string(generate_verilog_mux_node_name(output_node_level, false) + "_in"));
+ BasicPort instance_input_port = generate_verilog_bus_port(branch_node_input_ports, std::string(generate_mux_node_name(output_node_level, false) + "_in"));
/* If we have more than 1 port in the combined instance ports ,
* output a local wire */
if (1 < combine_verilog_ports(branch_node_input_ports).size()) {
@@ -1023,7 +1018,7 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
port2port_name_map[module_input_port.get_name()] = instance_input_port;
/* Link nodes to output ports for the branch module */
- BasicPort instance_output_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort instance_output_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
ModulePortId module_output_port_id = module_manager.find_module_port(branch_module_id, "out");
VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id);
/* Get the port from module */
@@ -1035,12 +1030,16 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
for (const auto& mem : mems) {
/* Generate the port info of each mem node */
BasicPort branch_node_mem_port(circuit_lib.port_lib_name(mux_regular_sram_ports[0]), size_t(mem), size_t(mem));
+ /* If use local decoders, we should use another name for the mem port */
+ if (true == circuit_lib.mux_use_local_encoder(circuit_model)) {
+ branch_node_mem_port.set_name(generate_mux_local_decoder_data_port_name());
+ }
branch_node_mem_ports.push_back(branch_node_mem_port);
}
/* Create the port info for the input */
/* TODO: the naming could be more flexible? */
- BasicPort instance_mem_port = generate_verilog_bus_port(branch_node_mem_ports, std::string(generate_verilog_mux_node_name(output_node_level, false) + "_mem"));
+ BasicPort instance_mem_port = generate_verilog_bus_port(branch_node_mem_ports, std::string(generate_mux_node_name(output_node_level, false) + "_mem"));
/* If we have more than 1 port in the combined instance ports ,
* output a local wire */
if (1 < combine_verilog_ports(branch_node_mem_ports).size()) {
@@ -1065,12 +1064,16 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
for (const auto& mem : mems) {
/* Generate the port info of each mem node */
BasicPort branch_node_mem_inv_port(circuit_lib.port_lib_name(mux_regular_sram_ports[0]) + "_inv", size_t(mem), size_t(mem));
+ /* If use local decoders, we should use another name for the mem port */
+ if (true == circuit_lib.mux_use_local_encoder(circuit_model)) {
+ branch_node_mem_inv_port.set_name(generate_mux_local_decoder_data_inv_port_name());
+ }
branch_node_mem_inv_ports.push_back(branch_node_mem_inv_port);
}
/* Create the port info for the input */
/* TODO: the naming could be more flexible? */
- BasicPort instance_mem_inv_port = generate_verilog_bus_port(branch_node_mem_inv_ports, std::string(generate_verilog_mux_node_name(output_node_level, false) + "_mem_inv"));
+ BasicPort instance_mem_inv_port = generate_verilog_bus_port(branch_node_mem_inv_ports, std::string(generate_mux_node_name(output_node_level, false) + "_mem_inv"));
/* If we have more than 1 port in the combined instance ports ,
* output a local wire */
if (1 < combine_verilog_ports(branch_node_mem_inv_ports).size()) {
@@ -1110,8 +1113,8 @@ void generate_verilog_cmos_mux_module_tgate_multiplexing_structure(ModuleManager
/* We must have a valid model id */
VTR_ASSERT(CircuitModelId::INVALID() != buffer_model);
- BasicPort buffer_instance_input_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
- BasicPort buffer_instance_output_port(generate_verilog_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level);
+ BasicPort buffer_instance_input_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort buffer_instance_output_port(generate_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level);
print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, buffer_model, buffer_instance_input_port, buffer_instance_output_port);
@@ -1167,7 +1170,7 @@ void generate_verilog_cmos_mux_module_input_buffers(ModuleManager& module_manage
BasicPort instance_input_port(module_input_port.get_name(), size_t(input_index), size_t(input_index));
/* Create the port information of the MUX graph input, which is the output of buffer instance */
- BasicPort instance_output_port(generate_verilog_mux_node_name(input_node_level, false), input_node_index_at_level, input_node_index_at_level);
+ BasicPort instance_output_port(generate_mux_node_name(input_node_level, false), input_node_index_at_level, input_node_index_at_level);
/* For last input:
* Add a constant value to the last input, if this MUX needs a constant input
@@ -1261,7 +1264,7 @@ void generate_verilog_cmos_mux_module_output_buffers(ModuleManager& module_manag
VTR_ASSERT(MuxNodeId::INVALID() != mux_graph.node_id(output_node_level, output_node_index_at_level));
/* Create the port information of the MUX input, which is the input of buffer instance */
- BasicPort instance_input_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort instance_input_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
/* Create the port information of the module output at the given pin range, which is the output of buffer instance */
BasicPort instance_output_port(module_output_port.get_name(), pin, pin);
@@ -1315,8 +1318,11 @@ void generate_verilog_cmos_mux_module(ModuleManager& module_manager,
std::vector mux_input_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_INPUT, true);
/* Get the output ports from the mux */
std::vector mux_output_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_OUTPUT, true);
- /* Get the sram ports from the mux */
- std::vector mux_sram_ports = circuit_lib.model_ports_by_type(circuit_model, SPICE_MODEL_PORT_SRAM, true);
+ /* Get the sram ports from the mux
+ * Multiplexing structure does not mode_sram_ports, they are handled in LUT modules
+ * Here we just bypass it.
+ */
+ std::vector mux_sram_ports = find_circuit_regular_sram_ports(circuit_lib, circuit_model);
/* Make sure we have a valid file handler*/
check_file_handler(fp);
@@ -1329,6 +1335,18 @@ void generate_verilog_cmos_mux_module(ModuleManager& module_manager,
/* Find out the number of memory bits */
size_t num_mems = mux_graph.num_memory_bits();
+ /* The size of of memory ports depend on
+ * if a local encoder is used for the mux or not
+ * Multiplexer local encoders are applied to memory bits at each stage
+ */
+ if (true == circuit_lib.mux_use_local_encoder(circuit_model)) {
+ num_mems = 0;
+ for (const auto& lvl : mux_graph.levels()) {
+ size_t data_size = mux_graph.num_memory_bits_at_level(lvl);
+ num_mems += find_mux_local_decoder_addr_size(data_size);
+ }
+ }
+
/* Check codes to ensure the port of Verilog netlists will match */
/* MUX graph must have only 1 output */
VTR_ASSERT(1 == mux_input_ports.size());
@@ -1383,12 +1401,6 @@ void generate_verilog_cmos_mux_module(ModuleManager& module_manager,
size_t sram_port_cnt = 0;
for (const auto& port : mux_sram_ports) {
- /* Multiplexing structure does not mode_sram_ports, they are handled in LUT modules
- * Here we just bypass it.
- */
- if (true == circuit_lib.port_is_mode_select(port)) {
- continue;
- }
BasicPort mem_port(circuit_lib.port_lib_name(port), num_mems);
module_manager.add_port(module_id, mem_port, ModuleManager::MODULE_INPUT_PORT);
BasicPort mem_inv_port(std::string(circuit_lib.port_lib_name(port) + "_inv"), num_mems);
@@ -1396,11 +1408,56 @@ void generate_verilog_cmos_mux_module(ModuleManager& module_manager,
/* Update counter */
sram_port_cnt++;
}
+ VTR_ASSERT(1 == sram_port_cnt);
/* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id);
- /* TODO: Print the internal logic in Verilog codes */
+ /* Add local decoder instance here */
+ if (true == circuit_lib.mux_use_local_encoder(circuit_model)) {
+ BasicPort decoder_data_port(generate_mux_local_decoder_data_port_name(), mux_graph.num_memory_bits());
+ BasicPort decoder_data_inv_port(generate_mux_local_decoder_data_inv_port_name(), mux_graph.num_memory_bits());
+ /* Print local wires to bridge the port of module and memory inputs
+ * of each MUX branch instance
+ */
+ fp << generate_verilog_port(VERILOG_PORT_WIRE, decoder_data_port) << ";" << std::endl;
+ fp << generate_verilog_port(VERILOG_PORT_WIRE, decoder_data_inv_port) << ";" << std::endl;
+
+ /* Local port to record the LSB and MSB of each level, here, we deposite (0, 0) */
+ BasicPort lvl_addr_port(circuit_lib.port_lib_name(mux_sram_ports[0]), 0);
+ BasicPort lvl_data_port(decoder_data_port.get_name(), 0);
+ BasicPort lvl_data_inv_port(decoder_data_inv_port.get_name(), 0);
+ for (const auto& lvl : mux_graph.levels()) {
+ size_t addr_size = find_mux_local_decoder_addr_size(mux_graph.num_memory_bits_at_level(lvl));
+ size_t data_size = mux_graph.num_memory_bits_at_level(lvl);
+ /* Update the LSB and MSB of addr and data port for the current level */
+ lvl_addr_port.rotate(addr_size);
+ lvl_data_port.rotate(data_size);
+ lvl_data_inv_port.rotate(data_size);
+ /* Print the instance of local decoder */
+ std::string decoder_module_name = generate_mux_local_decoder_subckt_name(addr_size, data_size);
+ ModuleId decoder_module = module_manager.find_module(decoder_module_name);
+ VTR_ASSERT(ModuleId::INVALID() != decoder_module);
+
+ /* Create a port-to-port map */
+ std::map decoder_port2port_name_map;
+ decoder_port2port_name_map[generate_mux_local_decoder_addr_port_name()] = lvl_addr_port;
+ decoder_port2port_name_map[generate_mux_local_decoder_data_port_name()] = lvl_data_port;
+ decoder_port2port_name_map[generate_mux_local_decoder_data_inv_port_name()] = lvl_data_inv_port;
+
+ /* Print an instance of the MUX Module */
+ print_verilog_comment(fp, std::string("----- BEGIN Instanciation of a local decoder -----"));
+ print_verilog_module_instance(fp, module_manager, module_id, decoder_module, decoder_port2port_name_map, circuit_lib.dump_explicit_port_map(circuit_model));
+ print_verilog_comment(fp, std::string("----- END Instanciation of a local decoder -----"));
+ fp << std::endl;
+ /* IMPORTANT: this update MUST be called after the instance outputting!!!!
+ * update the module manager with the relationship between the parent and child modules
+ */
+ module_manager.add_child_module(module_id, decoder_module);
+ }
+ }
+
+ /* Print the internal logic in Verilog codes */
/* Print the Multiplexing structure in Verilog codes
* Separated generation strategy on using standard cell MUX2 or TGATE,
* 1. MUX2 has a fixed port map: input_port[0] and input_port[1] is the data_path input
@@ -1467,13 +1524,13 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
/* Print local wires which are the nodes in the mux graph */
for (size_t level = 0; level < mux_graph.num_levels(); ++level) {
/* Print the internal wires located at this level */
- BasicPort internal_wire_port(generate_verilog_mux_node_name(level, false), mux_graph.num_nodes_at_level(level));
+ BasicPort internal_wire_port(generate_mux_node_name(level, false), mux_graph.num_nodes_at_level(level));
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_port) << ";" << std::endl;
/* Identify if an intermediate buffer is needed */
if (false == inter_buffer_location_map[level]) {
continue;
}
- BasicPort internal_wire_buffered_port(generate_verilog_mux_node_name(level, true), mux_graph.num_nodes_at_level(level));
+ BasicPort internal_wire_buffered_port(generate_mux_node_name(level, true), mux_graph.num_nodes_at_level(level));
fp << "\t" << generate_verilog_port(VERILOG_PORT_WIRE, internal_wire_buffered_port) << std::endl;
}
print_verilog_comment(fp, std::string("---- END Internal wires of a RRAM-based MUX module -----"));
@@ -1515,7 +1572,7 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
/* Instanciate the branch module which is a tgate-based module
*/
- std::string branch_module_name= generate_verilog_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, branch_size, verilog_mux_basis_posfix);
+ std::string branch_module_name= generate_mux_branch_subckt_name(circuit_lib, circuit_model, mux_size, branch_size, verilog_mux_basis_posfix);
/* Get the moduleId for the submodule */
ModuleId branch_module_id = module_manager.find_module(branch_module_name);
/* We must have one */
@@ -1531,13 +1588,13 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
/* Generate the port info of each input node */
size_t input_node_level = mux_graph.node_level(input_node);
size_t input_node_index_at_level = mux_graph.node_index_at_level(input_node);
- BasicPort branch_node_input_port(generate_verilog_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level);
+ BasicPort branch_node_input_port(generate_mux_node_name(input_node_level, inter_buffer_location_map[input_node_level]), input_node_index_at_level, input_node_index_at_level);
branch_node_input_ports.push_back(branch_node_input_port);
}
/* Create the port info for the input */
/* TODO: the naming could be more flexible? */
- BasicPort instance_input_port = generate_verilog_bus_port(branch_node_input_ports, std::string(generate_verilog_mux_node_name(output_node_level, false) + "_in"));
+ BasicPort instance_input_port = generate_verilog_bus_port(branch_node_input_ports, std::string(generate_mux_node_name(output_node_level, false) + "_in"));
/* If we have more than 1 port in the combined instance ports ,
* output a local wire */
if (1 < combine_verilog_ports(branch_node_input_ports).size()) {
@@ -1556,7 +1613,7 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
port2port_name_map[module_input_port.get_name()] = instance_input_port;
/* Link nodes to output ports for the branch module */
- BasicPort instance_output_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort instance_output_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
ModulePortId module_output_port_id = module_manager.find_module_port(branch_module_id, "out");
VTR_ASSERT(ModulePortId::INVALID() != module_output_port_id);
/* Get the port from module */
@@ -1589,7 +1646,7 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
/* Create the port info for the input */
/* TODO: the naming could be more flexible? */
- BasicPort instance_blb_port = generate_verilog_bus_port(branch_node_blb_ports, std::string(generate_verilog_mux_node_name(output_node_level, false) + "_blb"));
+ BasicPort instance_blb_port = generate_verilog_bus_port(branch_node_blb_ports, std::string(generate_mux_node_name(output_node_level, false) + "_blb"));
/* If we have more than 1 port in the combined instance ports ,
* output a local wire */
if (1 < combine_verilog_ports(branch_node_blb_ports).size()) {
@@ -1630,7 +1687,7 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
/* Create the port info for the WL */
/* TODO: the naming could be more flexible? */
- BasicPort instance_wl_port = generate_verilog_bus_port(branch_node_wl_ports, std::string(generate_verilog_mux_node_name(output_node_level, false) + "_wl"));
+ BasicPort instance_wl_port = generate_verilog_bus_port(branch_node_wl_ports, std::string(generate_mux_node_name(output_node_level, false) + "_wl"));
/* If we have more than 1 port in the combined instance ports ,
* output a local wire */
if (1 < combine_verilog_ports(branch_node_wl_ports).size()) {
@@ -1669,8 +1726,8 @@ void generate_verilog_rram_mux_module_multiplexing_structure(ModuleManager& modu
/* We must have a valid model id */
VTR_ASSERT(CircuitModelId::INVALID() != buffer_model);
- BasicPort buffer_instance_input_port(generate_verilog_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
- BasicPort buffer_instance_output_port(generate_verilog_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level);
+ BasicPort buffer_instance_input_port(generate_mux_node_name(output_node_level, false), output_node_index_at_level, output_node_index_at_level);
+ BasicPort buffer_instance_output_port(generate_mux_node_name(output_node_level, true), output_node_index_at_level, output_node_index_at_level);
print_verilog_buffer_instance(fp, module_manager, circuit_lib, module_id, buffer_model, buffer_instance_input_port, buffer_instance_output_port);
@@ -1825,9 +1882,9 @@ void generate_verilog_mux_module(ModuleManager& module_manager,
std::fstream& fp,
const CircuitModelId& circuit_model,
const MuxGraph& mux_graph) {
- std::string module_name = generate_verilog_mux_subckt_name(circuit_lib, circuit_model,
- find_mux_num_datapath_inputs(circuit_lib, circuit_model, mux_graph.num_inputs()),
- std::string(""));
+ std::string module_name = generate_mux_subckt_name(circuit_lib, circuit_model,
+ find_mux_num_datapath_inputs(circuit_lib, circuit_model, mux_graph.num_inputs()),
+ std::string(""));
/* Multiplexers built with different technology is in different organization */
switch (circuit_lib.design_tech_type(circuit_model)) {
diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c
index d124f3b05..d08f5eb15 100644
--- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c
+++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c
@@ -1,7 +1,7 @@
-/***********************************/
-/* SPICE Modeling for VPR */
-/* Xifan TANG, EPFL/LSI */
-/***********************************/
+/*********************************************************************
+ * This file includes functions that are used for
+ * Verilog generation of FPGA routing architecture (global routing)
+ *********************************************************************/
#include
#include
#include
@@ -11,6 +11,8 @@
#include
#include
#include
+#include