Merge pull request #10 from RapidSilicon/phy_mem_bank

Support WLR signal in physical friendly memory bank
This commit is contained in:
tangxifan 2021-09-20 21:33:21 -07:00 committed by GitHub
commit 8a3ce62d70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 796 additions and 41 deletions

View File

@ -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:: 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 FPGA I/O Port
^^^^^^^^^^^^^ ^^^^^^^^^^^^^

View File

@ -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. .. 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: .. _circuit_model_config_latch_example:
Configurable Latch Configurable Latch

View File

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

View File

@ -101,10 +101,11 @@ enum e_circuit_model_port_type {
CIRCUIT_MODEL_PORT_BLB, CIRCUIT_MODEL_PORT_BLB,
CIRCUIT_MODEL_PORT_WL, CIRCUIT_MODEL_PORT_WL,
CIRCUIT_MODEL_PORT_WLB, CIRCUIT_MODEL_PORT_WLB,
CIRCUIT_MODEL_PORT_WLR,
NUM_CIRCUIT_MODEL_PORT_TYPES NUM_CIRCUIT_MODEL_PORT_TYPES
}; };
/* Strings correspond to each port type */ /* 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 { enum e_circuit_model_delay_type {
CIRCUIT_MODEL_DELAY_RISE, CIRCUIT_MODEL_DELAY_RISE,

View File

@ -33,6 +33,7 @@ constexpr char* CONNECTION_BLOCK_MEM_INSTANCE_PREFIX = "mem_";
constexpr char* MEMORY_MODULE_POSTFIX = "_mem"; constexpr char* MEMORY_MODULE_POSTFIX = "_mem";
constexpr char* MEMORY_BL_PORT_NAME = "bl"; constexpr char* MEMORY_BL_PORT_NAME = "bl";
constexpr char* MEMORY_WL_PORT_NAME = "wl"; constexpr char* MEMORY_WL_PORT_NAME = "wl";
constexpr char* MEMORY_WLR_PORT_NAME = "wlr";
/* Multiplexer naming constant strings */ /* Multiplexer naming constant strings */
constexpr char* MUX_BASIS_MODULE_POSTFIX = "_basis"; 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_DATA_OUT_INV_PORT_NAME = "data_out_inv";
constexpr char* DECODER_BL_ADDRESS_PORT_NAME = "bl_address"; constexpr char* DECODER_BL_ADDRESS_PORT_NAME = "bl_address";
constexpr char* DECODER_WL_ADDRESS_PORT_NAME = "wl_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 */ /* Inverted port naming */
constexpr char* INV_PORT_POSTFIX = "_inv"; constexpr char* INV_PORT_POSTFIX = "_inv";

View File

@ -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) { if (CIRCUIT_MODEL_PORT_BL == port_type) {
port_name = std::string(MEMORY_BL_PORT_NAME); port_name = std::string(MEMORY_BL_PORT_NAME);
} else { } else if (CIRCUIT_MODEL_PORT_WL == port_type) {
VTR_ASSERT( CIRCUIT_MODEL_PORT_WL == port_type );
port_name = std::string(MEMORY_WL_PORT_NAME); 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; break;
case CONFIG_MEM_FRAME_BASED: case CONFIG_MEM_FRAME_BASED:

View File

@ -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); 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; return module_id;
} }

View File

