Merge pull request #10 from RapidSilicon/phy_mem_bank
Support WLR signal in physical friendly memory bank
This commit is contained in:
commit
8a3ce62d70
|
@ -201,7 +201,7 @@ A circuit model may consist of a number of ports. The port list is mandatory in
|
|||
|
||||
.. note:: Different types of ``circuit_model`` have different XML syntax, with which users can highly customize their circuit topologies. See refer to examples of :ref:``circuit_model_example`` for more details.
|
||||
|
||||
.. note:: Note that we have a list of reserved port names, which indicate the usage of these ports when building FPGA fabrics. Please do not use ``mem_out``, ``mem_inv``, ``bl``, ``wl``, ``blb``, ``wlb``, ``ccff_head`` and ``ccff_tail``.
|
||||
.. note:: Note that we have a list of reserved port names, which indicate the usage of these ports when building FPGA fabrics. Please do not use ``mem_out``, ``mem_inv``, ``bl``, ``wl``, ``blb``, ``wlb``, ``wlr``, ``ccff_head`` and ``ccff_tail``.
|
||||
|
||||
FPGA I/O Port
|
||||
^^^^^^^^^^^^^
|
||||
|
|
|
@ -333,6 +333,36 @@ The following XML codes describes the SRAM cell shown in :numref:`fig_sram_blwl`
|
|||
|
||||
.. note:: When the ``memory_bank`` type of configuration procotol is specified, SRAM modules should have a BL and a WL.
|
||||
|
||||
.. _circuit_model_sram_blwlr_example:
|
||||
|
||||
SRAM with BL/WL/WLR
|
||||
```````````````````
|
||||
.. _fig_sram_blwlr:
|
||||
|
||||
.. figure:: ./figures/sram_blwlr.svg
|
||||
:scale: 100%
|
||||
|
||||
An example of a SRAM with Bit-Line (BL), Word-Line (WL) and WL read control signals
|
||||
|
||||
The following XML codes describes the SRAM cell shown in :numref:`fig_sram_blwlr`.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<circuit_model type="sram" name="sram_blwlr" prefix="sram_blwlr" verilog_netlist="sram.v" spice_netlist="sram.sp"/>
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="false"/>
|
||||
<output_buffer exist="false"/>
|
||||
<port type="bl" prefix="bl" size="1"/>
|
||||
<port type="wl" prefix="wl" size="1"/>
|
||||
<port type="wlr" prefix="wlr" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="output" prefix="outb" size="1"/>
|
||||
</circuit_model>
|
||||
|
||||
.. note:: OpenFPGA always assume that a ``WL`` port should be the write enable signal, a ``WLR`` port should be the read enable signal, while a ``BL`` port is the data input.
|
||||
|
||||
.. note:: When the ``memory_bank`` type of configuration procotol is specified, SRAM modules should have a BL and a WL. WLR is optional
|
||||
|
||||
.. _circuit_model_config_latch_example:
|
||||
|
||||
Configurable Latch
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="102.24 198 171.66498 227.98976" width="171.66498" height="227.98976">
|
||||
<defs>
|
||||
<font-face font-family="Times New Roman" font-size="12" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1361.0827" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
|
||||
<font-face-src>
|
||||
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<font-face font-family="Times New Roman" font-size="14" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1166.6423" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
|
||||
<font-face-src>
|
||||
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<font-face font-family="Times New Roman" font-size="11" panose-1="2 2 5 3 5 4 5 9 3 4" units-per-em="1000" underline-position="-108.88672" underline-thickness="48.828125" slope="-1484.8175" x-height="430.1758" cap-height="662.1094" ascent="891.1133" descent="-216.3086" font-style="italic" font-weight="400">
|
||||
<font-face-src>
|
||||
<font-face-name name="TimesNewRomanPS-ItalicMT"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
</defs>
|
||||
<metadata> Produced by OmniGraffle 7.18.5\n2021-09-21 03:12:41 +0000</metadata>
|
||||
<g id="Canvas_1" stroke="none" stroke-dasharray="none" fill="none" fill-opacity="1" stroke-opacity="1">
|
||||
<title>Canvas 1</title>
|
||||
<g id="Canvas_1_Layer_1">
|
||||
<title>Layer 1</title>
|
||||
<g id="Graphic_8046">
|
||||
<path d="M 127.68 198.72 L 250.92 198.72 L 250.92 312.01722 L 127.68 312.01722 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4.0,4.0" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Graphic_34596">
|
||||
<text transform="translate(155.90445 208.44)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">WL</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Graphic_35704">
|
||||
<text transform="translate(104.17804 235.33)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">BL</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Group_35767">
|
||||
<g id="Line_35770">
|
||||
<path d="M 149.2183 242.6686 L 156.64962 242.6686 L 156.64962 233.84905 L 171.51226 233.84905 L 171.51226 242.6686 L 178.94358 242.6686" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35769">
|
||||
<line x1="164.08094" y1="230.72207" x2="164.08094" y2="222.9025" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35768">
|
||||
<line x1="156.64962" y1="230.72207" x2="171.51226" y2="230.72207" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Graphic_35772">
|
||||
<rect x="156.41637" y="339.84" width="68.054996" height="58.68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
<text transform="translate(161.41637 361.38263)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="14" font-style="italic" font-weight="400" fill="black" x="11.144686" y="12">SRAM</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Graphic_35773">
|
||||
<text transform="translate(243.51697 348.48)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="11" font-style="italic" font-weight="400" fill="black" x="0" y="10">out</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Graphic_35774">
|
||||
<text transform="translate(241.45736 372.5285)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="11" font-style="italic" font-weight="400" fill="black" x="0" y="10">outb</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Graphic_35775">
|
||||
<text transform="translate(128.17804 361.68)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">BL</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Graphic_35777">
|
||||
<text transform="translate(162.73144 411.48)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">WL</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Line_35778">
|
||||
<line x1="156.41637" y1="368.68" x2="144.72758" y2="368.6938" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35781">
|
||||
<line x1="237.71537" y1="355.48" x2="226.02657" y2="355.4938" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35780">
|
||||
<line x1="237.71537" y1="378.26216" x2="226.02657" y2="378.27596" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35782">
|
||||
<line x1="171.0341" y1="411.48" x2="170.97639" y2="398.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35783">
|
||||
<path d="M 196.65095 317.8024 L 187.53514 317.8024 L 187.53514 327.1839 L 184.64166 327.1839 L 192.09304 334.05483 L 199.54443 327.1839 L 196.65095 327.1839 Z" fill="#c0ffff"/>
|
||||
<path d="M 196.65095 317.8024 L 187.53514 317.8024 L 187.53514 327.1839 L 184.64166 327.1839 L 192.09304 334.05483 L 199.54443 327.1839 L 196.65095 327.1839 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Graphic_35785">
|
||||
<text transform="translate(195.02518 411.48)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">WLR</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Line_35784">
|
||||
<line x1="206.99287" y1="411.48" x2="206.93516" y2="398.52" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Group_35786">
|
||||
<g id="Graphic_35790">
|
||||
<path d="M 197.45672 215.28 L 212.31937 225.18842 L 197.45672 235.09685 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35789">
|
||||
<circle cx="214.79647" cy="225.18842" r="2.47710469423255" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35788">
|
||||
<line x1="192.5025" y1="225.18842" x2="196.45672" y2="225.18842" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35787">
|
||||
<line x1="218.27358" y1="225.18842" x2="222.2278" y2="225.18842" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Group_35791">
|
||||
<g id="Graphic_35795">
|
||||
<path d="M 217.27358 246.93685 L 202.41094 256.84528 L 217.27358 266.7537 Z" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35794">
|
||||
<circle cx="199.93383" cy="256.84528" r="2.47710469423254" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35793">
|
||||
<line x1="222.2278" y1="256.84528" x2="218.27358" y2="256.84528" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35792">
|
||||
<line x1="196.45672" y1="256.84528" x2="192.5025" y2="256.84528" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_35797">
|
||||
<line x1="192.5025" y1="225.18842" x2="192.5025" y2="256.84528" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35798">
|
||||
<line x1="222.3825" y1="224.64" x2="222.2278" y2="257.12" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35803">
|
||||
<line x1="222.3153" y1="238.7479" x2="251.50138" y2="238.495" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35804">
|
||||
<text transform="translate(254.34883 230.20132)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="11" font-style="italic" font-weight="400" fill="black" x="0" y="10">outb</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Line_35805">
|
||||
<path d="M 250.375 204.375 L 192.5025 204.875 L 192.5025 225.18842" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35806">
|
||||
<line x1="178.94358" y1="242.62" x2="192.5025" y2="242.37" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35807">
|
||||
<text transform="translate(254.34883 198)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="11" font-style="italic" font-weight="400" fill="black" x="0" y="10">out</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Group_35808">
|
||||
<g id="Line_35811">
|
||||
<path d="M 149.14524 267.52314 L 149.14524 274.95446 L 157.9648 274.95446 L 157.9648 289.8171 L 149.14524 289.8171 L 149.14524 297.24842" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35810">
|
||||
<line x1="161.09179" y1="282.38578" x2="168.91134" y2="282.38578" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35809">
|
||||
<line x1="161.09179" y1="274.95446" x2="161.09179" y2="289.8171" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_35817">
|
||||
<line x1="127.68" y1="242.875" x2="149.2183" y2="242.6686" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35818">
|
||||
<text transform="translate(102.24 252.04776)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="12" font-style="italic" font-weight="400" fill="black" x="0" y="11">WLR</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Graphic_35819">
|
||||
<text transform="translate(137.36102 295.24314)" fill="black">
|
||||
<tspan font-family="Times New Roman" font-size="11" font-style="italic" font-weight="400" fill="black" x="0" y="10">GND</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g id="Line_35820">
|
||||
<path d="M 168.91134 282.38578 L 241.12887 281.725 L 241.0367 238.58568" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Graphic_35821">
|
||||
<ellipse cx="240.89" cy="238.20685" rx="2.52000397038629" ry="2.87686226095125" fill="black"/>
|
||||
<ellipse cx="240.89" cy="238.20685" rx="2.52000397038629" ry="2.87686226095125" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Graphic_35822">
|
||||
<ellipse cx="222.7278" cy="238.2937" rx="2.52000397038632" ry="2.87686226095122" fill="black"/>
|
||||
<ellipse cx="222.7278" cy="238.2937" rx="2.52000397038632" ry="2.87686226095122" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Graphic_35823">
|
||||
<ellipse cx="192.09304" cy="242.83" rx="2.52000397038633" ry="2.87686226095122" fill="black"/>
|
||||
<ellipse cx="192.09304" cy="242.83" rx="2.52000397038633" ry="2.87686226095122" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Graphic_35824">
|
||||
<ellipse cx="192.20189" cy="225.18842" rx="2.52000397038633" ry="2.87686226095122" fill="black"/>
|
||||
<ellipse cx="192.20189" cy="225.18842" rx="2.52000397038633" ry="2.87686226095122" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Graphic_35825">
|
||||
<ellipse cx="149.09" cy="242.83" rx="2.5200039703863" ry="2.87686226095122" fill="black"/>
|
||||
<ellipse cx="149.09" cy="242.83" rx="2.5200039703863" ry="2.87686226095122" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="Group_35827">
|
||||
<g id="Line_35830">
|
||||
<path d="M 149.14524 244.44 L 149.14524 251.87132 L 140.32569 251.87132 L 140.32569 266.73396 L 149.14524 266.73396 L 149.14524 274.16528" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35829">
|
||||
<line x1="137.1987" y1="259.30264" x2="129.37915" y2="259.30264" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="Line_35828">
|
||||
<line x1="137.1987" y1="251.87132" x2="137.1987" y2="266.73396" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
|
@ -101,10 +101,11 @@ enum e_circuit_model_port_type {
|
|||
CIRCUIT_MODEL_PORT_BLB,
|
||||
CIRCUIT_MODEL_PORT_WL,
|
||||
CIRCUIT_MODEL_PORT_WLB,
|
||||
CIRCUIT_MODEL_PORT_WLR,
|
||||
NUM_CIRCUIT_MODEL_PORT_TYPES
|
||||
};
|
||||
/* Strings correspond to each port type */
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PORT_TYPES> CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb"}};
|
||||
constexpr std::array<const char*, NUM_CIRCUIT_MODEL_PORT_TYPES> CIRCUIT_MODEL_PORT_TYPE_STRING = {{"input", "output", "inout", "clock", "sram", "bl", "blb", "wl", "wlb", "wlr"}};
|
||||
|
||||
enum e_circuit_model_delay_type {
|
||||
CIRCUIT_MODEL_DELAY_RISE,
|
||||
|
|
|
@ -33,6 +33,7 @@ constexpr char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_";
|
|||
constexpr char* MEMORY_MODULE_POSTFIX = "_mem";
|
||||
constexpr char* MEMORY_BL_PORT_NAME = "bl";
|
||||
constexpr char* MEMORY_WL_PORT_NAME = "wl";
|
||||
constexpr char* MEMORY_WLR_PORT_NAME = "wlr";
|
||||
|
||||
/* Multiplexer naming constant strings */
|
||||
constexpr char* MUX_BASIS_MODULE_POSTFIX = "_basis";
|
||||
|
@ -48,6 +49,8 @@ constexpr char* DECODER_DATA_OUT_PORT_NAME = "data_out";
|
|||
constexpr char* DECODER_DATA_OUT_INV_PORT_NAME = "data_out_inv";
|
||||
constexpr char* DECODER_BL_ADDRESS_PORT_NAME = "bl_address";
|
||||
constexpr char* DECODER_WL_ADDRESS_PORT_NAME = "wl_address";
|
||||
constexpr char* DECODER_READBACK_PORT_NAME = "readback";
|
||||
constexpr char* DECODER_DATA_READ_ENABLE_PORT_NAME = "data_out_ren";
|
||||
|
||||
/* Inverted port naming */
|
||||
constexpr char* INV_PORT_POSTFIX = "_inv";
|
||||
|
|
|
@ -719,9 +719,11 @@ std::string generate_sram_port_name(const e_config_protocol_type& sram_orgz_type
|
|||
*/
|
||||
if (CIRCUIT_MODEL_PORT_BL == port_type) {
|
||||
port_name = std::string(MEMORY_BL_PORT_NAME);
|
||||
} else {
|
||||
VTR_ASSERT( CIRCUIT_MODEL_PORT_WL == port_type );
|
||||
} else if (CIRCUIT_MODEL_PORT_WL == port_type) {
|
||||
port_name = std::string(MEMORY_WL_PORT_NAME);
|
||||
} else {
|
||||
VTR_ASSERT( CIRCUIT_MODEL_PORT_WLR == port_type );
|
||||
port_name = std::string(MEMORY_WLR_PORT_NAME);
|
||||
}
|
||||
break;
|
||||
case CONFIG_MEM_FRAME_BASED:
|
||||
|
|
|
@ -184,6 +184,19 @@ ModuleId build_wl_memory_decoder_module(ModuleManager& module_manager,
|
|||
module_manager.add_port(module_id, data_inv_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
}
|
||||
|
||||
/* Add readback port */
|
||||
if (true == decoder_lib.use_readback(decoder)) {
|
||||
BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), 1);
|
||||
module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
|
||||
/* Add data read-enable port */
|
||||
if (true == decoder_lib.use_readback(decoder)) {
|
||||
BasicPort data_ren_port(std::string(DECODER_DATA_READ_ENABLE_PORT_NAME), data_size);
|
||||
module_manager.add_port(module_id, data_ren_port, ModuleManager::MODULE_OUTPUT_PORT);
|
||||
module_manager.set_port_is_register(module_id, data_ren_port.get_name(), true);
|
||||
}
|
||||
|
||||
return module_id;
|
||||
}
|
||||
|
||||
|
|
|
@ -366,12 +366,15 @@ void build_memory_flatten_module(ModuleManager& module_manager,
|
|||
/* Get the BL/WL ports from the SRAM */
|
||||
std::vector<CircuitPortId> sram_bl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_BL, true);
|
||||
std::vector<CircuitPortId> sram_wl_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WL, true);
|
||||
/* Optional: Get the WLR ports from the SRAM */
|
||||
std::vector<CircuitPortId> sram_wlr_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR, true);
|
||||
/* Get the output ports from the SRAM */
|
||||
std::vector<CircuitPortId> sram_output_ports = circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_OUTPUT, true);
|
||||
|
||||
/* Ensure that we have only 1 BL, 1 WL and 2 output ports*/
|
||||
/* Ensure that we have only 1 BL, 1 WL and 2 output ports, as well as an optional WLR*/
|
||||
VTR_ASSERT(1 == sram_bl_ports.size());
|
||||
VTR_ASSERT(1 == sram_wl_ports.size());
|
||||
VTR_ASSERT(2 > sram_wlr_ports.size());
|
||||
VTR_ASSERT(2 == sram_output_ports.size());
|
||||
|
||||
/* Create a module and add to the module manager */
|
||||
|
@ -389,6 +392,12 @@ void build_memory_flatten_module(ModuleManager& module_manager,
|
|||
BasicPort wl_port(std::string(MEMORY_WL_PORT_NAME), num_mems);
|
||||
ModulePortId mem_wl_port = module_manager.add_port(mem_module, wl_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
|
||||
BasicPort wlr_port(std::string(MEMORY_WLR_PORT_NAME), num_mems);
|
||||
ModulePortId mem_wlr_port = ModulePortId::INVALID();
|
||||
if (!sram_wlr_ports.empty()) {
|
||||
mem_wlr_port = module_manager.add_port(mem_module, wlr_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;
|
||||
|
@ -419,6 +428,9 @@ void build_memory_flatten_module(ModuleManager& module_manager,
|
|||
for (const CircuitPortId& port : sram_wl_ports) {
|
||||
add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wl_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance);
|
||||
}
|
||||
for (const CircuitPortId& port : sram_wlr_ports) {
|
||||
add_module_input_nets_to_mem_modules(module_manager, mem_module, mem_wlr_port, circuit_lib, port, sram_mem_module, i, sram_mem_instance);
|
||||
}
|
||||
/* Wire outputs of child module to outputs of parent module */
|
||||
add_module_output_nets_to_mem_modules(module_manager, mem_module, circuit_lib, sram_output_ports, sram_mem_module, i, sram_mem_instance);
|
||||
}
|
||||
|
@ -644,9 +656,9 @@ void build_frame_memory_module(ModuleManager& module_manager,
|
|||
* If we find one, we use the module.
|
||||
* Otherwise, we create one and add it to the decoder library
|
||||
*/
|
||||
DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv);
|
||||
DecoderId decoder_id = frame_decoder_lib.find_decoder(addr_size, data_size, true, false, use_data_inv, false);
|
||||
if (DecoderId::INVALID() == decoder_id) {
|
||||
decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv);
|
||||
decoder_id = frame_decoder_lib.add_decoder(addr_size, data_size, true, false, use_data_inv, false);
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != decoder_id);
|
||||
|
||||
|
|
|
@ -870,6 +870,12 @@ void add_top_module_sram_ports(ModuleManager& module_manager,
|
|||
BasicPort wl_addr_port(std::string(DECODER_WL_ADDRESS_PORT_NAME), wl_addr_size);
|
||||
module_manager.add_port(module_id, wl_addr_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
|
||||
/* Optional: If we have WLR port, we should add a read-back port */
|
||||
if (!circuit_lib.model_ports_by_type(sram_model, CIRCUIT_MODEL_PORT_WLR).empty()) {
|
||||
BasicPort readback_port(std::string(DECODER_READBACK_PORT_NAME), config_protocol.num_regions());
|
||||
module_manager.add_port(module_id, readback_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
}
|
||||
|
||||
/* Data input should be dependent on the number of configuration regions*/
|
||||
BasicPort din_port(std::string(DECODER_DATA_IN_PORT_NAME), config_protocol.num_regions());
|
||||
module_manager.add_port(module_id, din_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
|
@ -1056,9 +1062,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag
|
|||
* Otherwise, we create one and add it to the decoder library
|
||||
*/
|
||||
DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls,
|
||||
true, true, false);
|
||||
true, true, false, false);
|
||||
if (DecoderId::INVALID() == bl_decoder_id) {
|
||||
bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false);
|
||||
bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false);
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id);
|
||||
|
||||
|
@ -1084,9 +1090,9 @@ void add_top_module_nets_cmos_memory_bank_config_bus(ModuleManager& module_manag
|
|||
* Otherwise, we create one and add it to the decoder library
|
||||
*/
|
||||
DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls,
|
||||
true, false, false);
|
||||
true, false, false, false);
|
||||
if (DecoderId::INVALID() == wl_decoder_id) {
|
||||
wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false);
|
||||
wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, false);
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id);
|
||||
|
||||
|
@ -1533,9 +1539,9 @@ void add_top_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& mod
|
|||
/* Search the decoder library and try to find one
|
||||
* If not found, create a new module and add it to the module manager
|
||||
*/
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false);
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false);
|
||||
if (DecoderId::INVALID() == decoder_id) {
|
||||
decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false);
|
||||
decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false);
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != decoder_id);
|
||||
|
||||
|
|
|
@ -137,6 +137,16 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
|||
/* Data in port should match the number of configuration regions */
|
||||
VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size());
|
||||
|
||||
/* Find readback port from the top-level module */
|
||||
ModulePortId readback_port = module_manager.find_module_port(top_module, std::string(DECODER_READBACK_PORT_NAME));
|
||||
BasicPort readback_port_info;
|
||||
|
||||
/* Readback port if available, should be a 1-bit port */
|
||||
if (readback_port) {
|
||||
readback_port_info = module_manager.module_port(top_module, readback_port);
|
||||
VTR_ASSERT(readback_port_info.get_width() == 1);
|
||||
}
|
||||
|
||||
/* Find BL and WL address port from the top-level module */
|
||||
ModulePortId bl_addr_port = module_manager.find_module_port(top_module, std::string(DECODER_BL_ADDRESS_PORT_NAME));
|
||||
BasicPort bl_addr_port_info = module_manager.module_port(top_module, bl_addr_port);
|
||||
|
@ -168,9 +178,9 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
|||
* Otherwise, we create one and add it to the decoder library
|
||||
*/
|
||||
DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls,
|
||||
true, true, false);
|
||||
true, true, false, false);
|
||||
if (DecoderId::INVALID() == bl_decoder_id) {
|
||||
bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false);
|
||||
bl_decoder_id = decoder_lib.add_decoder(bl_addr_size, num_bls, true, true, false, false);
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != bl_decoder_id);
|
||||
|
||||
|
@ -196,9 +206,9 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
|||
* Otherwise, we create one and add it to the decoder library
|
||||
*/
|
||||
DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls,
|
||||
true, false, false);
|
||||
true, false, false, readback_port != ModulePortId::INVALID());
|
||||
if (DecoderId::INVALID() == wl_decoder_id) {
|
||||
wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false);
|
||||
wl_decoder_id = decoder_lib.add_decoder(wl_addr_size, num_wls, true, false, false, readback_port != ModulePortId::INVALID());
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != wl_decoder_id);
|
||||
|
||||
|
@ -264,7 +274,13 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
|||
BasicPort wl_decoder_en_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_en_port);
|
||||
|
||||
ModulePortId wl_decoder_addr_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_ADDRESS_PORT_NAME));
|
||||
BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, bl_decoder_addr_port);
|
||||
BasicPort wl_decoder_addr_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_addr_port);
|
||||
|
||||
ModulePortId wl_decoder_readback_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_READBACK_PORT_NAME));
|
||||
BasicPort wl_decoder_readback_port_info;
|
||||
if (wl_decoder_readback_port) {
|
||||
wl_decoder_readback_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_readback_port);
|
||||
}
|
||||
|
||||
/* Top module Enable port -> WL Decoder Enable port */
|
||||
add_module_bus_nets(module_manager,
|
||||
|
@ -278,6 +294,14 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
|||
top_module, 0, wl_addr_port,
|
||||
wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_addr_port);
|
||||
|
||||
/* Top module readback port -> WL Decoder readback port */
|
||||
if (wl_decoder_readback_port) {
|
||||
add_module_bus_nets(module_manager,
|
||||
top_module,
|
||||
top_module, 0, readback_port,
|
||||
wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_readback_port);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* Precompute the BLs and WLs distribution across the FPGA fabric
|
||||
* The distribution is a matrix which contains the starting index of BL/WL for each column or row
|
||||
|
@ -391,6 +415,45 @@ void add_top_module_nets_cmos_ql_memory_bank_config_bus(ModuleManager& module_ma
|
|||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* Optional: Add nets from WLR data out to each configurable child
|
||||
*/
|
||||
ModulePortId wl_decoder_data_ren_port = module_manager.find_module_port(wl_decoder_module, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME));
|
||||
BasicPort wl_decoder_data_ren_port_info;
|
||||
if (wl_decoder_data_ren_port) {
|
||||
wl_decoder_data_ren_port_info = module_manager.module_port(wl_decoder_module, wl_decoder_data_ren_port);
|
||||
for (size_t child_id = 0; child_id < module_manager.region_configurable_children(top_module, config_region).size(); ++child_id) {
|
||||
ModuleId child_module = module_manager.region_configurable_children(top_module, config_region)[child_id];
|
||||
vtr::Point<int> coord = module_manager.region_configurable_child_coordinates(top_module, config_region)[child_id];
|
||||
|
||||
size_t child_instance = module_manager.region_configurable_child_instances(top_module, config_region)[child_id];
|
||||
|
||||
/* Find the WL port */
|
||||
ModulePortId child_wlr_port = module_manager.find_module_port(child_module, std::string(MEMORY_WLR_PORT_NAME));
|
||||
BasicPort child_wlr_port_info = module_manager.module_port(child_module, child_wlr_port);
|
||||
|
||||
size_t cur_wlr_index = 0;
|
||||
|
||||
for (const size_t& sink_wlr_pin : child_wlr_port_info.pins()) {
|
||||
size_t wlr_pin_id = wl_start_index_per_tile[coord.y()] + cur_wlr_index;
|
||||
VTR_ASSERT(wlr_pin_id < wl_decoder_data_ren_port_info.pins().size());
|
||||
|
||||
/* Create net */
|
||||
ModuleNetId net = create_module_source_pin_net(module_manager, top_module,
|
||||
wl_decoder_module, curr_wl_decoder_instance_id,
|
||||
wl_decoder_data_ren_port,
|
||||
wl_decoder_data_ren_port_info.pins()[wlr_pin_id]);
|
||||
VTR_ASSERT(ModuleNetId::INVALID() != net);
|
||||
|
||||
/* Add net sink */
|
||||
module_manager.add_module_net_sink(top_module, net,
|
||||
child_module, child_instance, child_wlr_port, sink_wlr_pin);
|
||||
|
||||
cur_wlr_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* Add the BL and WL decoders to the end of configurable children list
|
||||
* Note: this MUST be done after adding all the module nets to other regular configurable children
|
||||
|
|
|
@ -289,6 +289,20 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
|
|||
data_inv_port = module_manager.module_port(module_id, data_inv_port_id);
|
||||
}
|
||||
|
||||
/* Find readback port */
|
||||
ModulePortId readback_port_id = module_manager.find_module_port(module_id, std::string(DECODER_READBACK_PORT_NAME));
|
||||
BasicPort readback_port;
|
||||
if (readback_port_id) {
|
||||
readback_port = module_manager.module_port(module_id, readback_port_id);
|
||||
}
|
||||
|
||||
/* Find data read-enable port */
|
||||
ModulePortId data_ren_port_id = module_manager.find_module_port(module_id, std::string(DECODER_DATA_READ_ENABLE_PORT_NAME));
|
||||
BasicPort data_ren_port;
|
||||
if (data_ren_port_id) {
|
||||
data_ren_port = module_manager.module_port(module_id, data_ren_port_id);
|
||||
}
|
||||
|
||||
/* dump module definition + ports */
|
||||
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
|
||||
/* Finish dumping ports */
|
||||
|
@ -303,10 +317,18 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
|
|||
* else data_out is driven by '0'
|
||||
*/
|
||||
if (1 == data_size) {
|
||||
/* Output logics for data output */
|
||||
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
|
||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
|
||||
/* If there is a readback port, the data output is only enabled when readback is disabled */
|
||||
if (readback_port_id) {
|
||||
fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
|
||||
}
|
||||
fp << ") begin" << std::endl;
|
||||
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && (";
|
||||
if (readback_port_id) {
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) && (";
|
||||
}
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
|
||||
fp << " begin" << std::endl;
|
||||
fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector<size_t>(1, 1)) << ";" << std::endl;
|
||||
|
@ -315,6 +337,26 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
|
|||
fp << "\t" << "end" << std::endl;
|
||||
fp << "end" << std::endl;
|
||||
|
||||
/* Output logics for data readback output */
|
||||
if (data_ren_port_id) {
|
||||
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
|
||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
|
||||
/* If there is a readback port, the data output is only enabled when readback is disabled */
|
||||
if (readback_port_id) {
|
||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
|
||||
}
|
||||
fp << ") begin" << std::endl;
|
||||
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && (";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) && (";
|
||||
fp << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
|
||||
fp << " begin" << std::endl;
|
||||
fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector<size_t>(1, 1)) << ";" << std::endl;
|
||||
fp << "\t" << "end else begin" << std::endl;
|
||||
fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, std::vector<size_t>(1, 0)) << ";" << std::endl;
|
||||
fp << "\t" << "end" << std::endl;
|
||||
fp << "end" << std::endl;
|
||||
}
|
||||
|
||||
/* Depend on if the inverted data output port is needed or not */
|
||||
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||
print_verilog_wire_connection(fp, data_inv_port, addr_port, true);
|
||||
|
@ -344,10 +386,23 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
|
|||
* The rest of addr codes 3'b110, 3'b111 will be decoded to data=8'b0_0000;
|
||||
*/
|
||||
|
||||
/* Output logics for data output */
|
||||
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
|
||||
/* If there is a readback port, the data output is only enabled when readback is disabled */
|
||||
if (readback_port_id) {
|
||||
fp << " or " << "~" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
|
||||
}
|
||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
|
||||
fp << ") begin" << std::endl;
|
||||
fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl;
|
||||
if (readback_port_id) {
|
||||
fp << "\tif (";
|
||||
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) ";
|
||||
fp << "&&";
|
||||
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b0) ";
|
||||
fp << ") begin" << std::endl;
|
||||
} else {
|
||||
fp << "\tif (" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) begin" << std::endl;
|
||||
}
|
||||
fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||
/* Create a string for addr and data */
|
||||
for (size_t i = 0; i < data_size; ++i) {
|
||||
|
@ -373,6 +428,46 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
|
|||
|
||||
fp << "end" << std::endl;
|
||||
|
||||
/* Output logics for data readback output */
|
||||
if (data_ren_port_id) {
|
||||
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
|
||||
/* If there is a readback port, the data output is only enabled when readback is disabled */
|
||||
if (readback_port_id) {
|
||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, readback_port);
|
||||
}
|
||||
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
|
||||
fp << ") begin" << std::endl;
|
||||
fp << "\tif (";
|
||||
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) ";
|
||||
fp << "&&";
|
||||
fp << "(" << generate_verilog_port(VERILOG_PORT_CONKT, readback_port) << " == 1'b1) ";
|
||||
fp << ") begin" << std::endl;
|
||||
fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
|
||||
/* Create a string for addr and data */
|
||||
for (size_t i = 0; i < data_size; ++i) {
|
||||
fp << "\t\t\t" << generate_verilog_constant_values(itobin_vec(i, addr_size));
|
||||
fp << " : ";
|
||||
fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(i, data_size));
|
||||
fp << ";" << std::endl;
|
||||
}
|
||||
/* Different from MUX decoder, we assign default values which is all zero */
|
||||
fp << "\t\t\t" << "default";
|
||||
fp << " : ";
|
||||
fp << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size));
|
||||
fp << ";" << std::endl;
|
||||
|
||||
fp << "\t\t" << "endcase" << std::endl;
|
||||
fp << "\t" << "end" << std::endl;
|
||||
|
||||
/* If enable is not active, we should give all zero */
|
||||
fp << "\t" << "else begin" << std::endl;
|
||||
fp << "\t\t" << generate_verilog_port_constant_values(data_ren_port, ito1hot_vec(data_size, data_size));
|
||||
fp << ";" << std::endl;
|
||||
fp << "\t" << "end" << std::endl;
|
||||
|
||||
fp << "end" << std::endl;
|
||||
}
|
||||
|
||||
if (true == decoder_lib.use_data_inv_port(decoder)) {
|
||||
print_verilog_wire_connection(fp, data_inv_port, data_port, true);
|
||||
}
|
||||
|
|
|
@ -128,6 +128,17 @@ void print_verilog_top_testbench_memory_bank_port(std::fstream& fp,
|
|||
BasicPort din_port = module_manager.module_port(top_module, din_port_id);
|
||||
fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl;
|
||||
|
||||
/* Print the optional readback port for the decoder here */
|
||||
print_verilog_comment(fp, std::string("---- Readback port for memory decoders -----"));
|
||||
ModulePortId readback_port_id = module_manager.find_module_port(top_module,
|
||||
std::string(DECODER_READBACK_PORT_NAME));
|
||||
if (readback_port_id) {
|
||||
BasicPort readback_port = module_manager.module_port(top_module, readback_port_id);
|
||||
fp << generate_verilog_port(VERILOG_PORT_WIRE, readback_port) << ";" << std::endl;
|
||||
/* Disable readback in full testbenches */
|
||||
print_verilog_wire_constant_values(fp, readback_port, std::vector<size_t>(readback_port.get_width(), 0));
|
||||
}
|
||||
|
||||
/* Generate enable signal waveform here:
|
||||
* which is a 90 degree phase shift than the programming clock
|
||||
*/
|
||||
|
|
|
@ -47,6 +47,11 @@ bool DecoderLibrary::use_data_inv_port(const DecoderId& decoder) const {
|
|||
return use_data_inv_port_[decoder];
|
||||
}
|
||||
|
||||
bool DecoderLibrary::use_readback(const DecoderId& decoder) const {
|
||||
VTR_ASSERT_SAFE(valid_decoder_id(decoder));
|
||||
return use_readback_[decoder];
|
||||
}
|
||||
|
||||
/* Find a decoder to the library, with the specification.
|
||||
* If found, return the id of decoder.
|
||||
* If not found, return an invalid id of decoder
|
||||
|
@ -61,13 +66,15 @@ DecoderId DecoderLibrary::find_decoder(const size_t& addr_size,
|
|||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port) const {
|
||||
const bool& use_data_inv_port,
|
||||
const bool& use_readback) const {
|
||||
for (auto decoder : decoders()) {
|
||||
if ( (addr_size == addr_sizes_[decoder])
|
||||
&& (data_size == data_sizes_[decoder])
|
||||
&& (use_enable == use_enable_[decoder])
|
||||
&& (use_data_in == use_data_in_[decoder])
|
||||
&& (use_data_inv_port == use_data_inv_port_[decoder]) ) {
|
||||
&& (use_data_inv_port == use_data_inv_port_[decoder])
|
||||
&& (use_readback == use_readback_[decoder]) ) {
|
||||
return decoder;
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +99,8 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size,
|
|||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port) {
|
||||
const bool& use_data_inv_port,
|
||||
const bool& use_readback) {
|
||||
DecoderId decoder = DecoderId(decoder_ids_.size());
|
||||
/* Push to the decoder list */
|
||||
decoder_ids_.push_back(decoder);
|
||||
|
@ -102,6 +110,7 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size,
|
|||
use_enable_.push_back(use_enable);
|
||||
use_data_in_.push_back(use_data_in);
|
||||
use_data_inv_port_.push_back(use_data_inv_port);
|
||||
use_readback_.push_back(use_readback);
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ class DecoderLibrary {
|
|||
bool use_data_in(const DecoderId& decoder) const;
|
||||
/* Get the flag if a decoder includes a data_inv port which is an inversion of the regular data output port */
|
||||
bool use_data_inv_port(const DecoderId& decoder) const;
|
||||
/* Get the flag if a decoder includes a readback port which enables readback from configurable memories */
|
||||
bool use_readback(const DecoderId& decoder) const;
|
||||
/* Find a decoder to the library, with the specification.
|
||||
* If found, return the id of decoder.
|
||||
* If not found, return an invalid id of decoder
|
||||
|
@ -64,7 +66,8 @@ class DecoderLibrary {
|
|||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port) const;
|
||||
const bool& use_data_inv_port,
|
||||
const bool& use_readback) const;
|
||||
|
||||
public: /* Public validators */
|
||||
/* valid ids */
|
||||
|
@ -76,7 +79,8 @@ class DecoderLibrary {
|
|||
const size_t& data_size,
|
||||
const bool& use_enable,
|
||||
const bool& use_data_in,
|
||||
const bool& use_data_inv_port);
|
||||
const bool& use_data_inv_port,
|
||||
const bool& use_readback);
|
||||
|
||||
private: /* Internal Data */
|
||||
vtr::vector<DecoderId, DecoderId> decoder_ids_;
|
||||
|
@ -85,6 +89,7 @@ class DecoderLibrary {
|
|||
vtr::vector<DecoderId, bool> use_enable_;
|
||||
vtr::vector<DecoderId, bool> use_data_in_;
|
||||
vtr::vector<DecoderId, bool> use_data_inv_port_;
|
||||
vtr::vector<DecoderId, bool> use_readback_;
|
||||
};
|
||||
|
||||
} /* End namespace openfpga*/
|
||||
|
|
|
@ -112,11 +112,11 @@ DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib,
|
|||
const size_t data_size) {
|
||||
size_t addr_size = find_mux_local_decoder_addr_size(data_size);
|
||||
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true);
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, false, false, true, false);
|
||||
|
||||
if (DecoderId::INVALID() == decoder_id) {
|
||||
/* Add the decoder */
|
||||
return decoder_lib.add_decoder(addr_size, data_size, false, false, true);
|
||||
return decoder_lib.add_decoder(addr_size, data_size, false, false, true, false);
|
||||
}
|
||||
|
||||
/* There is already a decoder in the library, return the decoder id */
|
||||
|
|
|
@ -330,7 +330,8 @@ std::vector<std::string> generate_sram_port_names(const CircuitLibrary& circuit_
|
|||
std::vector<e_circuit_model_port_type> ports_to_search;
|
||||
ports_to_search.push_back(CIRCUIT_MODEL_PORT_BL);
|
||||
ports_to_search.push_back(CIRCUIT_MODEL_PORT_WL);
|
||||
/* Try to find a BL/WL/BLB/WLB port and update the port types/module port types to be added */
|
||||
ports_to_search.push_back(CIRCUIT_MODEL_PORT_WLR);
|
||||
/* Try to find a BL/WL/WLR port and update the port types/module port types to be added */
|
||||
for (const auto& port_to_search : ports_to_search) {
|
||||
std::vector<CircuitPortId> found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search);
|
||||
if (0 == found_port.size()) {
|
||||
|
|
|
@ -195,6 +195,7 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager,
|
|||
port_type2type_map[CIRCUIT_MODEL_PORT_BLB] = ModuleManager::MODULE_INPUT_PORT;
|
||||
port_type2type_map[CIRCUIT_MODEL_PORT_WL] = ModuleManager::MODULE_INPUT_PORT;
|
||||
port_type2type_map[CIRCUIT_MODEL_PORT_WLB] = ModuleManager::MODULE_INPUT_PORT;
|
||||
port_type2type_map[CIRCUIT_MODEL_PORT_WLR] = ModuleManager::MODULE_INPUT_PORT;
|
||||
port_type2type_map[CIRCUIT_MODEL_PORT_OUTPUT] = ModuleManager::MODULE_OUTPUT_PORT;
|
||||
|
||||
/* Input ports (ignore all the global ports when searching the circuit_lib */
|
||||
|
@ -390,8 +391,9 @@ void add_pb_sram_ports_to_module_manager(ModuleManager& module_manager,
|
|||
for (const std::string& sram_port_name : sram_port_names) {
|
||||
/* Add generated ports to the ModuleManager */
|
||||
BasicPort sram_port(sram_port_name, sram_port_size);
|
||||
/* For WL ports, we need to fine-tune it */
|
||||
if (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) {
|
||||
/* For WL and WLR ports, we need to fine-tune it */
|
||||
if ( (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name)))
|
||||
|| (CIRCUIT_MODEL_PORT_WLR == circuit_lib.port_type(circuit_lib.model_port(sram_model, sram_port_name))) ) {
|
||||
sram_port.set_width(find_memory_wl_decoder_data_size(num_config_bits, sram_port_size));
|
||||
}
|
||||
module_manager.add_port(module_id, sram_port, ModuleManager::MODULE_INPUT_PORT);
|
||||
|
@ -885,7 +887,7 @@ void add_module_nets_between_logic_and_memory_sram_bus(ModuleManager& module_man
|
|||
* | | |
|
||||
* +------------+----------------------+
|
||||
* |
|
||||
* WL
|
||||
* WL/WLR
|
||||
*
|
||||
* Note:
|
||||
* - This function will do the connection for only one type of the port,
|
||||
|
@ -900,15 +902,16 @@ void add_module_nets_cmos_flatten_memory_config_bus(ModuleManager& module_manage
|
|||
/* A counter for the current pin id for the source port of parent module */
|
||||
size_t cur_src_pin_id = 0;
|
||||
|
||||
ModuleId net_src_module_id;
|
||||
size_t net_src_instance_id;
|
||||
ModulePortId net_src_port_id;
|
||||
|
||||
/* Find the port name of parent module */
|
||||
std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type);
|
||||
net_src_module_id = parent_module;
|
||||
net_src_instance_id = 0;
|
||||
net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||
ModuleId net_src_module_id = parent_module;
|
||||
size_t net_src_instance_id = 0;
|
||||
ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||
|
||||
/* We may not be able to find WLR port, return now */
|
||||
if (!net_src_port_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the pin id for source port */
|
||||
BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id);
|
||||
|
@ -1025,7 +1028,7 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage
|
|||
* | | |
|
||||
* +------------+----------------------+
|
||||
* |
|
||||
* WL<0>
|
||||
* WL<0>/WLR<0>
|
||||
*
|
||||
* +--------+ +--------+ +--------+
|
||||
* | Memory | | Memory | ... | Memory |
|
||||
|
@ -1036,7 +1039,7 @@ void add_module_nets_cmos_memory_bank_bl_config_bus(ModuleManager& module_manage
|
|||
* | | |
|
||||
* +------------+----------------------+
|
||||
* |
|
||||
* WL<1>
|
||||
* WL<1>/WLR<1>
|
||||
*
|
||||
*********************************************************************/
|
||||
void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manager,
|
||||
|
@ -1055,6 +1058,11 @@ void add_module_nets_cmos_memory_bank_wl_config_bus(ModuleManager& module_manage
|
|||
ModulePortId net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name);
|
||||
ModulePortId net_bl_port_id = module_manager.find_module_port(net_src_module_id, bl_port_name);
|
||||
|
||||
/* We may not be able to find WLR port, return now */
|
||||
if (!net_src_port_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the pin id for source port */
|
||||
BasicPort net_src_port = module_manager.module_port(net_src_module_id, net_src_port_id);
|
||||
BasicPort net_bl_port = module_manager.module_port(net_src_module_id, net_bl_port_id);
|
||||
|
@ -1300,9 +1308,9 @@ void add_module_nets_cmos_memory_frame_decoder_config_bus(ModuleManager& module_
|
|||
/* Search the decoder library and try to find one
|
||||
* If not found, create a new module and add it to the module manager
|
||||
*/
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false);
|
||||
DecoderId decoder_id = decoder_lib.find_decoder(addr_size, data_size, true, false, false, false);
|
||||
if (DecoderId::INVALID() == decoder_id) {
|
||||
decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false);
|
||||
decoder_id = decoder_lib.add_decoder(addr_size, data_size, true, false, false, false);
|
||||
}
|
||||
VTR_ASSERT(DecoderId::INVALID() != decoder_id);
|
||||
|
||||
|
@ -1519,6 +1527,8 @@ void add_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
|
|||
sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
|
||||
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
|
||||
sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
|
||||
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
|
||||
sram_orgz_type, CIRCUIT_MODEL_PORT_WLR);
|
||||
break;
|
||||
case CONFIG_MEM_FRAME_BASED:
|
||||
add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module);
|
||||
|
@ -1580,6 +1590,8 @@ void add_pb_module_nets_cmos_memory_config_bus(ModuleManager& module_manager,
|
|||
sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
|
||||
add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module,
|
||||
sram_orgz_type, CIRCUIT_MODEL_PORT_WL);
|
||||
add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module,
|
||||
sram_orgz_type, CIRCUIT_MODEL_PORT_WLR);
|
||||
break;
|
||||
case CONFIG_MEM_MEMORY_BANK:
|
||||
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
<!-- Architecture annotation for OpenFPGA framework
|
||||
This annotation supports the k6_N10_40nm.xml
|
||||
- General purpose logic block
|
||||
- K = 6, N = 10, I = 40
|
||||
- Single mode
|
||||
- Routing architecture
|
||||
- L = 4, fc_in = 0.15, fc_out = 0.1
|
||||
-->
|
||||
<openfpga_architecture>
|
||||
<technology_library>
|
||||
<device_library>
|
||||
<device_model name="logic" type="transistor">
|
||||
<lib type="industry" corner="TOP_TT" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
|
||||
<design vdd="0.9" pn_ratio="2"/>
|
||||
<pmos name="pch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
|
||||
<nmos name="nch" chan_length="40e-9" min_width="140e-9" variation="logic_transistor_var"/>
|
||||
</device_model>
|
||||
<device_model name="io" type="transistor">
|
||||
<lib type="academia" ref="M" path="${OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.pm"/>
|
||||
<design vdd="2.5" pn_ratio="3"/>
|
||||
<pmos name="pch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
|
||||
<nmos name="nch_25" chan_length="270e-9" min_width="320e-9" variation="io_transistor_var"/>
|
||||
</device_model>
|
||||
</device_library>
|
||||
<variation_library>
|
||||
<variation name="logic_transistor_var" abs_deviation="0.1" num_sigma="3"/>
|
||||
<variation name="io_transistor_var" abs_deviation="0.1" num_sigma="3"/>
|
||||
</variation_library>
|
||||
</technology_library>
|
||||
<circuit_library>
|
||||
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
|
||||
<design_technology type="cmos" topology="inverter" size="1"/>
|
||||
<device_technology device_model_name="logic"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="false">
|
||||
<design_technology type="cmos" topology="buffer" size="1" num_level="2" f_per_stage="4"/>
|
||||
<device_technology device_model_name="logic"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="inv_buf" name="tap_buf4" prefix="tap_buf4" is_default="false">
|
||||
<design_technology type="cmos" topology="buffer" size="1" num_level="3" f_per_stage="4"/>
|
||||
<device_technology device_model_name="logic"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="pass_gate" name="TGATE" prefix="TGATE" is_default="true">
|
||||
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
|
||||
<device_technology device_model_name="logic"/>
|
||||
<input_buffer exist="false"/>
|
||||
<output_buffer exist="false"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="input" prefix="sel" size="1"/>
|
||||
<port type="input" prefix="selb" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
|
||||
10e-12 5e-12 5e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
|
||||
10e-12 5e-12 5e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="true">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="false"/>
|
||||
<output_buffer exist="false"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<wire_param model_type="pi" R="101" C="22.5e-15" num_level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
|
||||
</circuit_model>
|
||||
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="true">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="false"/>
|
||||
<output_buffer exist="false"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<wire_param model_type="pi" R="0" C="0" num_level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
|
||||
</circuit_model>
|
||||
<circuit_model type="mux" name="mux_2level" prefix="mux_2level" dump_structural_verilog="true">
|
||||
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="mux" name="mux_2level_tapbuf" prefix="mux_2level_tapbuf" dump_structural_verilog="true">
|
||||
<design_technology type="cmos" structure="multi_level" num_level="2" add_const_input="true" const_input_val="1"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
|
||||
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="mux" name="mux_1level_tapbuf" prefix="mux_1level_tapbuf" is_default="true" dump_structural_verilog="true">
|
||||
<design_technology type="cmos" structure="one_level" add_const_input="true" const_input_val="1"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="tap_buf4"/>
|
||||
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="1"/>
|
||||
</circuit_model>
|
||||
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
|
||||
<circuit_model type="ff" name="DFFSRQ" prefix="DFFSRQ" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/dff.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/dff.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<port type="input" prefix="D" lib_name="D" size="1"/>
|
||||
<port type="input" prefix="set" lib_name="SET" size="1" is_global="true" default_val="0" is_set="true"/>
|
||||
<port type="input" prefix="reset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true"/>
|
||||
<port type="output" prefix="Q" lib_name="Q" size="1"/>
|
||||
<port type="clock" prefix="clk" lib_name="CK" size="1" is_global="true" default_val="0" />
|
||||
</circuit_model>
|
||||
<circuit_model type="lut" name="lut4" prefix="lut4" dump_structural_verilog="true">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<lut_input_inverter exist="true" circuit_model_name="INVTX1"/>
|
||||
<lut_input_buffer exist="true" circuit_model_name="buf4"/>
|
||||
<pass_gate_logic circuit_model_name="TGATE"/>
|
||||
<port type="input" prefix="in" size="4"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="16"/>
|
||||
</circuit_model>
|
||||
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
|
||||
<circuit_model type="sram" name="SRAM_RE" prefix="SRAM_RE" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/sram.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/sram.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<port type="bl" prefix="bl" lib_name="D" size="1"/>
|
||||
<port type="wl" prefix="wl" lib_name="WE" size="1"/>
|
||||
<port type="wlr" prefix="wlr" lib_name="RE" size="1"/>
|
||||
<port type="output" prefix="out" lib_name="Q" size="1"/>
|
||||
<port type="output" prefix="outb" lib_name="QN" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="iopad" name="GPIO" prefix="GPIO" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/gpio.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/gpio.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<output_buffer exist="true" circuit_model_name="INVTX1"/>
|
||||
<port type="inout" prefix="PAD" size="1" is_global="true" is_io="true" is_data_io="true"/>
|
||||
<port type="sram" prefix="DIR" size="1" mode_select="true" circuit_model_name="SRAM_RE" default_val="1"/>
|
||||
<port type="input" prefix="outpad" lib_name="A" size="1"/>
|
||||
<port type="output" prefix="inpad" lib_name="Y" size="1"/>
|
||||
</circuit_model>
|
||||
</circuit_library>
|
||||
<configuration_protocol>
|
||||
<organization type="ql_memory_bank" circuit_model_name="SRAM_RE"/>
|
||||
</configuration_protocol>
|
||||
<connection_block>
|
||||
<switch name="ipin_cblock" circuit_model_name="mux_2level_tapbuf"/>
|
||||
</connection_block>
|
||||
<switch_block>
|
||||
<switch name="0" circuit_model_name="mux_2level_tapbuf"/>
|
||||
</switch_block>
|
||||
<routing_segment>
|
||||
<segment name="L4" circuit_model_name="chan_segment"/>
|
||||
</routing_segment>
|
||||
<pb_type_annotations>
|
||||
<!-- physical pb_type binding in complex block IO -->
|
||||
<pb_type name="io" physical_mode_name="physical" idle_mode_name="inpad"/>
|
||||
<pb_type name="io[physical].iopad" circuit_model_name="GPIO" mode_bits="1"/>
|
||||
<pb_type name="io[inpad].inpad" physical_pb_type_name="io[physical].iopad" mode_bits="1"/>
|
||||
<pb_type name="io[outpad].outpad" physical_pb_type_name="io[physical].iopad" mode_bits="0"/>
|
||||
<!-- End physical pb_type binding in complex block IO -->
|
||||
|
||||
<!-- physical pb_type binding in complex block CLB -->
|
||||
<!-- physical mode will be the default mode if not specified -->
|
||||
<pb_type name="clb">
|
||||
<!-- Binding interconnect to circuit models as their physical implementation, if not defined, we use the default model -->
|
||||
<interconnect name="crossbar" circuit_model_name="mux_2level"/>
|
||||
</pb_type>
|
||||
<pb_type name="clb.fle[n1_lut4].ble4.lut4" circuit_model_name="lut4"/>
|
||||
<pb_type name="clb.fle[n1_lut4].ble4.ff" circuit_model_name="DFFSRQ"/>
|
||||
<!-- End physical pb_type binding in complex block IO -->
|
||||
</pb_type_annotations>
|
||||
</openfpga_architecture>
|
|
@ -256,6 +256,41 @@ module SRAMSR(
|
|||
|
||||
endmodule
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Function : A SRAM cell with WL read signal
|
||||
//-----------------------------------------------------
|
||||
module SRAM_RE(
|
||||
input WE, // Word line control signal as write enable
|
||||
input RE, // Word line read signal as read enable
|
||||
inout D, // Bit line control signal
|
||||
output Q, // Data output
|
||||
output QN // Data output
|
||||
);
|
||||
|
||||
//----- local variable need to be registered
|
||||
reg data;
|
||||
reg data_readback;
|
||||
|
||||
//----- when wl is enabled, we can read in data from bl
|
||||
always @(WE or RE or D)
|
||||
begin
|
||||
if ((1'b1 == D)&&(1'b1 == WE)) begin
|
||||
//----- Cases to program internal memory bit
|
||||
//----- case 1: bl = 1, wl = 1, a -> 0
|
||||
data <= 1'b1;
|
||||
end else if ((1'b0 == D)&&(1'b1 == WE)) begin
|
||||
//----- case 2: bl = 0, wl = 1, a -> 0
|
||||
data <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// Wire q_reg to Q
|
||||
assign Q = data;
|
||||
assign QN = ~data;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Function : A SRAM cell with
|
||||
// - an active-low reset
|
||||
|
|
|
@ -55,6 +55,7 @@ run-task basic_tests/preconfig_testbench/memory_bank --debug --show_thread_logs
|
|||
|
||||
echo -e "Testing physical design friendly memory bank configuration protocol of a K4N4 FPGA";
|
||||
run-task basic_tests/full_testbench/ql_memory_bank --debug --show_thread_logs
|
||||
run-task basic_tests/full_testbench/ql_memory_bank_use_wlr --debug --show_thread_logs
|
||||
|
||||
echo -e "Testing testbenches without self checking features";
|
||||
run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
# 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]
|
||||
run_engine=openfpga_shell
|
||||
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=yosys_vpr
|
||||
|
||||
[OpenFPGA_SHELL]
|
||||
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_example_script.openfpga
|
||||
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbank_wlr_openfpga.xml
|
||||
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
|
||||
openfpga_vpr_device_layout=
|
||||
openfpga_fast_configuration=
|
||||
|
||||
[ARCHITECTURES]
|
||||
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
|
||||
|
||||
[BENCHMARKS]
|
||||
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
|
||||
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v
|
||||
bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v
|
||||
|
||||
[SYNTHESIS_PARAM]
|
||||
bench0_top = and2
|
||||
bench0_chan_width = 300
|
||||
|
||||
bench1_top = or2
|
||||
bench1_chan_width = 300
|
||||
|
||||
bench2_top = and2_latch
|
||||
bench2_chan_width = 300
|
||||
|
||||
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
|
||||
end_flow_with_test=
|
Loading…
Reference in New Issue