Merge branch 'dev' into std_map_support

This commit is contained in:
tangxifan 2019-08-06 14:38:19 -06:00
commit 55bfaf271d
20 changed files with 664 additions and 208 deletions

View File

@ -3,7 +3,7 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build-3.6
SPHINXBUILD = sphinx-build
SOURCEDIR = source
BUILDDIR = build

View File

@ -13,7 +13,7 @@ Inverters and Buffers
<port type="output" prefix="string" size="int"/>
</circuit_model>
.. note:: customized SPICE netlists are not currently supported for inverters and buffers.
.. note:: customized Verilog/SPICE netlists are not currently supported for inverters and buffers.
* design_technology:
@ -128,7 +128,7 @@ Pass-gate Logic
<port type="output" prefix="string" size="int"/>
</circuit_model>
.. note:: customized SPICE netlists are not currently supported for pass-gate logics.
.. note:: customized Verilog/SPICE netlists are not currently supported for pass-gate logics.
* design_technology:
@ -209,9 +209,9 @@ SRAMs
<port type="output" prefix="string" size="int"/>
</circuit_model>
.. note:: The circuit designs of SRAMs are highly dependent on the technology node and well optimized by engineers. Therefore, FPGA-SPICE requires users to provide their customized SRAM SPICE/Verilog netlists. A sample SPICE netlist of SRAM can be found in the directory SpiceNetlists in the released package. FPGA-SPICE assumes that all the LUTs and MUXes employ the SRAM circuit design. Therefore, currently only one SRAM type is allowed to be defined.
.. note:: The circuit designs of SRAMs are highly dependent on the technology node and well optimized by engineers. Therefore, FPGA-Verilog/SPICE requires users to provide their customized SRAM Verilog/SPICE/Verilog netlists. A sample Verilog/SPICE netlist of SRAM can be found in the directory SpiceNetlists in the released package. FPGA-Verilog/SPICE assumes that all the LUTs and MUXes employ the SRAM circuit design. Therefore, currently only one SRAM type is allowed to be defined.
.. note:: The information of input and output buffer should be clearly specified according to the customized SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
.. note:: The information of input and output buffer should be clearly specified according to the customized Verilog/SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
.. note:: The support SRAM modules should have a BL and a WL when the memory-bank-style configuration circuit is declared. Note that the WL should be the write/read enable signal, while BL is the data input.
@ -230,9 +230,9 @@ Logic gates
.. note:: The circuit model in the type of gate aims to support direct mapping to standard cells or customized cells provided by technology vendors or users.
.. note:: The logic functionality of a gate can be defined through the XML keyword topology. Currently, OpenFPGA supports AND, OR and MUX2 gates. As for standard cells, the size of each port is limited to 1. Currently, only 2-input and single-output logic gates are supported.
.. note:: The logic functionality of a gate can be defined through the XML keyword ``topology``. Currently, OpenFPGA supports AND, OR and MUX2 gates. As for standard cells, the size of each port is limited to 1. Currently, only 2-input and single-output logic gates are supported.
.. note:: It may happen that the port sequence in generated Verilog netlists has conflicts with the port sequence in standard and customized cells. To avoid this, users can set the XML keyword dump_explicit_port_map to be true, which enables explicit port mapping are dumped. Users can specify the pin/port name in the standard cell library using the XML keyword lib_name.
.. note:: It may happen that the port sequence in generated Verilog netlists has conflicts with the port sequence in standard and customized cells. To avoid this, users can set the XML keyword ``dump_explicit_port_map`` to be true, which enables explicit port mapping are dumped. Users can specify the pin/port name in the standard cell library using the XML keyword ``lib_name``.
Multiplexers
------------
@ -240,8 +240,7 @@ Multiplexers
.. code-block:: xml
<circuit_model type="mux" name="string" prefix="string" is_default="int">
<design_technology type="string" structure="string" num_level="int" ron="float" roff="float"
prog_transistor_size="float"/>
<design_technology type="string" structure="string" num_level="int" add_const_input="string" const_input_val="int" local_encoder="string" ron="float" roff="float" prog_transistor_size="float"/>
<input_buffer exist="string" circuit_model_name="string"/>
<output_buffer exist="string" circuit_model_name="string"/>
<pass_gate_logic type="string" circuit_model_name="string"/>
@ -250,24 +249,31 @@ Multiplexers
<port type="sram" prefix="string" size="int"/>
</circuit_model>
.. note:: customized SPICE netlists are not currently supported for multiplexers.
.. note:: customized Verilog/SPICE netlists are not currently supported for multiplexers.
* design_technology:
* **structure:** can be [tree|multi-level|one-level]. The structure options are valid for SRAM-based multiplexers. For RRAM-based multiplexers, currently we only support the circuit design in [5]. If *multi-level* the following parameter is required:
* **structure:** can be [``tree`` \| ``multi-level`` \| ``one-level``]. The structure options are valid for SRAM-based multiplexers. For RRAM-based multiplexers, currently we only support the circuit design in [5]. If ``multi-level`` the following parameter is required:
* **num_level:** specify the number of levels when multi-level structure is selected, only.
* **add_const_input:** can be [``true`` \| ``false``]. When enabled, an extra input will be added to the multiplexer circuits defined in this ``circuit_model``. For example, an 4-input multiplexer will be turned to a 5-input multiplexer. The extra input will be wired to a constant value, which can be specified through the XML syntax ``const_input_val``. The constant value can be either 0 or 1 (By default it is 0). Note that adding such input will help reducing the leakage power of FPGA and parasitic signal activities, with a limited area overhead.
* **const_input_val:** specify the constant value, to which the extra input will be connected. This syntax is only valid when the ``add_const_input`` is set to true.
* **local_encoder:** can be [``true`` \| ``false``]. When enabled, an local encoder will be added to the multiplexer circuits defined in this ``circuit_model``. The local encoder will be interface the SRAM inputs of multiplexing structure and SRAMs. It can encode the one-hot codes (that drive the select port of multiplexing structure) to a binary code. For example, 8-bit ``00000001`` will be encoded to 3-bit ``000``. This will help reduce the number of SRAM cells used in FPGAs as well as configuration time (especially for scan-chain configuration protocols). But it may cost an area overhead.
* **prog_transistor_size:** valid only when the type of design technology is rram. Specify the size of programming transistors used in the RRAM-based multiplexer, we use only n-type transistor and the size should be expressed in terms of the min_width defined in XML node <transistors>.
.. note:: Local encoders are only applicable for one-level and multi-level multiplexers. Tree-like multiplexers are already encoded in their nature.
* If type of design technology is **rram**, then the following parameters are required:
* **prog_transistor_size:** valid only when the type of design technology is ``rram``. Specify the size of programming transistors used in the RRAM-based multiplexer, we use only n-type transistor and the size should be expressed in terms of the min_width defined in XML node ``transistors``. If type of design technology is ``rram``, then the following parameters are required:
* **ron:** valid only when the type of design technology is rram. Specify the on-resistance of the RRAM device used in the RRAM-based multiplexer.
* **roff:** valid only when the type of design technology is rram. Specify the off-resistance of the RRAM device used in the RRAM-based multiplexer.
* port: for a multiplexer, the three types of ports, input, output and sram should be defined.
* port: for a multiplexer, the three types of ports, ``input``, ``output`` and ``sram`` should be defined.
.. note:: For tree-like multiplexers, they can be built with standard cell MUX2. To enable this, users should define a ``circuit_model``, which describes a 2-input multiplexer (See details and examples in how to define a logic gate using ``circuit_model``. In this case, the ``circuit_model_name`` in the ``pass_gate_logic`` should be the name of MUX2 ``circuit_model``.
**Mux 1 level example**
@ -349,9 +355,9 @@ Look-Up Tables
<port type="sram" prefix="string" size="int" mode_select="true|false" circuit_model_name="string" default_val="0|1"/>
</circuit_model>
.. note:: The SPICE netlists of LUT can be auto-generated or customized.
.. note:: The Verilog/SPICE netlists of LUT can be auto-generated or customized.
The auto-generated LUTs are based on a tree-like multiplexer, whose gates of the transistors are used as the inputs of LUTs and the drains/sources of the transistors are used for configurable memories (SRAMs).
The LUT provided in customized SPICE netlist should have the same decoding methodology as the traditional LUT.
The LUT provided in customized Verilog/SPICE netlist should have the same decoding methodology as the traditional LUT.
Additional design parameters for LUTs:
@ -369,7 +375,7 @@ Instructions of defining design parameters:
* **pass_gate_logic:** Specify the pass-gates of the internal multiplexer, the same as the multiplexers.
* **port:** three types of ports (input, output and sram) should be defined. If the user provides an customized SPICE netlist, the bandwidth of ports should be defined to the same as the SPICE netlist. To support customizable LUTs, each type of port contain special keywords. For input ports, the keyword tri_state_map aims to customize which inputs are fixed to constant values when the LUT is in fracturable modes. For example, tri_state_map="----11" indicates that the last two inputs will be fixed to be logic '1' when a 6-input LUT is in fracturable modes. The circuit_model_name of input port is used to specify which logic gates will be used to tri-state the inputs in fracturable LUT modes. It is required to use an AND gate to force logic '0' or an OR gate to force logic '1' for the input ports. For output ports, the keyword lut_frac_level is used to specify the level in LUT multiplexer tree where the output port are wired to. For example, lut_frac_level="4" in a fracturable LUT6 means that the output are potentially wired to the 4th stage of a LUT multiplexer and it is an output of a LUT4. The keyword lut_output_mask describes which fracturable outputs are used. For instance, in a 6-LUT, there are potentially four LUT4 outputs can be wired out. lut_output_mask="0,2" indicates that only the first and the thrid LUT4 outputs will be used in fracturable mode. Note that the size of the output port should be consistent to the length of lut_output_mask.
* **port:** three types of ports (input, output and sram) should be defined. If the user provides an customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist. To support customizable LUTs, each type of port contain special keywords. For input ports, the keyword tri_state_map aims to customize which inputs are fixed to constant values when the LUT is in fracturable modes. For example, tri_state_map="----11" indicates that the last two inputs will be fixed to be logic '1' when a 6-input LUT is in fracturable modes. The circuit_model_name of input port is used to specify which logic gates will be used to tri-state the inputs in fracturable LUT modes. It is required to use an AND gate to force logic '0' or an OR gate to force logic '1' for the input ports. For output ports, the keyword lut_frac_level is used to specify the level in LUT multiplexer tree where the output port are wired to. For example, lut_frac_level="4" in a fracturable LUT6 means that the output are potentially wired to the 4th stage of a LUT multiplexer and it is an output of a LUT4. The keyword lut_output_mask describes which fracturable outputs are used. For instance, in a 6-LUT, there are potentially four LUT4 outputs can be wired out. lut_output_mask="0,2" indicates that only the first and the thrid LUT4 outputs will be used in fracturable mode. Note that the size of the output port should be consistent to the length of lut_output_mask.
* **SRAM port for mode selection:** To enable switch between different operating modes, the SRAM bits of a fracturable LUT consists of two parts: configuration memory and mode selecting. The SRAM port for mode selection is specified through the XML keyword mode_select. Note that the size of such SRAM port should be consistent to the number of 1s or 0s in the tri_state_map.
@ -400,7 +406,7 @@ The code describing this LUT is:
</circuit_model>
**This example shows:**
* The difference between *input_buffer* and *lut_input_buffer* and that they are independent.
* The difference between ``input_buffer`` and ``lut_input_buffer`` and that they are independent.
* How each blocks is defined
Flip-Flops
@ -417,17 +423,17 @@ Flip-Flops
<port type="clock" prefix="string" size="int"/>
</circuit_model>
.. note:: The circuit designs of flip-flops are highly dependent on the technology node and well optimized by engineers. Therefore, FPGA-SPICE requires users to provide their customized FF SPICE/Verilog netlists. A sample SPICE netlist of FF can be found in the directory SpiceNetlists in the released package.
.. note:: The circuit designs of flip-flops are highly dependent on the technology node and well optimized by engineers. Therefore, FPGA-Verilog/SPICE requires users to provide their customized FF Verilog/SPICE/Verilog netlists. A sample Verilog/SPICE netlist of FF can be found in the directory SpiceNetlists in the released package.
The information of input and output buffer should be clearly specified according to the customized SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
The information of input and output buffer should be clearly specified according to the customized Verilog/SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
FPGA-SPICE currently support only one clock domain in the FPGA. Therefore there should be only one clock port to be defined and the size of the clock port should be 1.
FPGA-Verilog/SPICE currently support only one clock domain in the FPGA. Therefore there should be only one clock port to be defined and the size of the clock port should be 1.
Instructions of defining design parameters:
* **circuit_model type:** can be ff or scff. FF is typical Flip-Flop, SCFF is Scan-Chain Flip-Flop
* **port:** three types of ports (input, output and clock) should be defined. If the user provides a customized SPICE netlist, the bandwidth of ports should be defined to the same as the SPICE netlist.
* **port:** three types of ports (input, output and clock) should be defined. If the user provides a customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
**FF example**
@ -454,9 +460,9 @@ The code describing this FF is:
</circuit_model>
**This example shows:**
* Circuit model type as ff
* The verilog netlist file associated to this component *ff.v*
* 3 ports, *Set*, *Reset* and *clk*, defined as global
* Circuit model type as ``ff``
* The verilog netlist file associated to this component ``ff.v``
* 3 ports, ``Set``, ``Reset`` and ``clk``, defined as global
**SCFF example**
@ -481,9 +487,9 @@ The code describing this FF is:
</circuit_model>
**This example shows:**
* Circuit model type as scff
* The verilog netlist file associated to this component *scff.v*
* 1 port, *clk*, defined as global
* Circuit model type as ``scff``
* The verilog netlist file associated to this component ``scff.v``
* 1 port, ``clk``, defined as global
Hard Logics
-----------
@ -501,18 +507,18 @@ Hard Logics
.. note:: Hard logics are defined for non-configurable resources in FPGA architectures, such as adders, multipliers and RAM blocks.
Their circuit designs are highly dependent on the technology node and well optimized by engineers.
As more functional units are included in FPGA architecture, it is impossible to auto-generate these functional units [3].
Therefore, FPGA-SPICE requires users to provide their customized SPICE netlists. A sample SPICE netlist of a 1-bit adder can be found in the directory SpiceNetlists in the released package.
Therefore, FPGA-Verilog/SPICE requires users to provide their customized Verilog/SPICE netlists. A sample Verilog/SPICE netlist of a 1-bit adder can be found in the directory SpiceNetlists in the released package.
The information of input and output buffer should be clearly specified according to the customized SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
The information of input and output buffer should be clearly specified according to the customized Verilog/SPICE netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
Instructions of defining design parameters:
* **port:** two types of ports (input and output) should be defined. If the user provides a user-defined SPICE netlist, the bandwidth of ports should be defined to the same as the SPICE netlist.
* **port:** two types of ports (input and output) should be defined. If the user provides a user-defined Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
Routing Wire Segments
---------------------
FPGA-SPICE provides two types of SPICE models for the wire segments in FPGA architecture:
FPGA-Verilog/SPICE provides two types of Verilog/SPICE models for the wire segments in FPGA architecture:
* One type is called **wire**, which targets the local wires inside the logic blocks. The wire has one input and one output, directly connecting the output of a driver and the input of the downstream unit, respectively
* The other type is called **chan_wire**, especially targeting the channel wires. The channel wires have one input and two outputs, one of which is connected to the inputs of Connection Boxes while the other is connected to the inputs of Switch Boxes. Two outputs are created because from the view of layout, the inputs of Connection Boxes are typically connected to the middle point of channel wires, which has less parasitic resistances and capacitances than connected to the ending point.
@ -528,15 +534,15 @@ FPGA-SPICE provides two types of SPICE models for the wire segments in FPGA arch
<wire_param model_type="string" res_val="float" cap_val="float" level="int"/>
</circuit_model>
.. note:: FPGA-SPICE can auto-generate the SPICE model for wires while also allows users to provide their customized SPICE netlists.
.. note:: FPGA-Verilog/SPICE can auto-generate the Verilog/SPICE model for wires while also allows users to provide their customized Verilog/SPICE netlists.
The information of input and output buffer should be clearly specified according to the customized netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
Instructions of defining design parameters:
* **type:** can be [wire|chan_wire]. The SPICE model wire targets the local wire inside the logic block while the chan_wire targets the channel wires in global routing.
* **type:** can be [wire|chan_wire]. The Verilog/SPICE model wire targets the local wire inside the logic block while the chan_wire targets the channel wires in global routing.
* **port:** two types of ports (input and output) should be defined. If the user provides an customized SPICE netlist, the bandwidth of ports should be defined to the same as the SPICE netlist.
* **port:** two types of ports (input and output) should be defined. If the user provides an customized Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
* **wire_param:**
@ -570,7 +576,7 @@ The code describing this wire is:
**This example shows**
* How to use the *wire_param* for a π-type RC wire model
* How to use this circuit_model to auto-generate the SPICE netlist
* How to use this circuit_model to auto-generate the Verilog/SPICE netlist
I/O pads
--------
@ -588,13 +594,13 @@ I/O pads
</circuit_model>
.. note:: The circuit designs of I/O pads are highly dependent on the technology node and well optimized by engineers.
Therefore, FPGA-SPICE requires users to provide their customized SPICE/Verilog netlists. A sample SPICE netlist of an I/O pad can be found in the directory SpiceNetlists in the released package.
Therefore, FPGA-Verilog/SPICE requires users to provide their customized Verilog/SPICE/Verilog netlists. A sample Verilog/SPICE netlist of an I/O pad can be found in the directory SpiceNetlists in the released package.
The information of input and output buffer should be clearly specified according to the customized netlist! The existence of input/output buffers will influence the decision in creating testbenches, which may leads to larger errors in power analysis.
Instructions of defining design parameters:
* **port:** two types of ports (input and output) should be defined. If the user provides a user-defined SPICE netlist, the bandwidth of ports should be defined to the same as the SPICE netlist.
* **port:** two types of ports (input and output) should be defined. If the user provides a user-defined Verilog/SPICE netlist, the bandwidth of ports should be defined to the same as the Verilog/SPICE netlist.
**IO-pad example**

View File

@ -1,10 +1,10 @@
Define Circuit-level Modules
============================
To support FPGA SPICE, Verily and Bitstream Generator, physical modules containing gate-level and transistor-level features are required for FPGA primitive blocks.
To support FPGA Verilog/SPICE, Verily and Bitstream Generator, physical modules containing gate-level and transistor-level features are required for FPGA primitive blocks.
The physical modules are defined in XML syntax, similar to the original VPR FPGA architecture description language.
For each module that appears in the FPGA architecture, a circuit model should be defined. In the definition of a circuit model, the user can specify if the SPICE netlist of the module is either auto-generated or user-defined.
For each module that appears in the FPGA architecture, a circuit model should be defined. In the definition of a circuit model, the user can specify if the Verilog/SPICE netlist of the module is either auto-generated or user-defined.
Define circuit_models
---------------------
@ -22,21 +22,21 @@ Define circuit_models
* **circuit_model**: the child node defining transistor-level modeling parameters.
* **type**: can be [ inv_buf | pass_gate | mux | wire | chan_wire | sram | lut | ff | scff | hard_logic | iopad ]. Specify the type of circuit model. The provided types cover all the modules in FPGAs. For the circuit models in the type of mux/wire/chan_wire/lut, FPGA-SPICE can auto-generate SPICE netlists. For the rest, FPGA-SPICE requires a user-defined SPICE netlist.
* **type**: can be [ inv_buf | pass_gate | mux | wire | chan_wire | sram | lut | ff | scff | hard_logic | iopad ]. Specify the type of circuit model. The provided types cover all the modules in FPGAs. For the circuit models in the type of mux/wire/chan_wire/lut, FPGA-Verilog/SPICE can auto-generate Verilog/SPICE netlists. For the rest, FPGA-Verilog/SPICE requires a user-defined Verilog/SPICE netlist.
* **name**: define the name of this circuit model. The name should be unique and will be used to create the sub-circuit of the circuit model in SPICE netlists. Note that for a customized SPICE netlist, the name defined here should be the name of the top-level sub-circuit in the customized SPICE netlist. FPGA-SPICE will check if the given name is conflicted with any reserved words.
* **name**: define the name of this circuit model. The name should be unique and will be used to create the sub-circuit of the circuit model in Verilog/SPICE netlists. Note that for a customized Verilog/SPICE netlist, the name defined here should be the name of the top-level sub-circuit in the customized Verilog/SPICE netlist. FPGA-Verilog/SPICE will check if the given name is conflicted with any reserved words.
* **prefix**: specify the name of the circuit_model to shown in the auto-generated SPICE netlists. The prefix can be the same as the name defined above. And again, the prefix should be unique.
* **prefix**: specify the name of the circuit_model to shown in the auto-generated Verilog/SPICE netlists. The prefix can be the same as the name defined above. And again, the prefix should be unique.
* **is_default**: can be [1|0], corresponding to [true|false] respectively. Specify this circuit model is the default one for some modules, such as multiplexers. If a module is not linked to any spice model by users, FPGA-SPICE will find the default spice model defined in the same type and link. For a spice model type, only one spice model can be set as default.
* **is_default**: can be [1|0], corresponding to [true|false] respectively. Specify this circuit model is the default one for some modules, such as multiplexers. If a module is not linked to any spice model by users, FPGA-Verilog/SPICE will find the default spice model defined in the same type and link. For a spice model type, only one spice model can be set as default.
* **spice_netlist**: specify the path and file name of a customized SPICE netlist. For some modules such as SRAMs, FFs, inpads, and outpads, FPGA-SPICE does not support auto-generation of the transistor-level sub-circuits because their circuit design is highly dependent on the technology nodes. These circuit designs should be specified by users. For the other modules that can be auto-generated by FPGA-SPICE, the user can also define a custom netlist. Multiplexers cannot be user-defined.
* **spice_netlist**: specify the path and file name of a customized Verilog/SPICE netlist. For some modules such as SRAMs, FFs, inpads, and outpads, FPGA-Verilog/SPICE does not support auto-generation of the transistor-level sub-circuits because their circuit design is highly dependent on the technology nodes. These circuit designs should be specified by users. For the other modules that can be auto-generated by FPGA-Verilog/SPICE, the user can also define a custom netlist. Multiplexers cannot be user-defined.
* **verilog_netlist**: specify the path and file name of a customized Verilog netlist. For some modules such as SRAMs, FFs, inpad and outpads, FPGA-SPICE does not support auto-generation of the transistor-level sub-circuits because their circuit design is highly dependent on the technology nodes. These circuit designs should be specified by users. For the other modules that can be auto-generated by FPGA-SPICE, the user can also define a custom netlist. Multiplexers cannot be user-defined.
* **verilog_netlist**: specify the path and file name of a customized Verilog netlist. For some modules such as SRAMs, FFs, inpad and outpads, FPGA-Verilog/SPICE does not support auto-generation of the transistor-level sub-circuits because their circuit design is highly dependent on the technology nodes. These circuit designs should be specified by users. For the other modules that can be auto-generated by FPGA-Verilog/SPICE, the user can also define a custom netlist. Multiplexers cannot be user-defined.
* **dump_structural_verilog**: when the value of this keyword is set to be true, Verilog generator will output gate-level netlists of this module, instead of behavior-level. Gate-level netlists bring more opportunities in layout-level optimization while behavior-level is more suitable for high-speed formal verification and easier in debugging with HDL simulators.
.. note:: If netlist is not specified, FPGA-SPICE auto-generates the SPICE netlists for multiplexers, wires, and LUTs.
.. note:: If netlist is not specified, FPGA-Verilog/SPICE auto-generates the Verilog/SPICE netlists for multiplexers, wires, and LUTs.
.. note:: The user-defined netlists, such as LUTs, the decoding methodology should comply with the auto-generated LUTs (See Section 4.5)
@ -67,7 +67,7 @@ Transistor level
* input_buffer and output_buffer:
* **exist:** [on|off]. Define the existence of the input_buffer or output_buffer. Note that the existence is valid for all the inputs and outputs. Note that if users want only part of the inputs (or outputs) to be buffered, this is not supported here. A solution can be building a user-defined SPICE netlist.
* **exist:** [on|off]. Define the existence of the input_buffer or output_buffer. Note that the existence is valid for all the inputs and outputs. Note that if users want only part of the inputs (or outputs) to be buffered, this is not supported here. A solution can be building a user-defined Verilog/SPICE netlist.
* **circuit_model_name:** Specify the name of circuit model which is used to implement input/output buffer, the type of specified circuit model should be inv_buf.
@ -79,7 +79,7 @@ Transistor level
* **type:** can be [input|output|sram|clock]. For programmable modules, such as multiplexers and LUTs, SRAM ports should be defined. For registers, such as FFs and memory banks, clock ports should be defined.
* **prefix:** the name of the port. Each port will be shown as <prefix>[i], 0≤i<size in SPICE netlists.
* **prefix:** the name of the port. Each port will be shown as <prefix>[i] in Verilog/SPICE netlists.
* **size:** bandwidth of the port.
@ -96,3 +96,5 @@ Transistor level
* **is_reset:** can be either true or false. Specify if this port controls a reset signal. Only valid when is_global is true. All the reset ports are connected to a global reset voltage stimuli in testbenches.
* **is_config_enable:** can be either true or false. Only valid when is_global is true. Specify if this port controls a configuration-enable signal. This port is only enabled during FPGA configuration, and always disabled during FPGA operation. All the config_enable ports are connected to global configuration-enable voltage stimuli in testbenches.
.. note:: Different types of ``circuit_model`` have different XML syntax, with which users can highly customize their circuit topologies. See refer to examples of ``circuit_model`` for more details.

View File

@ -29,7 +29,6 @@ perl rewrite_path_in_file.pl -i $architecture_generated -k $ff_keyword $ff_path
echo "perl rewrite_path_in_file.pl -i $ff_path -k $dir_keyword $verilog_path"
perl rewrite_path_in_file.pl -i ${ff_template_path} -o ${ff_path} -k $dir_keyword $verilog_path # Set the define path in the ff.v file
# SRAM FPGA
# TT case
perl fpga_flow.pl -conf ${config_file} -benchmark ${bench_txt} -rpt ${rpt_file} -N 10 -K 6 -ace_d 0.5 -multi_thread 1 -vpr_fpga_x2p_rename_illegal_port -vpr_fpga_verilog -vpr_fpga_verilog_dir $verilog_path -vpr_fpga_bitstream_generator -vpr_fpga_verilog_print_autocheck_top_testbench -vpr_fpga_verilog_include_timing -vpr_fpga_verilog_include_signal_init -vpr_fpga_verilog_formal_verification_top_netlist -fix_route_chan_width -vpr_fpga_verilog_include_icarus_simulator -power -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 -vpr_fpga_verilog_explicit_mapping

View File

@ -5,16 +5,20 @@
#include "my_free_fwd.h"
void InitSpiceMeasParams(t_spice_meas_params* meas_params);
void FreeSpiceMeasParams(t_spice_meas_params* meas_params);
void FreeSpiceMeasParams();
void InitSpiceStimulateParams(t_spice_stimulate_params* stimulate_params);
void FreeSpiceStimulateParams(t_spice_stimulate_params* stimulate_params);
void FreeSpiceStimulateParams();
void InitSpiceVariationParams(t_spice_mc_variation_params* mc_variation_params);
void FreeSpiceVariationParams();
void InitSpiceMonteCarloParams(t_spice_mc_params* mc_params);
void FreeSpiceMonteCarloParams();
void InitSpiceParams(t_spice_params* spice_params);
void FreeSpiceParams(t_spice_params* params);
void FreeSpiceParams();
void FreeSpiceModelNetlist(t_spice_model_netlist* spice_model_netlist);
void FreeSpiceModelBuffer(t_spice_model_buffer* spice_model_buffer);
void FreeSpiceModelPassGateLogic(t_spice_model_pass_gate_logic* spice_model_pass_gate_logic);
void FreeSpiceModelBuffer();
void FreeSpiceModelPassGateLogic();
void FreeSpiceModelPort(t_spice_model_port* spice_model_port);
void FreeSpiceModelWireParam(t_spice_model_wire_param* spice_model_wire_param);
void FreeSpiceModelWireParam();
void FreeSpiceModel(t_spice_model* spice_model);
void InitSpice(t_spice* spice);
void FreeSpice(t_spice* spice);

View File

@ -93,9 +93,10 @@ enum e_process_corner {
/* For SRAM */
enum e_sram_orgz {
SPICE_SRAM_STANDALONE,
SPICE_SRAM_SCAN_CHAIN,
SPICE_SRAM_MEMORY_BANK
SPICE_SRAM_STANDALONE, /* SRAMs are organized and accessed as standalone elements */
SPICE_SRAM_SCAN_CHAIN, /* SRAMs are organized and accessed by a scan-chain */
SPICE_SRAM_MEMORY_BANK, /* SRAMs are organized and accessed by memory bank */
SPICE_SRAM_LOCAL_ENCODER /* SRAMs are organized and accessed by a local encoder */
};
enum e_spice_accuracy_type {
@ -240,6 +241,8 @@ struct s_spice_model_port {
/* Timing edeges linked to other t_model_ports */
int* num_tedges; /* 1-D Array, show number of tedges of each pin */
t_spice_model_tedge*** tedge; /* 3-D array, considering the each pin in this port, [pin_number][num_edges[iedge]] is an edge pointor */
/* SRAM organization only applicable SRAM ports */
enum e_sram_orgz organization;
};
struct s_spice_model_wire_param {
@ -271,6 +274,7 @@ struct s_spice_model_mux {
boolean add_const_input;
int const_input_val;
boolean advanced_rram_design;
boolean local_encoder; /* Define if a local encoder should be added to this mux */
};
struct s_spice_model_lut {

View File

@ -120,7 +120,7 @@ ProcessWireBuffer(INOUTP ezxml_t Node,
return;
}
void
static void
ProcessTechComp(INOUTP ezxml_t Node,
OUTP struct s_arch *arch) {
const char *Prop;

View File

@ -600,6 +600,10 @@ static void ProcessSpiceModelMUX(ezxml_t Node,
mux_info->advanced_rram_design = GetBooleanProperty(Node,"advanced_rram_design", FALSE, FALSE);
ezxml_set_attr(Node, "advanced_rram_design", NULL);
/* Specify if should use a local encoder for this multiplexer */
mux_info->local_encoder = GetBooleanProperty(Node, "local_encoder", FALSE, FALSE);
ezxml_set_attr(Node, "local_encoder", NULL);
return;
}
@ -765,6 +769,26 @@ static void ProcessSpiceModelPort(ezxml_t Node,
port->inv_spice_model_name = my_strdup(FindProperty(Node, "inv_circuit_model_name", FALSE));
ezxml_set_attr(Node, "inv_circuit_model_name", NULL);
}
/* Add a feature to enable/disable the configuration encoders for multiplexers */
const char* Prop = FindProperty(Node, "organization", FALSE);
if (NULL == Prop) {
port->organization = SPICE_SRAM_STANDALONE; /* Default */
} else if (0 == strcmp("scan-chain", Prop)) {
port->organization = SPICE_SRAM_SCAN_CHAIN;
} else if (0 == strcmp("memory-bank", Prop)) {
port->organization = SPICE_SRAM_MEMORY_BANK;
} else if (0 == strcmp("standalone", Prop)) {
port->organization = SPICE_SRAM_STANDALONE;
} else if (0 == strcmp("local-encoder", Prop)) {
port->organization = SPICE_SRAM_LOCAL_ENCODER;
} else {
vpr_printf(TIO_MESSAGE_ERROR,
"[LINE %d] Unknown property %s for SRAM organization\n",
Node->line, FindProperty(Node, "organization", FALSE));
exit(1);
}
ezxml_set_attr(Node, "organization", NULL);
return;
}

View File

@ -41,7 +41,7 @@ void InitSpiceMeasParams(t_spice_meas_params* meas_params) {
return;
}
void FreeSpiceMeasParams(t_spice_meas_params* meas_params) {
void FreeSpiceMeasParams() {
return;
}
@ -64,7 +64,7 @@ void InitSpiceStimulateParams(t_spice_stimulate_params* stimulate_params) {
return;
}
void FreeSpiceStimulateParams(t_spice_stimulate_params* stimulate_params) {
void FreeSpiceStimulateParams() {
return;
}
@ -74,7 +74,7 @@ void InitSpiceVariationParams(t_spice_mc_variation_params* mc_variation_params)
mc_variation_params->num_sigma = 1;
}
void FreeSpiceVariationParams(t_spice_mc_variation_params* mc_variation_params) {
void FreeSpiceVariationParams() {
return;
}
@ -86,7 +86,7 @@ void InitSpiceMonteCarloParams(t_spice_mc_params* mc_params) {
return;
}
void FreeSpiceMonteCarloParams(t_spice_mc_params* mc_params) {
void FreeSpiceMonteCarloParams() {
return;
}
@ -110,7 +110,7 @@ void InitSpiceParams(t_spice_params* params) {
return;
}
void FreeSpiceParams(t_spice_params* params) {
void FreeSpiceParams() {
return;
}
@ -121,12 +121,12 @@ void FreeSpiceModelNetlist(t_spice_model_netlist* spice_model_netlist) {
return;
}
void FreeSpiceModelBuffer(t_spice_model_buffer* spice_model_buffer) {
void FreeSpiceModelBuffer() {
return;
}
void FreeSpiceModelPassGateLogic(t_spice_model_pass_gate_logic* spice_model_pass_gate_logic) {
void FreeSpiceModelPassGateLogic() {
return;
}
@ -137,8 +137,7 @@ void FreeSpiceModelPort(t_spice_model_port* spice_model_port) {
return;
}
void FreeSpiceModelWireParam(t_spice_model_wire_param* spice_model_wire_param) {
void FreeSpiceModelWireParam() {
return;
}
@ -152,14 +151,14 @@ void FreeSpiceModel(t_spice_model* spice_model) {
spice_model->include_netlist = NULL;
/* Free the buffers */
FreeSpiceModelBuffer(spice_model->input_buffer);
FreeSpiceModelBuffer(spice_model->output_buffer);
FreeSpiceModelBuffer();
FreeSpiceModelBuffer();
my_free(spice_model->input_buffer);
my_free(spice_model->output_buffer);
spice_model->input_buffer = NULL;
spice_model->output_buffer = NULL;
FreeSpiceModelPassGateLogic(spice_model->pass_gate_logic);
FreeSpiceModelPassGateLogic();
my_free(spice_model->pass_gate_logic);
spice_model->pass_gate_logic = NULL;
@ -173,7 +172,7 @@ void FreeSpiceModel(t_spice_model* spice_model) {
/* Free wire parameters */
if (NULL != spice_model->wire_param) {
FreeSpiceModelWireParam(spice_model->wire_param);
FreeSpiceModelWireParam();
my_free(spice_model->wire_param);
spice_model->wire_param = NULL;
}
@ -220,6 +219,7 @@ void FreeSpiceMuxArch(t_spice_mux_arch* spice_mux_arch) {
return;
}
static
void FreeSramInfOrgz(t_sram_inf_orgz* sram_inf_orgz) {
my_free(sram_inf_orgz->spice_model_name);

View File

@ -192,6 +192,18 @@ int count_num_sram_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
}
break;
case SPICE_MODEL_DESIGN_CMOS:
/* When a local encoder is added, the number of sram bits will be reduced
* to N * log_2{X}, where N is the number of levels and X is the number of inputs per level
* Note that: we only apply this to one-level and multi-level multiplexers
*/
if ( (TRUE == cur_spice_model->design_tech_info.mux_info->local_encoder)
&& (2 < num_input_size) ) {
if (SPICE_MODEL_STRUCTURE_ONELEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_sram_bits = ceil(log(num_sram_bits + 1) / log(2));
} else if (SPICE_MODEL_STRUCTURE_MULTILEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_sram_bits = cur_spice_model->design_tech_info.mux_info->mux_num_level * ceil(log(num_sram_bits / cur_spice_model->design_tech_info.mux_info->mux_num_level + 1) / log(2));
}
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid design_technology of MUX(name: %s)\n",
@ -702,6 +714,18 @@ int count_num_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
}
break;
case SPICE_MODEL_DESIGN_CMOS:
/* When a local encoder is added, the number of sram bits will be reduced
* to N * log_2{X}, where N is the number of levels and X is the number of inputs per level
* Note that: we only apply this to one-level and multi-level multiplexers
*/
if ( (TRUE == cur_spice_model->design_tech_info.mux_info->local_encoder)
&& (2 < num_input_size) ) {
if (SPICE_MODEL_STRUCTURE_ONELEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_conf_bits = ceil(log(num_conf_bits + 1) / log(2));
} else if (SPICE_MODEL_STRUCTURE_MULTILEVEL == cur_spice_model->design_tech_info.mux_info->structure) {
num_conf_bits = cur_spice_model->design_tech_info.mux_info->mux_num_level * ceil(log(num_conf_bits / cur_spice_model->design_tech_info.mux_info->mux_num_level + 1) / log(2));
}
}
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid design_technology of MUX(name: %s)\n",

View File

@ -187,6 +187,26 @@ int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
return ret;
}
/***************************************************************************************
* 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
***************************************************************************************/
int determine_mux_local_encoder_num_inputs(int num_outputs) {
return ceil(log(num_outputs + 1) / log(2));
}
/* Decoding a one-level MUX:
* SPICE/Verilog model declare the sram port sequence as follows:
* sel0, sel1, ... , selN,
@ -198,24 +218,36 @@ int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
*/
int* decode_onelevel_mux_sram_bits(int fan_in,
int mux_level,
int path_id) {
int* ret = (int*)my_malloc(sizeof(int)*fan_in);
int i;
int path_id,
boolean use_local_encoder) {
/* Check */
assert( (!(0 > path_id)) && (path_id < fan_in) );
for (i = 0; i < fan_in; i++) {
ret[i] = 0;
/* If we use local encoder, we have a different number of sram bits! */
int num_sram_bits = fan_in;
if (TRUE == use_local_encoder) {
num_sram_bits = determine_mux_local_encoder_num_inputs(fan_in);
}
/* Allocate sram_bits array to return */
int* ret = (int*)my_calloc(num_sram_bits, sizeof(int));
if (TRUE == use_local_encoder) {
/* The encoder will convert the path_id to a binary number
* For example: when path_id=3, using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0011
*/
ret = my_itobin_int(path_id, num_sram_bits);
} else {
ret[path_id] = 1;
}
ret[path_id] = 1;
/* ret[fan_in - 1 - path_id] = 1; */
return ret;
}
int* decode_multilevel_mux_sram_bits(int fan_in,
int mux_level,
int path_id) {
int path_id,
boolean use_local_encoder) {
int* ret = NULL;
int i, j, path_differ, temp;
int num_last_level_input, active_mux_level, active_path_id, num_input_basis;
@ -228,7 +260,7 @@ int* decode_multilevel_mux_sram_bits(int fan_in,
switch (mux_level) {
case 1:
/* Special: 1-level should be have special care !!! */
return decode_onelevel_mux_sram_bits(fan_in, mux_level, path_id);
return decode_onelevel_mux_sram_bits(fan_in, mux_level, path_id, use_local_encoder);
default:
assert(1 < mux_level);
num_input_basis = determine_num_input_basis_multilevel_mux(fan_in, mux_level);
@ -258,12 +290,7 @@ int* decode_multilevel_mux_sram_bits(int fan_in,
} else {
assert(num_last_level_input == fan_in);
}
/*
if ((41 == fan_in) && (40 == path_id)) {
printf("num_last_level_input=%d, active_mux_lvl=%d, active_path_id=%d\n",
num_last_level_input, active_mux_level, active_path_id);
}
*/
temp = active_path_id;
for (i = mux_level - 1; i > (mux_level - active_mux_level - 1); i--) {
for (j = 0; j < num_input_basis; j++) {
@ -283,8 +310,49 @@ int* decode_multilevel_mux_sram_bits(int fan_in,
/* Check */
assert(0 == temp);
return ret;
/* If we do not use a local encoder, these are the sram bits we want */
if (FALSE == use_local_encoder) {
return ret;
}
/* If we use local encoder, we have a different number of sram bits! */
int num_bits_per_level = determine_mux_local_encoder_num_inputs(num_input_basis);
int num_sram_bits = mux_level * num_bits_per_level;
/* Allocate sram_bits array to return */
int* encoded_ret = (int*)my_calloc(num_sram_bits, sizeof(int));
/* Walk through each level and find the path_id and encode it */
for (int ilvl = 0; ilvl < mux_level; ++ilvl) {
int start_idx = num_input_basis * ilvl;
int end_idx = num_input_basis * (ilvl + 1) - 1;
int encoded_path_id = 0;
int checker = 0;
for (int idx = start_idx; idx < end_idx; ++idx) {
if ('1' == ret[idx]) {
checker++;
encoded_path_id = idx;
}
}
/* There should be at most one '1' */
assert( (0 == checker) || (1 == checker));
/* The encoder will convert the path_id to a binary number
* For example: when path_id=3, using a 4-input encoder
* the sram_bits will be the 4-digit binary number of 3: 0011
*/
int* tmp_bits = my_itobin_int(encoded_path_id, num_bits_per_level);
/* Copy tmp_bits to encoded bits */
for (int idx = 0; idx < num_bits_per_level; ++idx) {
encoded_ret[idx + ilvl* num_bits_per_level] = tmp_bits[idx];
}
/* Free */
my_free(tmp_bits);
}
/* Free ret */
my_free(ret);
return encoded_ret;
}
/* Decode the configuration to sram_bits
@ -428,12 +496,24 @@ void decode_cmos_mux_sram_bits(t_spice_model* mux_spice_model,
case SPICE_MODEL_STRUCTURE_ONELEVEL:
(*mux_level) = 1;
(*bit_len) = num_mux_input;
(*conf_bits) = decode_onelevel_mux_sram_bits(num_mux_input, (*mux_level), datapath_id);
/* Mux has local encoders are different in the number of bits */
if (TRUE == mux_spice_model->design_tech_info.mux_info->local_encoder) {
(*bit_len) = determine_mux_local_encoder_num_inputs(*bit_len);
}
(*conf_bits) = decode_onelevel_mux_sram_bits(num_mux_input, (*mux_level), datapath_id,
mux_spice_model->design_tech_info.mux_info->local_encoder);
break;
case SPICE_MODEL_STRUCTURE_MULTILEVEL:
(*mux_level) = mux_spice_model->design_tech_info.mux_info->mux_num_level;
(*bit_len) = determine_num_input_basis_multilevel_mux(num_mux_input, (*mux_level)) * (*mux_level);
(*conf_bits) = decode_multilevel_mux_sram_bits(num_mux_input, (*mux_level), datapath_id);
/* Mux has local encoders are different in the number of bits */
if (TRUE == mux_spice_model->design_tech_info.mux_info->local_encoder) {
int num_bits_per_level = determine_mux_local_encoder_num_inputs(determine_num_input_basis_multilevel_mux(num_mux_input, (*mux_level)));
(*bit_len) = (*mux_level) * num_bits_per_level;
} else {
(*bit_len) = (*mux_level) * determine_num_input_basis_multilevel_mux(num_mux_input, (*mux_level));
}
(*conf_bits) = decode_multilevel_mux_sram_bits(num_mux_input, (*mux_level), datapath_id,
mux_spice_model->design_tech_info.mux_info->local_encoder);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid structure for mux_spice_model (%s)!\n",

View File

@ -17,13 +17,17 @@ int tree_mux_last_level_input_num(int num_level,
int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
int mux_size);
int determine_mux_local_encoder_num_inputs(int num_outputs);
int* decode_onelevel_mux_sram_bits(int fan_in,
int mux_level,
int path_id);
int path_id,
boolean use_local_encoder);
int* decode_multilevel_mux_sram_bits(int fan_in,
int mux_level,
int path_id);
int path_id,
boolean use_local_encoder);
int* decode_tree_mux_sram_bits(int fan_in,
int mux_level,

View File

@ -576,6 +576,27 @@ t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib,
return ret;
}
/* Converter an integer to a binary string */
int* my_itobin_int(int in_int, int bin_len) {
int* ret = (int*) my_calloc (bin_len, sizeof(int));
int i, temp;
/* Make sure we do not have any overflow! */
if (! ( (-1 < in_int) && (in_int < pow(2., bin_len)) ) )
assert ( (-1 < in_int) && (in_int < pow(2., bin_len)) );
temp = in_int;
for (i = 0; i < bin_len; i++) {
if (1 == temp % 2) {
ret[i] = 1;
}
temp = temp / 2;
}
return ret;
}
/* Converter an integer to a binary string */
char* my_itobin(int in_int, int bin_len) {
char* ret = (char*) my_calloc (bin_len + 1, sizeof(char));

View File

@ -60,6 +60,8 @@ t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib,
char* my_itobin(int in_int, int bin_len);
int* my_itobin_int(int in_int, int bin_len);
char* my_itoa(int input);
char* fpga_spice_create_one_subckt_filename(const char* file_name_prefix,

View File

@ -63,6 +63,7 @@ char* logic_block_verilog_file_name = "logic_blocks.v";
char* luts_verilog_file_name = "luts.v";
char* routing_verilog_file_name = "routing.v";
char* muxes_verilog_file_name = "muxes.v";
char* local_encoder_verilog_file_name = "local_encoder.v";
char* memories_verilog_file_name = "memories.v";
char* wires_verilog_file_name = "wires.v";
char* essentials_verilog_file_name = "inv_buf_passgate.v";

View File

@ -55,6 +55,7 @@ extern char* logic_block_verilog_file_name;
extern char* luts_verilog_file_name;
extern char* routing_verilog_file_name;
extern char* muxes_verilog_file_name;
extern char* local_encoder_verilog_file_name;
extern char* memories_verilog_file_name;
extern char* wires_verilog_file_name;
extern char* essentials_verilog_file_name;

View File

@ -10,6 +10,8 @@
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
#include <algorithm>
/* Include vpr structs*/
#include "util.h"
@ -34,8 +36,11 @@
#include "verilog_pbtypes.h"
#include "verilog_decoder.h"
#include "verilog_submodules.h"
/***** Subroutines *****/
static
void dump_verilog_submodule_timing(FILE* fp,
t_spice_model* cur_spice_model) {
int iport, ipin, iedge;
@ -85,6 +90,7 @@ void dump_verilog_submodule_timing(FILE* fp,
return;
}
static
void dump_verilog_submodule_signal_init(FILE* fp,
t_spice_model* cur_spice_model) {
int iport;
@ -124,6 +130,7 @@ void dump_verilog_submodule_signal_init(FILE* fp,
/* Dump a module of inverter or buffer or tapered buffer */
static
void dump_verilog_invbuf_module(FILE* fp,
t_spice_model* invbuf_spice_model) {
int ipin, iport, port_cnt;
@ -344,6 +351,7 @@ void dump_verilog_invbuf_module(FILE* fp,
}
/* Dump a module of pass-gate logic */
static
void dump_verilog_passgate_module(FILE* fp,
t_spice_model* passgate_spice_model) {
int iport;
@ -448,6 +456,7 @@ void dump_verilog_passgate_module(FILE* fp,
}
/* Dump a module of pass-gate logic */
static
void dump_verilog_gate_module(FILE* fp,
t_spice_model* gate_spice_model) {
int iport, ipin, jport, jpin;
@ -568,10 +577,10 @@ void dump_verilog_gate_module(FILE* fp,
* 1. inverters
* 2. buffers
* 3. pass-gate logics */
static
void dump_verilog_submodule_essentials(char* verilog_dir, char* submodule_dir,
int num_spice_model,
t_spice_model* spice_models,
t_syn_verilog_opts fpga_verilog_opts) {
t_spice_model* spice_models) {
int imodel;
char* verilog_name = my_strcat(submodule_dir, essentials_verilog_file_name);
FILE* fp = NULL;
@ -616,6 +625,7 @@ void dump_verilog_submodule_essentials(char* verilog_dir, char* submodule_dir,
}
/* Dump a CMOS MUX basis module */
static
void dump_verilog_cmos_mux_one_basis_module(FILE* fp,
char* mux_basis_subckt_name,
int mux_size,
@ -906,6 +916,7 @@ void dump_verilog_rram_mux_one_basis_module_structural(FILE* fp,
/* Dump a RRAM MUX basis module */
static
void dump_verilog_rram_mux_one_basis_module(FILE* fp,
char* mux_basis_subckt_name,
int num_input_basis_subckt,
@ -1021,6 +1032,7 @@ void dump_verilog_rram_mux_one_basis_module(FILE* fp,
}
/* Print a basis submodule */
static
void dump_verilog_mux_one_basis_module(FILE* fp,
char* mux_basis_subckt_name,
int mux_size,
@ -1073,6 +1085,7 @@ void dump_verilog_mux_one_basis_module(FILE* fp,
/**
* Dump a verilog module for the basis circuit of a MUX
*/
static
void dump_verilog_mux_basis_module(FILE* fp,
t_spice_mux_model* spice_mux_model) {
/** Act depends on the structure of MUX
@ -1165,6 +1178,7 @@ void dump_verilog_mux_basis_module(FILE* fp,
return;
}
static
void dump_verilog_cmos_mux_tree_structure(FILE* fp,
char* mux_basis_subckt_name,
t_spice_model spice_model,
@ -1195,7 +1209,7 @@ void dump_verilog_cmos_mux_tree_structure(FILE* fp,
inter_buf_loc[i] = FALSE;
}
if (NULL != spice_model.lut_intermediate_buffer->location_map) {
assert (spice_mux_arch.num_level - 1 == strlen(spice_model.lut_intermediate_buffer->location_map));
assert ((size_t)spice_mux_arch.num_level - 1 == strlen(spice_model.lut_intermediate_buffer->location_map));
/* For intermediate buffers */
for (i = 0; i < spice_mux_arch.num_level - 1; i++) {
if ('1' == spice_model.lut_intermediate_buffer->location_map[i]) {
@ -1404,6 +1418,7 @@ void dump_verilog_cmos_mux_tree_structure(FILE* fp,
return;
}
static
void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
char* mux_basis_subckt_name,
char* mux_special_basis_subckt_name,
@ -1437,6 +1452,16 @@ void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
}
fprintf(fp, "wire [%d:%d] mux2_l%d_in; \n",
0, 0, 0);
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
/* Print local wires for local encoders */
fprintf(fp, "wire [%d:0] %s_data;\n",
spice_mux_arch.num_level * spice_mux_arch.num_input_basis - 1,
sram_port[0]->prefix);
fprintf(fp, "wire [%d:0] %s_data_inv;\n",
spice_mux_arch.num_level * spice_mux_arch.num_input_basis - 1,
sram_port[0]->prefix);
}
for (i = 0; i < spice_mux_arch.num_level; i++) {
level = spice_mux_arch.num_level - i;
@ -1444,6 +1469,30 @@ void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
sram_idx = nextlevel * spice_mux_arch.num_input_basis;
/* Check */
assert(nextlevel > -1);
/* Determine the number of input of this basis */
cur_num_input_basis = spice_mux_arch.num_input_basis;
/* Instanciate local encoder circuit here */
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
/* Get the number of inputs */
int num_outputs = cur_num_input_basis;
int num_inputs = determine_mux_local_encoder_num_inputs(num_outputs);
/* Find the decoder name */
fprintf(fp, "%s %s_%d_ (",
generate_verilog_decoder_subckt_name(num_inputs, num_outputs),
generate_verilog_decoder_subckt_name(num_inputs, num_outputs),
i);
if (true == is_explicit_mapping) {
fprintf(fp, ".addr(%s[%d:%d]), .data(%s_data[%d:%d]), .data_inv(%s_data_inv[%d:%d]) );\n",
sram_port[0]->prefix, nextlevel * num_inputs, (nextlevel + 1) * num_inputs - 1,
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis - 1,
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis - 1);
} else {
fprintf(fp, "%s[%d:%d], %s_data[%d:%d], %s_data_inv[%d:%d]);\n",
sram_port[0]->prefix, nextlevel * num_inputs, (nextlevel + 1) * num_inputs - 1,
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis - 1,
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis - 1);
}
}
/* Print basis muxQto1 for each level*/
for (j = 0; j < spice_mux_arch.num_input_per_level[nextlevel]; j = j + cur_num_input_basis) {
/* output index */
@ -1474,15 +1523,25 @@ void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
} else {
fprintf(fp, ", ");
}
fprintf(fp, "%s[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
fprintf(fp, "%s_data[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
} else {
fprintf(fp, "%s[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
}
if (true == is_explicit_mapping) {
fprintf(fp, "), .mem_inv(");
} else {
fprintf(fp, ", ");
}
fprintf(fp, "%s_inv[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
fprintf(fp, "%s_data_inv[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
} else {
fprintf(fp, "%s_inv[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
}
if (true == is_explicit_mapping) {
fprintf(fp, ")");
}
@ -1514,15 +1573,25 @@ void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
} else {
fprintf(fp, ", ");
}
fprintf(fp, "%s[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
fprintf(fp, "%s_data[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
} else {
fprintf(fp, "%s[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
}
if (true == is_explicit_mapping) {
fprintf(fp, "), .mem_inv(");
} else {
fprintf(fp, ", ");
}
fprintf(fp, "%s_inv[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
fprintf(fp, "%s_data_inv[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
} else {
fprintf(fp, "%s_inv[%d:%d]",
sram_port[0]->prefix, sram_idx, sram_idx + cur_num_input_basis -1);
}
if (true == is_explicit_mapping) {
fprintf(fp, ")");
}
@ -1541,6 +1610,7 @@ void dump_verilog_cmos_mux_multilevel_structure(FILE* fp,
return;
}
static
void dump_verilog_cmos_mux_onelevel_structure(FILE* fp,
char* mux_basis_subckt_name,
t_spice_model spice_model,
@ -1603,25 +1673,68 @@ void dump_verilog_cmos_mux_onelevel_structure(FILE* fp,
if (true == is_explicit_mapping) {
fprintf(fp, ".mem(");
}
fprintf(fp, "%s[0:%d]",
sram_port[0]->prefix, spice_mux_arch.num_input - 1); /* sram */
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
fprintf(fp, "%s_data[0:%d]",
sram_port[0]->prefix, spice_mux_arch.num_input - 1); /* sram */
} else {
fprintf(fp, "%s[0:%d]",
sram_port[0]->prefix, spice_mux_arch.num_input - 1); /* sram */
}
if (true == is_explicit_mapping) {
fprintf(fp, "), .mem_inv(");
} else {
fprintf(fp, ", ");
}
fprintf(fp, "%s_inv[0:%d]",
sram_port[0]->prefix, spice_mux_arch.num_input - 1); /* sram_inv */
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
fprintf(fp, "%s_data_inv[0:%d]",
sram_port[0]->prefix, spice_mux_arch.num_input - 1); /* sram_inv */
} else {
fprintf(fp, "%s_inv[0:%d]",
sram_port[0]->prefix, spice_mux_arch.num_input - 1); /* sram_inv */
}
if (true == is_explicit_mapping) {
fprintf(fp, ")");
}
}
fprintf(fp, "\n");
fprintf(fp, ");\n");
if (2 < spice_mux_arch.num_input) {
/* Instanciate local encoder circuit here */
if (TRUE == spice_model.design_tech_info.mux_info->local_encoder) {
/* Get the number of inputs */
int num_outputs = spice_mux_arch.num_input - 1;
int num_inputs = determine_mux_local_encoder_num_inputs(num_outputs);
/* Print local wires for local encoders */
fprintf(fp, "wire [%d:0] %s_data;\n",
spice_mux_arch.num_input - 1,
sram_port[0]->prefix);
fprintf(fp, "wire [%d:0] %s_data_inv;\n",
spice_mux_arch.num_input - 1,
sram_port[0]->prefix);
/* Find the decoder name */
fprintf(fp, "%s %s_0_ (",
generate_verilog_decoder_subckt_name(num_inputs, num_outputs),
generate_verilog_decoder_subckt_name(num_inputs, num_outputs));
if (true == is_explicit_mapping) {
fprintf(fp, ".addr(%s), .data(%s_data), .data_inv(%s_data_inv) );\n",
sram_port[0]->prefix,
sram_port[0]->prefix,
sram_port[0]->prefix);
} else {
fprintf(fp, "%s, %s_data, %s_data_inv);\n",
sram_port[0]->prefix,
sram_port[0]->prefix,
sram_port[0]->prefix);
}
}
}
return;
}
static
void dump_verilog_cmos_mux_submodule(FILE* fp,
int mux_size,
t_spice_model spice_model,
@ -1755,7 +1868,7 @@ void dump_verilog_cmos_mux_submodule(FILE* fp,
if (2 == spice_mux_arch.num_input) {
cur_mux_structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
}
/* Print internal architecture*/
switch (cur_mux_structure) {
case SPICE_MODEL_STRUCTURE_TREE:
@ -1906,7 +2019,6 @@ void dump_verilog_cmos_mux_submodule(FILE* fp,
}
}
fprintf(fp, "endmodule\n");
fprintf(fp, "//----- END CMOS MUX info: spice_model_name=%s, size=%d -----\n\n", spice_model.name, mux_size);
fprintf(fp, "\n");
@ -1927,6 +2039,7 @@ void dump_verilog_cmos_mux_submodule(FILE* fp,
* However I use another function, because in future the internal structure may change.
* We will suffer less software problems.
*/
static
void dump_verilog_rram_mux_tree_structure(FILE* fp,
char* mux_basis_subckt_name,
t_spice_model spice_model,
@ -1995,6 +2108,7 @@ void dump_verilog_rram_mux_tree_structure(FILE* fp,
return;
}
static
void dump_verilog_rram_mux_multilevel_structure(FILE* fp,
char* mux_basis_subckt_name,
char* mux_special_basis_subckt_name,
@ -2095,6 +2209,7 @@ void dump_verilog_rram_mux_multilevel_structure(FILE* fp,
return;
}
static
void dump_verilog_rram_mux_onelevel_structure(FILE* fp,
char* mux_basis_subckt_name,
t_spice_model spice_model,
@ -2133,6 +2248,7 @@ void dump_verilog_rram_mux_onelevel_structure(FILE* fp,
return;
}
static
void dump_verilog_rram_mux_submodule(FILE* fp,
int mux_size,
t_spice_model spice_model,
@ -2366,6 +2482,7 @@ void dump_verilog_rram_mux_submodule(FILE* fp,
}
/* Dump a memory submodule for the MUX */
static
void dump_verilog_cmos_mux_mem_submodule(FILE* fp,
int mux_size,
t_spice_model spice_model,
@ -2428,6 +2545,7 @@ void dump_verilog_cmos_mux_mem_submodule(FILE* fp,
* 3. output ports
* 4. bl/wl ports
*/
/* Local Encoding support */
dump_verilog_mem_module_port_map(fp, mem_model, TRUE, 0, num_conf_bits, my_bool_to_boolean(is_explicit_mapping));
fprintf(fp, ");\n");
@ -2453,6 +2571,7 @@ void dump_verilog_cmos_mux_mem_submodule(FILE* fp,
* We always dump a basis submodule for a MUX
* whatever structure it is: one-level, two-level or multi-level
*/
static
void dump_verilog_mux_mem_module(FILE* fp,
t_spice_mux_model* spice_mux_model,
bool is_explicit_mapping) {
@ -2506,6 +2625,7 @@ void dump_verilog_mux_mem_module(FILE* fp,
* We always dump a basis submodule for a MUX
* whatever structure it is: one-level, two-level or multi-level
*/
static
void dump_verilog_mux_module(FILE* fp,
t_spice_mux_model* spice_mux_model,
bool is_explicit_mapping) {
@ -2568,7 +2688,7 @@ void dump_verilog_mux_module(FILE* fp,
/*** Top-level function *****/
/* We should count how many multiplexers with different sizes are needed */
static
void dump_verilog_submodule_muxes(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* submodule_dir,
@ -2696,6 +2816,232 @@ void dump_verilog_submodule_muxes(t_sram_orgz_info* cur_sram_orgz_info,
return;
}
/***************************************************************************************
* Create a Verilog module 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
***************************************************************************************/
static
void dump_verilog_mux_local_encoder_module(FILE* fp, int num_outputs) {
/* Make sure we have a encoder which is at least 2 ! */
assert (2 <= num_outputs);
/* Get the number of inputs */
int num_inputs = determine_mux_local_encoder_num_inputs(num_outputs);
/* Validate the FILE handler */
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d]Invalid file handler!\n",
__FILE__, __LINE__);
exit(1);
}
/* Print the name of encoder */
fprintf(fp, "//-------- Local Decoder convert %d-bit addr to %d-bit data \n",
num_inputs, num_outputs);
fprintf(fp, "module %s(", generate_verilog_decoder_subckt_name(num_inputs, num_outputs));
fprintf(fp, "\n");
/* Inputs */
dump_verilog_generic_port(fp, VERILOG_PORT_INPUT,
"addr",
0, num_inputs - 1);
fprintf(fp, ",\n");
/* Outputs */
dump_verilog_generic_port(fp, VERILOG_PORT_OUTPUT,
"data",
0, num_outputs - 1);
fprintf(fp, ",\n");
dump_verilog_generic_port(fp, VERILOG_PORT_OUTPUT,
"data_inv",
0, num_outputs - 1);
fprintf(fp, "\n);\n");
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
"data_reg",
0, num_outputs - 1);
fprintf(fp, ";\n");
/* Print the truth table of this encoder */
/* Internal logics */
/* 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
* We should narrow the encoding to be applied to a given set of data
* This will lead to that any addr which falls out of the op code of data
* will give a all-zero code
* For example:
* data is 5-bit while addr is 3-bit
* data=8'b0_0000 is reserved by addr=3'b000;
* data=8'b0_0001 will be encoded to addr=3'b001;
* data=8'b0_0010 will be encoded to addr=3'b010;
* data=8'b0_0100 will be encoded to addr=3'b011;
* data=8'b0_1000 will be encoded to addr=3'b100;
* data=8'b1_0000 will be encoded to addr=3'b101;
* The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000;
*/
fprintf(fp, "always@(addr, data)\n");
fprintf(fp, "begin\n");
fprintf(fp, "\tdata_reg = %d'b0;\n", num_outputs);
fprintf(fp, "\tif ((0 < addr) && (addr < %d) ) begin\n", num_outputs);
fprintf(fp, "\t\tdata_reg = 1'b1 << (addr - 1);\n");
fprintf(fp, "\tend\n");
fprintf(fp, "end\n");
fprintf(fp, "assign data = data_reg;\n");
fprintf(fp, "assign data_inv = ~data;\n");
/* Finish */
fprintf(fp, "endmodule\n");
fprintf(fp, "//-------- END Local Decoder convert %d-bit addr to %d-bit data \n\n",
num_inputs, num_outputs);
return;
}
/* We should count how many multiplexers with different sizes are needed */
static
void dump_verilog_submodule_local_encoders(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* submodule_dir,
int num_switch,
t_switch_inf* switches,
t_spice* spice,
t_det_routing_arch* routing_arch,
bool is_explicit_mapping) {
/* Statisitcs for input sizes and structures of MUXes
* used in FPGA architecture
*/
/* We have linked list whichs stores spice model information of multiplexer*/
t_llist* muxes_head = NULL;
t_llist* temp = NULL;
FILE* fp = NULL;
char* verilog_name = my_strcat(submodule_dir, local_encoder_verilog_file_name);
int num_input_ports = 0;
t_spice_model_port** input_ports = NULL;
int num_sram_ports = 0;
t_spice_model_port** sram_ports = NULL;
int num_input_basis = 0;
t_spice_mux_model* cur_spice_mux_model = NULL;
/* Alloc the muxes*/
muxes_head = stats_spice_muxes(num_switch, switches, spice, routing_arch);
/* Print the muxes netlist*/
fp = fopen(verilog_name, "w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create subckt SPICE netlist %s",__FILE__, __LINE__, verilog_name);
exit(1);
}
/* Generate the descriptions*/
dump_verilog_file_header(fp,"MUXes used in FPGA");
verilog_include_defines_preproc_file(fp, verilog_dir);
/* Create a vector for local encoders with different sizes */
std::vector<int> encoder_sizes;
/* Make sure a clean start */
encoder_sizes.clear();
/* Print mux netlist one by one*/
temp = muxes_head;
while(temp) {
assert(NULL != temp->dptr);
cur_spice_mux_model = (t_spice_mux_model*)(temp->dptr);
/* Bypass the spice models who has a user-defined subckt */
if (NULL != cur_spice_mux_model->spice_model->verilog_netlist) {
input_ports = find_spice_model_ports(cur_spice_mux_model->spice_model, SPICE_MODEL_PORT_INPUT, &num_input_ports, TRUE);
sram_ports = find_spice_model_ports(cur_spice_mux_model->spice_model, SPICE_MODEL_PORT_SRAM, &num_sram_ports, TRUE);
assert(0 != num_input_ports);
assert(0 != num_sram_ports);
/* Check the Input port size */
if (cur_spice_mux_model->size != input_ports[0]->size) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d])User-defined MUX SPICE MODEL(%s) size(%d) unmatch with the architecture needs(%d)!\n",
__FILE__, __LINE__, cur_spice_mux_model->spice_model->name, input_ports[0]->size,cur_spice_mux_model->size);
exit(1);
}
/* Check the SRAM port size */
num_input_basis = determine_num_input_basis_multilevel_mux(cur_spice_mux_model->size,
cur_spice_mux_model->spice_model->design_tech_info.mux_info->mux_num_level);
if ((num_input_basis * cur_spice_mux_model->spice_model->design_tech_info.mux_info->mux_num_level) != sram_ports[0]->size) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s,[LINE%d])User-defined MUX SPICE MODEL(%s) SRAM size(%d) unmatch with the num of level(%d)!\n",
__FILE__, __LINE__, cur_spice_mux_model->spice_model->name, sram_ports[0]->size, cur_spice_mux_model->spice_model->design_tech_info.mux_info->mux_num_level*num_input_basis);
exit(1);
}
/* Move on to the next*/
temp = temp->next;
continue;
}
/* Bypass those without local encoders, we only care SPICE models whose type is MUX! */
if ( (SPICE_MODEL_MUX != cur_spice_mux_model->spice_model->type)
|| (FALSE == cur_spice_mux_model->spice_model->design_tech_info.mux_info->local_encoder) ) {
/* Move on to the next*/
temp = temp->next;
continue;
}
/* Reach here, we need to generate a local encoder Verilog module */
/* Generate the spice_mux_arch */
cur_spice_mux_model->spice_mux_arch = (t_spice_mux_arch*)my_malloc(sizeof(t_spice_mux_arch));
init_spice_mux_arch(cur_spice_mux_model->spice_model, cur_spice_mux_model->spice_mux_arch, cur_spice_mux_model->size);
/* We will bypass all the TREE-LIKE multiplexers and those with 2-inputs */
if ( (SPICE_MODEL_STRUCTURE_TREE == cur_spice_mux_model->spice_mux_arch->structure)
|| ( 2 == cur_spice_mux_model->spice_mux_arch->num_input) ) {
/* Move on to the next*/
temp = temp->next;
continue;
}
/* Find the size of local encoders */
std::vector<int>::iterator it = std::find(encoder_sizes.begin(), encoder_sizes.end(), cur_spice_mux_model->spice_mux_arch->num_input_basis);
/* See if a same-sized local encoder is already in the list */
if (it == encoder_sizes.end()) {
/* Need to add to the list */
encoder_sizes.push_back(cur_spice_mux_model->spice_mux_arch->num_input_basis);
}
/* Move on to the next*/
temp = temp->next;
}
/* Print the local encoder subckt */
for (size_t i = 0; i < encoder_sizes.size(); ++i) {
dump_verilog_mux_local_encoder_module(fp, encoder_sizes[i]);
}
vpr_printf(TIO_MESSAGE_INFO,"Generated %d local encoders for Multiplexers.\n",
encoder_sizes.size());
/* Add fname to the linked list */
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_name);
/* Close the file*/
fclose(fp);
/* remember to free the linked list*/
free_muxes_llist(muxes_head);
/* Free strings */
free(verilog_name);
return;
}
static
void dump_verilog_wire_module(FILE* fp,
char* wire_subckt_name,
t_spice_model verilog_model) {
@ -2765,6 +3111,7 @@ void dump_verilog_wire_module(FILE* fp,
}
/* Dump one module of a LUT */
static
void dump_verilog_submodule_one_lut(FILE* fp,
t_spice_model* verilog_model,
bool is_explicit_mapping) {
@ -3203,6 +3550,7 @@ void dump_verilog_submodule_one_lut(FILE* fp,
}
/* Dump one module of a LUT */
static
void dump_verilog_submodule_one_mem(FILE* fp,
t_spice_model* verilog_model) {
int iport, ipin, pin_index;
@ -3275,6 +3623,7 @@ void dump_verilog_submodule_one_mem(FILE* fp,
}
/* Dump verilog top-level module for LUTs */
static
void dump_verilog_submodule_luts(char* verilog_dir,
char* submodule_dir,
int num_spice_model,
@ -3316,70 +3665,7 @@ void dump_verilog_submodule_luts(char* verilog_dir,
return;
}
/* Dump a submodule which is a constant vdd */
void dump_verilog_hard_wired_vdd(FILE* fp,
t_spice_model verilog_model) {
int num_output_port = 0;
t_spice_model_port** output_port = NULL;
/* Find the input port, output port*/
output_port = find_spice_model_ports(&verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
/* Asserts*/
assert(1 == num_output_port);
assert(1 == output_port[0]->size);
/* Ensure a valid file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* print the spice model*/
fprintf(fp, "//-----Hard-wired VDD module, verilog_model_name=%s -----\n", verilog_model.name);
fprintf(fp, "module %s(output wire %s);\n", verilog_model.name, output_port[0]->prefix);
/* Constant logic 1*/
fprintf(fp, "assign %s = 1\'b1;\n", output_port[0]->prefix);
/* Finish*/
fprintf(fp, "endmodule\n");
fprintf(fp, "//-----END VDD module, verilog_model_name=%s -----\n", verilog_model.name);
fprintf(fp, "\n");
return;
}
/* Dump a submodule which is a constant vdd */
void dump_verilog_hard_wired_gnd(FILE* fp,
t_spice_model verilog_model) {
int num_output_port = 0;
t_spice_model_port** output_port = NULL;
/* Find the input port, output port*/
output_port = find_spice_model_ports(&verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
/* Asserts*/
assert(1 == num_output_port);
assert(1 == output_port[0]->size);
/* Ensure a valid file handler*/
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File handler.\n",
__FILE__, __LINE__);
exit(1);
}
/* print the spice model*/
fprintf(fp, "//-----Hard-wired GND module, verilog_model_name=%s -----\n", verilog_model.name);
fprintf(fp, "module %s(output wire %s);\n", verilog_model.name, output_port[0]->prefix);
/* Constant logic 1*/
fprintf(fp, "assign %s = 1\'b0;\n", output_port[0]->prefix);
/* Finish*/
fprintf(fp, "endmodule\n");
fprintf(fp, "//-----END GND module, verilog_model_name=%s -----\n", verilog_model.name);
fprintf(fp, "\n");
return;
}
static
void dump_verilog_submodule_wires(char* verilog_dir,
char* subckt_dir,
int num_segments,
@ -3461,6 +3747,7 @@ void dump_verilog_submodule_wires(char* verilog_dir,
return;
}
static
void dump_verilog_submodule_memories(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* submodule_dir,
@ -3579,34 +3866,8 @@ void dump_verilog_submodule_memories(t_sram_orgz_info* cur_sram_orgz_info,
return;
}
/* Print a non-global port for the template */
void dump_one_verilog_template_module_one_port(FILE* fp, int* cnt,
t_spice_model* cur_spice_model,
enum e_spice_model_port_type port_type) {
int iport;
int num_port_to_dump= 0;
t_spice_model_port** port_to_dump = NULL;
port_to_dump = find_spice_model_ports(cur_spice_model, port_type, &num_port_to_dump, TRUE);
for (iport = 0; iport < num_port_to_dump; iport++) {
if (0 < *cnt) {
fprintf(fp, ",\n");
}
dump_verilog_generic_port(fp,
convert_spice_model_port_type_to_verilog_port_type(port_to_dump[iport]->type),
port_to_dump[iport]->lib_name,
port_to_dump[iport]->size - 1, 0);
(*cnt)++;
}
/* Free */
my_free(port_to_dump);
return;
}
/* Give a template for a user-defined module */
static
void dump_one_verilog_template_module(FILE* fp,
t_spice_model* cur_spice_model) {
int iport;
@ -3663,6 +3924,7 @@ void dump_one_verilog_template_module(FILE* fp,
}
/* Give a template of all the submodules that are user-defined */
static
void dump_verilog_submodule_templates(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* submodule_dir,
@ -3714,13 +3976,15 @@ void dump_verilog_submodules(t_sram_orgz_info* cur_sram_orgz_info,
vpr_printf(TIO_MESSAGE_INFO, "Generating essential modules...\n");
dump_verilog_submodule_essentials(verilog_dir, submodule_dir,
Arch.spice->num_spice_model,
Arch.spice->spice_models,
fpga_verilog_opts);
Arch.spice->spice_models);
/* 1. MUXes */
vpr_printf(TIO_MESSAGE_INFO, "Generating modules of multiplexers...\n");
dump_verilog_submodule_muxes(cur_sram_orgz_info, verilog_dir, submodule_dir, routing_arch->num_switch,
switch_inf, Arch.spice, routing_arch, fpga_verilog_opts.dump_explicit_verilog);
vpr_printf(TIO_MESSAGE_INFO, "Generating local encoders for multiplexers...\n");
dump_verilog_submodule_local_encoders(cur_sram_orgz_info, verilog_dir, submodule_dir, routing_arch->num_switch,
switch_inf, Arch.spice, routing_arch, fpga_verilog_opts.dump_explicit_verilog);
/* 2. LUTes */
vpr_printf(TIO_MESSAGE_INFO, "Generating modules of LUTs...\n");

View File

@ -1,7 +1,9 @@
#ifndef VERILOG_SUBMODULES_H
#define VERILOG_SUBMODULES_H
void dump_verilog_submodules(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* submodule_dir,
t_arch Arch,
t_det_routing_arch* routing_arch,
t_syn_verilog_opts fpga_verilog_opts);
#endif

View File

@ -2915,6 +2915,19 @@ char* generate_verilog_mem_subckt_name(t_spice_model* spice_model,
return subckt_name;
}
/* Generate the subckt name for a decoder submodule */
char* generate_verilog_decoder_subckt_name(int addr_len, int data_len) {
char* subckt_name = NULL;
subckt_name = (char*)my_malloc(sizeof(char)*(strlen("decoder")
+ strlen(my_itoa(addr_len)) + 2
+ strlen(my_itoa(data_len)) + 1));
sprintf(subckt_name, "%s%dto%d",
"decoder", addr_len, data_len);
return subckt_name;
}
/* Generate the subckt name for a MUX module/submodule */
char* generate_verilog_mux_basis_subckt_name(t_spice_model* spice_model,
int mux_size, char* postfix) {
@ -3029,7 +3042,10 @@ int dump_verilog_mem_module_one_port_map(FILE* fp,
return cnt;
}
/* Output the ports of a SRAM MUX */
/*
* Dump the port map of a memory module
* which consist of a number of SRAMs/SCFFs etc.
*/
void dump_verilog_mem_module_port_map(FILE* fp,
t_spice_model* mem_model,
boolean dump_port_type,

View File

@ -221,6 +221,8 @@ char* generate_verilog_mem_subckt_name(t_spice_model* spice_model,
t_spice_model* mem_model,
char* postfix);
char* generate_verilog_decoder_subckt_name(int addr_len, int data_len);
char* generate_verilog_mux_basis_subckt_name(t_spice_model* spice_model,
int mux_size, char* postfix);