@ -366,12 +366,15 @@ void build_memory_flatten_module(ModuleManager& module_manager,
/* Get the BL/WL ports from the SRAM */ /* 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_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); 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 */ /* 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); 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_bl_ports.size());
VTR_ASSERT(1 == sram_wl_ports.size()); VTR_ASSERT(1 == sram_wl_ports.size());
VTR_ASSERT(2 > sram_wlr_ports.size());
VTR_ASSERT(2 == sram_output_ports.size()); VTR_ASSERT(2 == sram_output_ports.size());
/* Create a module and add to the module manager */ /* 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); 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); 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 */ /* Add each output port: port width should match the number of memories */
for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) { for (size_t iport = 0; iport < sram_output_ports.size(); ++iport) {
std::string port_name; std::string port_name;
@ -419,6 +428,9 @@ void build_memory_flatten_module(ModuleManager& module_manager,
for (const CircuitPortId& port : sram_wl_ports) { 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); 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 */ /* 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); 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. * If we find one, we use the module.
* Otherwise, we create one and add it to the decoder library * 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) { 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); VTR_ASSERT(DecoderId::INVALID() != decoder_id);

View File

@ -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); 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); 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*/ /* 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()); 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); 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 * Otherwise, we create one and add it to the decoder library
*/ */
DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, 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) { 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); 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 * Otherwise, we create one and add it to the decoder library
*/ */
DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, 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) { 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); 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 /* Search the decoder library and try to find one
* If not found, create a new module and add it to the module manager * 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) { 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); VTR_ASSERT(DecoderId::INVALID() != decoder_id);

View File

@ -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 */ /* Data in port should match the number of configuration regions */
VTR_ASSERT(din_port_info.get_width() == module_manager.regions(top_module).size()); 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 */ /* 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)); 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); 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 * Otherwise, we create one and add it to the decoder library
*/ */
DecoderId bl_decoder_id = decoder_lib.find_decoder(bl_addr_size, num_bls, 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) { 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); 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 * Otherwise, we create one and add it to the decoder library
*/ */
DecoderId wl_decoder_id = decoder_lib.find_decoder(wl_addr_size, num_wls, 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) { 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); 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); 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)); 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 */ /* Top module Enable port -> WL Decoder Enable port */
add_module_bus_nets(module_manager, 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, top_module, 0, wl_addr_port,
wl_decoder_module, curr_wl_decoder_instance_id, wl_decoder_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 * 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 * 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 * 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 * Note: this MUST be done after adding all the module nets to other regular configurable children

View File

@ -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); 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 */ /* dump module definition + ports */
print_verilog_module_declaration(fp, module_manager, module_id, default_net_type); print_verilog_module_declaration(fp, module_manager, module_id, default_net_type);
/* Finish dumping ports */ /* Finish dumping ports */
@ -303,10 +317,18 @@ void print_verilog_arch_decoder_module(std::fstream& fp,
* else data_out is driven by '0' * else data_out is driven by '0'
*/ */
if (1 == data_size) { if (1 == data_size) {
/* Output logics for data output */
fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port); fp << "always@(" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port);
fp << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_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 << ") begin" << std::endl;
fp << "\tif ((" << generate_verilog_port(VERILOG_PORT_CONKT, enable_port) << " == 1'b1) && ("; 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 << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << " == 1'b0))";
fp << " begin" << std::endl; fp << " begin" << std::endl;
fp << "\t\t" << generate_verilog_port_constant_values(data_port, std::vector<size_t>(1, 1)) << ";" << 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 << "\t" << "end" << std::endl;
fp << "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 */ /* Depend on if the inverted data output port is needed or not */
if (true == decoder_lib.use_data_inv_port(decoder)) { if (true == decoder_lib.use_data_inv_port(decoder)) {
print_verilog_wire_connection(fp, data_inv_port, addr_port, true); 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; * 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); 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 << " or " << generate_verilog_port(VERILOG_PORT_CONKT, enable_port);
fp << ") begin" << std::endl; 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; fp << "\t\t" << "case (" << generate_verilog_port(VERILOG_PORT_CONKT, addr_port) << ")" << std::endl;
/* Create a string for addr and data */ /* Create a string for addr and data */
for (size_t i = 0; i < data_size; ++i) { 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; 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)) { if (true == decoder_lib.use_data_inv_port(decoder)) {
print_verilog_wire_connection(fp, data_inv_port, data_port, true); print_verilog_wire_connection(fp, data_inv_port, data_port, true);
} }

View File

@ -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); BasicPort din_port = module_manager.module_port(top_module, din_port_id);
fp << generate_verilog_port(VERILOG_PORT_REG, din_port) << ";" << std::endl; 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: /* Generate enable signal waveform here:
* which is a 90 degree phase shift than the programming clock * which is a 90 degree phase shift than the programming clock
*/ */

View File

@ -47,6 +47,11 @@ bool DecoderLibrary::use_data_inv_port(const DecoderId& decoder) const {
return use_data_inv_port_[decoder]; 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. /* Find a decoder to the library, with the specification.
* If found, return the id of decoder. * If found, return the id of decoder.
* If not found, return an invalid 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 size_t& data_size,
const bool& use_enable, const bool& use_enable,
const bool& use_data_in, 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()) { for (auto decoder : decoders()) {
if ( (addr_size == addr_sizes_[decoder]) if ( (addr_size == addr_sizes_[decoder])
&& (data_size == data_sizes_[decoder]) && (data_size == data_sizes_[decoder])
&& (use_enable == use_enable_[decoder]) && (use_enable == use_enable_[decoder])
&& (use_data_in == use_data_in_[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; return decoder;
} }
} }
@ -92,7 +99,8 @@ DecoderId DecoderLibrary::add_decoder(const size_t& addr_size,
const size_t& data_size, const size_t& data_size,
const bool& use_enable, const bool& use_enable,
const bool& use_data_in, 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()); DecoderId decoder = DecoderId(decoder_ids_.size());
/* Push to the decoder list */ /* Push to the decoder list */
decoder_ids_.push_back(decoder); 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_enable_.push_back(use_enable);
use_data_in_.push_back(use_data_in); use_data_in_.push_back(use_data_in);
use_data_inv_port_.push_back(use_data_inv_port); use_data_inv_port_.push_back(use_data_inv_port);
use_readback_.push_back(use_readback);
return decoder; return decoder;
} }

View File

@ -50,6 +50,8 @@ class DecoderLibrary {
bool use_data_in(const DecoderId& decoder) const; 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 */ /* 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; 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. /* Find a decoder to the library, with the specification.
* If found, return the id of decoder. * If found, return the id of decoder.
* If not found, return an invalid id of decoder * If not found, return an invalid id of decoder
@ -64,7 +66,8 @@ class DecoderLibrary {
const size_t& data_size, const size_t& data_size,
const bool& use_enable, const bool& use_enable,
const bool& use_data_in, 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 */ public: /* Public validators */
/* valid ids */ /* valid ids */
@ -76,7 +79,8 @@ class DecoderLibrary {
const size_t& data_size, const size_t& data_size,
const bool& use_enable, const bool& use_enable,
const bool& use_data_in, const bool& use_data_in,
const bool& use_data_inv_port); const bool& use_data_inv_port,
const bool& use_readback);
private: /* Internal Data */ private: /* Internal Data */
vtr::vector<DecoderId, DecoderId> decoder_ids_; vtr::vector<DecoderId, DecoderId> decoder_ids_;
@ -85,6 +89,7 @@ class DecoderLibrary {
vtr::vector<DecoderId, bool> use_enable_; vtr::vector<DecoderId, bool> use_enable_;
vtr::vector<DecoderId, bool> use_data_in_; vtr::vector<DecoderId, bool> use_data_in_;
vtr::vector<DecoderId, bool> use_data_inv_port_; vtr::vector<DecoderId, bool> use_data_inv_port_;
vtr::vector<DecoderId, bool> use_readback_;
}; };
} /* End namespace openfpga*/ } /* End namespace openfpga*/

View File

@ -112,11 +112,11 @@ DecoderId add_mux_local_decoder_to_library(DecoderLibrary& decoder_lib,
const size_t data_size) { const size_t data_size) {
size_t addr_size = find_mux_local_decoder_addr_size(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) { if (DecoderId::INVALID() == decoder_id) {
/* Add the decoder */ /* 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 */ /* There is already a decoder in the library, return the decoder id */

View File

@ -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; 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_BL);
ports_to_search.push_back(CIRCUIT_MODEL_PORT_WL); 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) { 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); std::vector<CircuitPortId> found_port = circuit_lib.model_ports_by_type(sram_model, port_to_search);
if (0 == found_port.size()) { if (0 == found_port.size()) {

View File

@ -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_BLB] = ModuleManager::MODULE_INPUT_PORT;
port_type2type_map[CIRCUIT_MODEL_PORT_WL] = 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_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; port_type2type_map[CIRCUIT_MODEL_PORT_OUTPUT] = ModuleManager::MODULE_OUTPUT_PORT;
/* Input ports (ignore all the global ports when searching the circuit_lib */ /* 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) { for (const std::string& sram_port_name : sram_port_names) {
/* Add generated ports to the ModuleManager */ /* Add generated ports to the ModuleManager */
BasicPort sram_port(sram_port_name, sram_port_size); BasicPort sram_port(sram_port_name, sram_port_size);
/* For WL ports, we need to fine-tune it */ /* 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))) { 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)); 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); 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: * Note:
* - This function will do the connection for only one type of the port, * - 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 */ /* A counter for the current pin id for the source port of parent module */
size_t cur_src_pin_id = 0; 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 */ /* Find the port name of parent module */
std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type); std::string src_port_name = generate_sram_port_name(sram_orgz_type, config_port_type);
net_src_module_id = parent_module; ModuleId net_src_module_id = parent_module;
net_src_instance_id = 0; size_t net_src_instance_id = 0;
net_src_port_id = module_manager.find_module_port(net_src_module_id, src_port_name); 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 */ /* 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_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 | * | 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, 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_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); 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 */ /* 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_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); 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 /* Search the decoder library and try to find one
* If not found, create a new module and add it to the module manager * 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) { 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); 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); sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,
sram_orgz_type, CIRCUIT_MODEL_PORT_WL); 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; break;
case CONFIG_MEM_FRAME_BASED: case CONFIG_MEM_FRAME_BASED:
add_module_nets_cmos_memory_frame_config_bus(module_manager, decoder_lib, parent_module); 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); sram_orgz_type, CIRCUIT_MODEL_PORT_BL);
add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module, add_module_nets_cmos_memory_bank_wl_config_bus(module_manager, parent_module,
sram_orgz_type, CIRCUIT_MODEL_PORT_WL); 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; break;
case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK:
add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module, add_module_nets_cmos_flatten_memory_config_bus(module_manager, parent_module,

View File

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

View File

@ -256,6 +256,41 @@ module SRAMSR(
endmodule 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 // Function : A SRAM cell with
// - an active-low reset // - an active-low reset

View File

@ -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"; 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 --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"; echo -e "Testing testbenches without self checking features";
run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs run-task basic_tests/full_testbench/full_testbench_without_self_checking --debug --show_thread_logs

View File

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