Merge pull request #1841 from lnis-uofu/xt_mux

Support last stage pass-gate-logic model for MUX circuit model
This commit is contained in:
tangxifan 2024-09-19 11:42:50 -07:00 committed by GitHub
commit 0c43e99d39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 617 additions and 15 deletions

View File

@ -53,6 +53,7 @@ Here, we focus these common syntax and we will detail special syntax in :ref:`ci
<input_buffer exist="<string>" circuit_model_name="<string>"/>
<output_buffer exist="<string>" circuit_model_name="<string>"/>
<pass_gate_logic type="<string>" circuit_model_name="<string>"/>
<last_stage_pass_gate_logic type="<string>" circuit_model_name="<string>"/>
<port type="<string>" prefix="<string>" lib_name="<string>" size="<int>" default_val="<int>" circuit_model_name="<string>" mode_select="<bool>" is_global="<bool>" is_set="<bool>" is_reset="<bool>" is_config_enable="<bool>"/>
<!-- more ports -->
</circuit_model>
@ -129,12 +130,16 @@ Input and Output Buffers
Pass Gate Logic
^^^^^^^^^^^^^^^
.. note:: pass-gate logic are used in building multiplexers and LUTs.
.. option:: <pass_gate_logic circuit_model_name="<string>"/>
- ``circuit_model_name="<string>"`` Specify the name of the circuit model which is used to implement pass-gate logic, the type of specified circuit model should be ``pass_gate``.
.. note:: pass-gate logic are used in building multiplexers and LUTs.
.. option:: <last_stage_pass_gate_logic circuit_model_name="<string>"/>
- ``circuit_model_name="<string>"`` Specify the name of the circuit model which is used to implement the pass-gate logic at last stage of multiplexer, the type of specified circuit model should be ``pass_gate``. The type of the pass-gate logic circuit model must be a standard cell MUX2!
.. _circuit_library_circuit_port:

View File

@ -619,6 +619,14 @@ This example shows:
Standard Cell Multiplexer
`````````````````````````
.. _fig_stdcellmux:
.. figure:: ./figures/stdcellmux.png
:width: 100%
:alt: Examples of MUX built with standard cells
An example of a multiplexer built with standard cells: (a) all the MUX2 are the same; (b) the MUX2 at the last stage is a different one
.. code-block:: xml
<circuit_model type="mux" name="mux_stdcell" prefix="mux_stdcell">
@ -631,12 +639,34 @@ Standard Cell Multiplexer
<port type="sram" prefix="sram" size="3"/>
</circuit_model>
This example shows:
This example shows (see an illustative example in :numref:`fig_stdcellmux` (a)):
- A tree-like 4-input CMOS multiplexer built by the standard cell ``MUX2``
- All the inputs will be buffered using the circuit model ``inv1x``
- All the outputs will be buffered using the circuit model ``tapbuf4``
- The multiplexer will have 4 inputs and 3 SRAMs to control which datapath to propagate
Alternatively, user can specify a different standard cell MUX2 at the last stage.
.. code-block:: xml
<circuit_model type="mux" name="mux_stdcell" prefix="mux_stdcell">
<design_technology type="cmos" structure="tree"/>
<input_buffer exist="on" circuit_model_name="inv1x"/>
<output_buffer exist="on" circuit_model_name="tapdrive4"/>
<pass_gate_logic circuit_model_name="MUX2"/>
<last_stage_pass_gate_logic circuit_model_name="MUX2D2"/>
<port type="input" prefix="in" size="4"/>
<port type="output" prefix="out" size="1"/>
<port type="sram" prefix="sram" size="3"/>
</circuit_model>
This example shows (see an illustative example in :numref:`fig_stdcellmux` (b)):
- A tree-like 4-input CMOS multiplexer built by the standard cell ``MUX2``
- The last stage A tree-like 4-input CMOS multiplexer built by the standard cell ``MUX2``
- All the inputs will be buffered using the circuit model ``inv1x``
- All the outputs will be buffered using the circuit model ``tapbuf4``
- The multiplexer will have 4 inputs and 3 SRAMs to control which datapath to propagate
.. _circuit_model_mux_multilevel_example:
Multi-level Multiplexer

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -800,6 +800,60 @@ static size_t check_io_circuit_model(const CircuitLibrary& circuit_lib) {
return num_err;
}
/************************************************************************
* Check the last stage pass gate logic model is the same type as default
***********************************************************************/
static size_t check_pass_gate_circuit_model_consistency(
const CircuitLibrary& circuit_lib) {
size_t num_err = 0;
for (const CircuitModelId& mux_model :
circuit_lib.models_by_type(CIRCUIT_MODEL_MUX)) {
CircuitModelId pgl_model = circuit_lib.pass_gate_logic_model(mux_model);
CircuitModelId last_stage_pgl_model =
circuit_lib.last_stage_pass_gate_logic_model(mux_model);
if (!circuit_lib.valid_model_id(pgl_model)) {
VTR_LOGF_ERROR(
__FILE__, __LINE__,
"The pass-gate logic circuit model '%s' of '%s' is not valid!\n",
circuit_lib.pass_gate_logic_model_name(mux_model).c_str(),
circuit_lib.model_name(mux_model).c_str());
num_err++;
}
if (!circuit_lib.valid_model_id(last_stage_pgl_model)) {
VTR_LOGF_ERROR(
__FILE__, __LINE__,
"The last stage pass-gate logic circuit model '%s' of '%s' is not "
"valid!\n",
circuit_lib.last_stage_pass_gate_logic_model_name(mux_model).c_str(),
circuit_lib.model_name(mux_model).c_str());
num_err++;
}
if (circuit_lib.model_type(pgl_model) !=
circuit_lib.model_type(last_stage_pgl_model)) {
VTR_LOGF_ERROR(
__FILE__, __LINE__,
"The last stage pass-gate logic circuit model '%s' of '%s' should be "
"the same type as its regular pass-gate logic model '%s'!\n",
circuit_lib.model_name(last_stage_pgl_model).c_str(),
circuit_lib.model_name(mux_model).c_str(),
circuit_lib.model_name(pgl_model).c_str());
num_err++;
}
if (pgl_model != last_stage_pgl_model &&
circuit_lib.gate_type(pgl_model) != CIRCUIT_MODEL_GATE_MUX2) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"The last stage pass-gate logic circuit model '%s' of "
"'%s' should be a MUX2 gate!\n",
circuit_lib.model_name(last_stage_pgl_model).c_str(),
circuit_lib.model_name(mux_model).c_str());
num_err++;
}
}
return num_err;
}
/************************************************************************
* Check points to make sure we have a valid circuit library
* Detailed checkpoints:
@ -920,6 +974,9 @@ bool check_circuit_library(const CircuitLibrary& circuit_lib) {
/* 11. Check power-gated inverter/buffer models */
num_err += check_power_gated_circuit_models(circuit_lib);
/* 12. Check pass-gate logic model consistency */
num_err += check_pass_gate_circuit_model_consistency(circuit_lib);
/* If we have any errors, exit */
if (0 < num_err) {

View File

@ -259,6 +259,28 @@ CircuitModelId CircuitLibrary::pass_gate_logic_model(
return pgl_model_id;
}
/* Find the id of pass-gate circuit model
* Two cases to be considered:
* 1. this is a pass-gate circuit model, just find the data and return
* 2. this circuit model includes a pass-gate, find the link to pass-gate
* circuit model and go recursively
*/
CircuitModelId CircuitLibrary::last_stage_pass_gate_logic_model(
const CircuitModelId& model_id) const {
/* validate the model_id */
VTR_ASSERT(valid_model_id(model_id));
/* Return the data if this is a pass-gate circuit model */
if (CIRCUIT_MODEL_PASSGATE == model_type(model_id)) {
return model_ids_[model_id];
}
/* Otherwise, we need to make sure this circuit model contains a pass-gate */
CircuitModelId pgl_model_id = last_stage_pass_gate_logic_model_ids_[model_id];
VTR_ASSERT(CircuitModelId::INVALID() != pgl_model_id);
return pgl_model_id;
}
/* Find the name of pass-gate circuit model
* Two cases to be considered:
* 1. this is a pass-gate circuit model, just find the data and return
@ -279,6 +301,26 @@ std::string CircuitLibrary::pass_gate_logic_model_name(
return pass_gate_logic_model_names_[model_id];
}
/* Find the name of pass-gate circuit model
* Two cases to be considered:
* 1. this is a pass-gate circuit model, just find the data and return
* 2. this circuit model includes a pass-gate, find the link to pass-gate
* circuit model and go recursively
*/
std::string CircuitLibrary::last_stage_pass_gate_logic_model_name(
const CircuitModelId& model_id) const {
/* validate the model_id */
VTR_ASSERT(valid_model_id(model_id));
/* Return the data if this is a pass-gate circuit model */
if (CIRCUIT_MODEL_PASSGATE == model_type(model_id)) {
return model_names_[model_id];
}
/* Otherwise, we need to make sure this circuit model contains a pass-gate */
return last_stage_pass_gate_logic_model_names_[model_id];
}
/* Return the type of pass gate logic module, only applicable to circuit model
* whose type is pass-gate logic */
enum e_circuit_model_pass_gate_logic_type CircuitLibrary::pass_gate_logic_type(
@ -1262,6 +1304,8 @@ CircuitModelId CircuitLibrary::add_model(
/* Pass-gate-related parameters */
pass_gate_logic_model_names_.emplace_back();
pass_gate_logic_model_ids_.emplace_back(CircuitModelId::INVALID());
last_stage_pass_gate_logic_model_names_.emplace_back();
last_stage_pass_gate_logic_model_ids_.emplace_back(CircuitModelId::INVALID());
/* Delay information */
delay_types_.emplace_back();
@ -1485,6 +1529,15 @@ void CircuitLibrary::set_model_pass_gate_logic(const CircuitModelId& model_id,
return;
}
/* Set pass-gate logic information of a circuit model */
void CircuitLibrary::set_model_last_stage_pass_gate_logic(
const CircuitModelId& model_id, const std::string& model_name) {
/* validate the model_id */
VTR_ASSERT(valid_model_id(model_id));
last_stage_pass_gate_logic_model_names_[model_id] = model_name;
return;
}
/* Add a port to a circuit model */
CircuitPortId CircuitLibrary::add_model_port(
const CircuitModelId& model_id,
@ -2174,6 +2227,12 @@ void CircuitLibrary::link_pass_gate_logic_model(
}
pass_gate_logic_model_ids_[model_id] =
model(pass_gate_logic_model_names_[model_id]);
/* Get the circuit model id by name, skip those with empty names*/
if (true == last_stage_pass_gate_logic_model_names_[model_id].empty()) {
return;
}
last_stage_pass_gate_logic_model_ids_[model_id] =
model(last_stage_pass_gate_logic_model_names_[model_id]);
return;
}

View File

@ -272,7 +272,11 @@ class CircuitLibrary {
const CircuitModelId& model_id) const;
/* Pass-gate-logic information */
CircuitModelId pass_gate_logic_model(const CircuitModelId& model_id) const;
CircuitModelId last_stage_pass_gate_logic_model(
const CircuitModelId& model_id) const;
std::string pass_gate_logic_model_name(const CircuitModelId& model_id) const;
std::string last_stage_pass_gate_logic_model_name(
const CircuitModelId& model_id) const;
enum e_circuit_model_pass_gate_logic_type pass_gate_logic_type(
const CircuitModelId& model_id) const;
float pass_gate_logic_pmos_size(const CircuitModelId& model_id) const;
@ -448,6 +452,8 @@ class CircuitLibrary {
/* Pass-gate-related parameters */
void set_model_pass_gate_logic(const CircuitModelId& model_id,
const std::string& model_name);
void set_model_last_stage_pass_gate_logic(const CircuitModelId& model_id,
const std::string& model_name);
/* Port information */
CircuitPortId add_model_port(const CircuitModelId& model_id,
const enum e_circuit_model_port_type& port_type);
@ -664,6 +670,10 @@ class CircuitLibrary {
/* Pass-gate-related parameters */
vtr::vector<CircuitModelId, std::string> pass_gate_logic_model_names_;
vtr::vector<CircuitModelId, CircuitModelId> pass_gate_logic_model_ids_;
vtr::vector<CircuitModelId, std::string>
last_stage_pass_gate_logic_model_names_;
vtr::vector<CircuitModelId, CircuitModelId>
last_stage_pass_gate_logic_model_ids_;
/* Port information */
vtr::vector<CircuitPortId, CircuitPortId> port_ids_;

View File

@ -832,6 +832,25 @@ static void read_xml_circuit_model(pugi::xml_node& xml_model,
circuit_lib.set_model_pass_gate_logic(
model, get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data)
.as_string());
/* Last stage pass gate is optional */
size_t num_last_stage_pgl =
count_children(xml_model, "last_stage_pass_gate_logic", loc_data,
pugiutil::ReqOpt::OPTIONAL);
if (0 < num_last_stage_pgl) {
auto xml_last_stage_pass_gate_logic =
get_single_child(xml_model, "last_stage_pass_gate_logic", loc_data);
circuit_lib.set_model_last_stage_pass_gate_logic(
model, get_attribute(xml_last_stage_pass_gate_logic,
"circuit_model_name", loc_data)
.as_string());
} else {
/* By default, assume the last stage circuit model is the same as others
*/
circuit_lib.set_model_last_stage_pass_gate_logic(
model,
get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data)
.as_string());
}
}
/* Parse all the ports belonging to this circuit model

View File

@ -593,6 +593,15 @@ static void write_xml_circuit_model(std::fstream& fp, const char* fname,
circuit_lib.model_name(circuit_lib.pass_gate_logic_model(model)).c_str());
fp << "/>"
<< "\n";
fp << "\t\t\t"
<< "<last_stage_pass_gate_logic";
write_xml_attribute(
fp, "circuit_model_name",
circuit_lib
.model_name(circuit_lib.last_stage_pass_gate_logic_model(model))
.c_str());
fp << "/>"
<< "\n";
}
/* Write the ports of circuit model */

View File

@ -496,6 +496,71 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
module_manager.module_port(std_cell_module_id, std_cell_module_output);
VTR_ASSERT(1 == std_cell_module_output_port.get_width());
/* Find module information of the standard cell MUX2 */
CircuitModelId last_stage_std_cell_model =
circuit_lib.last_stage_pass_gate_logic_model(mux_model);
std::string last_stage_std_cell_module_name =
circuit_lib.model_name(last_stage_std_cell_model);
/* Get the moduleId for the submodule */
ModuleId last_stage_std_cell_module_id =
module_manager.find_module(last_stage_std_cell_module_name);
/* We must have one */
VTR_ASSERT(ModuleId::INVALID() != last_stage_std_cell_module_id);
/* Find the input ports and output ports of the standard cell */
std::vector<CircuitPortId> last_stage_std_cell_input_ports =
circuit_lib.model_ports_by_type(last_stage_std_cell_model,
CIRCUIT_MODEL_PORT_INPUT, true);
std::vector<CircuitPortId> last_stage_std_cell_output_ports =
circuit_lib.model_ports_by_type(last_stage_std_cell_model,
CIRCUIT_MODEL_PORT_OUTPUT, true);
/* Quick check the requirements on port map */
VTR_ASSERT(3 == last_stage_std_cell_input_ports.size());
VTR_ASSERT(1 == last_stage_std_cell_output_ports.size());
/* Find the module ports of the standard cell MUX2 module */
std::vector<ModulePortId> last_stage_std_cell_module_inputs;
std::vector<BasicPort> last_stage_std_cell_module_input_ports;
/* Input 0 port is the first data path input of the tgate, whose size must be
* 1 ! */
for (size_t port_id = 0; port_id < 2; ++port_id) {
last_stage_std_cell_module_inputs.push_back(module_manager.find_module_port(
last_stage_std_cell_module_id,
circuit_lib.port_prefix(last_stage_std_cell_input_ports[port_id])));
VTR_ASSERT(true == module_manager.valid_module_port_id(
last_stage_std_cell_module_id,
last_stage_std_cell_module_inputs[port_id]));
last_stage_std_cell_module_input_ports.push_back(
module_manager.module_port(last_stage_std_cell_module_id,
last_stage_std_cell_module_inputs[port_id]));
VTR_ASSERT(1 ==
last_stage_std_cell_module_input_ports[port_id].get_width());
}
/* Mem port is the memory of the standard cell MUX2, whose size must be 1 ! */
ModulePortId last_stage_std_cell_module_mem = module_manager.find_module_port(
last_stage_std_cell_module_id,
circuit_lib.port_prefix(last_stage_std_cell_input_ports[2]));
VTR_ASSERT(true ==
module_manager.valid_module_port_id(
last_stage_std_cell_module_id, last_stage_std_cell_module_mem));
BasicPort last_stage_std_cell_module_mem_port = module_manager.module_port(
last_stage_std_cell_module_id, last_stage_std_cell_module_mem);
VTR_ASSERT(1 == last_stage_std_cell_module_mem_port.get_width());
/* Output port is the data path output of the standard cell MUX2, whose size
* must be 1 ! */
ModulePortId last_stage_std_cell_module_output =
module_manager.find_module_port(
last_stage_std_cell_module_id,
circuit_lib.port_prefix(last_stage_std_cell_output_ports[0]));
VTR_ASSERT(true == module_manager.valid_module_port_id(
last_stage_std_cell_module_id,
last_stage_std_cell_module_output));
BasicPort last_stage_std_cell_module_output_port = module_manager.module_port(
last_stage_std_cell_module_id, last_stage_std_cell_module_output);
VTR_ASSERT(1 == last_stage_std_cell_module_output_port.get_width());
/* Cache Net ids for each level of the multiplexer */
std::vector<std::vector<ModuleNetId>> module_nets_by_level;
module_nets_by_level.resize(mux_graph.num_node_levels());
@ -518,11 +583,16 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* To match the standard cell MUX2: We should have only 2 input_nodes */
VTR_ASSERT(2 == branch_size);
/* Last stage MUX model may have a different name */
ModuleId curr_stage_std_cell_module_id = std_cell_module_id;
if (true == mux_graph.is_node_output(node)) {
curr_stage_std_cell_module_id = last_stage_std_cell_module_id;
}
/* Find the instance id */
size_t std_cell_instance_id =
module_manager.num_instance(mux_module, std_cell_module_id);
module_manager.num_instance(mux_module, curr_stage_std_cell_module_id);
/* Add the module to mux_module */
module_manager.add_child_module(mux_module, std_cell_module_id);
module_manager.add_child_module(mux_module, curr_stage_std_cell_module_id);
/* Get the node level and index in the current level */
size_t output_node_level = mux_graph.node_level(node);
@ -530,9 +600,9 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* Set a name for the instance */
std::string std_cell_instance_name = generate_mux_branch_instance_name(
output_node_level, output_node_index_at_level, false);
module_manager.set_child_instance_name(mux_module, std_cell_module_id,
std_cell_instance_id,
std_cell_instance_name);
module_manager.set_child_instance_name(
mux_module, curr_stage_std_cell_module_id, std_cell_instance_id,
std_cell_instance_name);
/* Add module nets to wire to next stage modules */
ModuleNetId branch_net;
@ -540,13 +610,18 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
/* This is an output node, we should use existing output nets */
MuxOutputId output_id = mux_graph.output_id(node);
branch_net = mux_module_output_nets[output_id];
module_manager.add_module_net_source(
mux_module, branch_net, curr_stage_std_cell_module_id,
std_cell_instance_id, last_stage_std_cell_module_output,
last_stage_std_cell_module_output_port.get_lsb());
} else {
VTR_ASSERT(false == mux_graph.is_node_output(node));
branch_net = module_manager.create_module_net(mux_module);
module_manager.add_module_net_source(
mux_module, branch_net, curr_stage_std_cell_module_id,
std_cell_instance_id, std_cell_module_output,
std_cell_module_output_port.get_lsb());
}
module_manager.add_module_net_source(
mux_module, branch_net, std_cell_module_id, std_cell_instance_id,
std_cell_module_output, std_cell_module_output_port.get_lsb());
/* Record the module net id in the cache */
module_nets_by_level[output_node_level][output_node_index_at_level] =
@ -567,10 +642,17 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
* Note that standard cell MUX2 only needs mem but NOT mem_inv
*/
for (const MuxMemId& mem : mems) {
module_manager.add_module_net_sink(
mux_module, mux_module_mem_nets[mem], std_cell_module_id,
std_cell_instance_id, std_cell_module_mem,
std_cell_module_mem_port.get_lsb());
if (true == mux_graph.is_node_output(node)) {
module_manager.add_module_net_sink(
mux_module, mux_module_mem_nets[mem], last_stage_std_cell_module_id,
std_cell_instance_id, last_stage_std_cell_module_mem,
last_stage_std_cell_module_mem_port.get_lsb());
} else {
module_manager.add_module_net_sink(
mux_module, mux_module_mem_nets[mem], std_cell_module_id,
std_cell_instance_id, std_cell_module_mem,
std_cell_module_mem_port.get_lsb());
}
}
/* Wire the branch module inputs to the nets in previous stage */
@ -602,8 +684,15 @@ static void build_cmos_mux_module_mux2_multiplexing_structure(
mux_module, mux_module_input_nets[input_id], std_cell_module_id,
std_cell_instance_id, std_cell_module_inputs[node_id],
std_cell_module_input_ports[node_id].get_lsb());
} else if (true == mux_graph.is_node_output(node)) {
/* Find the input port of standard cell */
module_manager.add_module_net_sink(
mux_module,
module_nets_by_level[input_node_level][input_node_index_at_level],
last_stage_std_cell_module_id, std_cell_instance_id,
last_stage_std_cell_module_inputs[node_id],
last_stage_std_cell_module_input_ports[node_id].get_lsb());
} else {
VTR_ASSERT(false == mux_graph.is_node_input(input_nodes[node_id]));
/* Find the input port of standard cell */
module_manager.add_module_net_sink(
mux_module,

View File

@ -29,6 +29,7 @@ Note that an OpenFPGA architecture can be applied to multiple VPR architecture f
- registerable\_io: If I/Os are registerable (can be either combinational or sequential)
- IoSubtile: If I/O block contains sub tiles (more compact with a higher density of I/Os)
- stdcell: If circuit designs are built with standard cells only
- stdcell_laststage: If circuit designs are built with standard cells only. And the last stage uses a different standard cell
- tree\_mux: If routing multiplexers are built with a tree-like structure
- localClkGen: The clock signal of CLB can be generated by internal programmable resources
- <feature_size>: The technology node which the delay numbers are extracted from.

View File

@ -0,0 +1,236 @@
<?xml version="1.0"?>
<!-- Architecture annotation for OpenFPGA framework
This annotation supports the k6_N10_40nm.xml
- General purpose logic block
- K = 6, N = 8, 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="gate" name="OR2" prefix="OR2" is_default="true">
<design_technology type="cmos" topology="OR"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="a" size="1"/>
<port type="input" prefix="b" size="1"/>
<port type="output" prefix="out" size="1"/>
<delay_matrix type="rise" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
<delay_matrix type="fall" in_port="a b" out_port="out">
10e-12 5e-12
</delay_matrix>
</circuit_model>
<!-- Define a circuit model for the standard cell MUX2
OpenFPGA requires the following truth table for the MUX2
When the select signal sel is enabled, the first input, i.e., in0
will be propagated to the output, i.e., out
If your standard cell provider does not offer the exact truth table,
you can simply swap the inputs as shown in the example below
-->
<circuit_model type="gate" name="MUX2" prefix="MUX2" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/mux2.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/mux2.v">
<design_technology type="cmos" topology="MUX2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in0" lib_name="B" size="1"/>
<port type="input" prefix="in1" lib_name="A" size="1"/>
<port type="input" prefix="sel" lib_name="S0" size="1"/>
<port type="output" prefix="out" lib_name="Y" size="1"/>
</circuit_model>
<circuit_model type="gate" name="MUX2D2" prefix="MUX2D2" spice_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/spice/mux2.sp" verilog_netlist="${OPENFPGA_PATH}/openfpga_flow/openfpga_cell_library/verilog/mux2.v">
<design_technology type="cmos" topology="MUX2"/>
<device_technology device_model_name="logic"/>
<input_buffer exist="false"/>
<output_buffer exist="false"/>
<port type="input" prefix="in0" lib_name="BB" size="1"/>
<port type="input" prefix="in1" lib_name="AA" size="1"/>
<port type="input" prefix="sel" lib_name="SS0" size="1"/>
<port type="output" prefix="out" lib_name="YY" size="1"/>
</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_tree" prefix="mux_tree" is_default="true" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" 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="MUX2"/>
<last_stage_pass_gate_logic circuit_model_name="MUX2D2"/>
<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_tree_tapbuf" prefix="mux_tree_tapbuf" dump_structural_verilog="true">
<design_technology type="cmos" structure="tree" 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="MUX2"/>
<last_stage_pass_gate_logic circuit_model_name="MUX2D2"/>
<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" 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" 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="frac_lut6" prefix="frac_lut6" dump_structural_verilog="true">
<design_technology type="cmos" fracturable_lut="true"/>
<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"/>
<lut_intermediate_buffer exist="true" circuit_model_name="buf4" location_map="-1-1-"/>
<pass_gate_logic circuit_model_name="MUX2"/>
<port type="input" prefix="in" size="6" tri_state_map="-----1" circuit_model_name="OR2"/>
<port type="output" prefix="lut5_out" size="2" lut_frac_level="5" lut_output_mask="0,1"/>
<port type="output" prefix="lut6_out" size="1" lut_output_mask="0"/>
<port type="sram" prefix="sram" size="64"/>
<port type="sram" prefix="mode" size="1" mode_select="true" circuit_model_name="DFFRQ" default_val="1"/>
</circuit_model>
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
<circuit_model type="ccff" name="DFFRQ" prefix="DFFRQ" 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="pReset" lib_name="RST" size="1" is_global="true" default_val="0" is_reset="true" is_prog="true"/>
<port type="input" prefix="D" size="1"/>
<port type="output" prefix="Q" size="1"/>
<port type="clock" prefix="prog_clk" lib_name="CK" size="1" is_global="true" default_val="0" is_prog="true"/>
</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="DFFRQ" 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="scan_chain" circuit_model_name="DFFRQ"/>
</configuration_protocol>
<connection_block>
<switch name="ipin_cblock" circuit_model_name="mux_tree_tapbuf"/>
</connection_block>
<switch_block>
<switch name="0" circuit_model_name="mux_tree_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_tree"/>
</pb_type>
<pb_type name="clb.fle" physical_mode_name="physical"/>
<pb_type name="clb.fle[physical].fabric.frac_logic.frac_lut6" circuit_model_name="frac_lut6" mode_bits="0"/>
<pb_type name="clb.fle[physical].fabric.ff" circuit_model_name="DFFSRQ"/>
<!-- Binding operating pb_type to physical pb_type -->
<pb_type name="clb.fle[n2_lut5].lut5inter.ble5.lut5" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut6" mode_bits="1" physical_pb_type_index_factor="0.5">
<!-- Binding the lut5 to the first 5 inputs of fracturable lut6 -->
<port name="in" physical_mode_port="in[0:4]"/>
<port name="out" physical_mode_port="lut5_out[0:0]" physical_mode_pin_rotate_offset="1"/>
</pb_type>
<pb_type name="clb.fle[n2_lut5].lut5inter.ble5.ff" physical_pb_type_name="clb.fle[physical].fabric.ff"/>
<pb_type name="clb.fle[n1_lut6].ble6.lut6" physical_pb_type_name="clb.fle[physical].fabric.frac_logic.frac_lut6" mode_bits="0">
<!-- Binding the lut6 to the first 6 inputs of fracturable lut6 -->
<port name="in" physical_mode_port="in[0:5]"/>
<port name="out" physical_mode_port="lut6_out"/>
</pb_type>
<pb_type name="clb.fle[n1_lut6].ble6.ff" physical_pb_type_name="clb.fle[physical].fabric.ff" physical_pb_type_index_factor="2" physical_pb_type_index_offset="0"/>
<!-- End physical pb_type binding in complex block IO -->
</pb_type_annotations>
</openfpga_architecture>

View File

@ -54,6 +54,55 @@ module MUX2(
endmodule
module MUX2D2(
// iVerilog is buggy on the 'input A' declaration when deposit initial
// values
input [0:0] AA, // Data input 0
input [0:0] BB, // Data input 1
input [0:0] SS0, // Select port
output [0:0] YY // Data output
);
assign YY = SS0 ? BB : AA;
// Note:
// MUX2 appears will appear in LUTs, routing multiplexers,
// being a component in combinational loops
// To help convergence in simulation
// i.e., to avoid the X (undetermined) signals,
// the following timing constraints and signal initialization
// has to be added!
`ifdef ENABLE_TIMING
// ------ BEGIN Pin-to-pin Timing constraints -----
specify
(AA => YY) = (0.001, 0.001);
(BB => YY) = (0.001, 0.001);
(SS0 => YY) = (0.001, 0.001);
endspecify
// ------ END Pin-to-pin Timing constraints -----
`endif
`ifdef ENABLE_SIGNAL_INITIALIZATION
// ------ BEGIN driver initialization -----
initial begin
`ifdef ENABLE_FORMAL_VERIFICATION
$deposit(AA, 1'b0);
$deposit(BB, 1'b0);
$deposit(SS0, 1'b0);
`else
$deposit(AA, $random);
$deposit(BB, $random);
$deposit(SS0, $random);
`endif
end
// ------ END driver initialization -----
`endif
endmodule
//-----------------------------------------------------
// Design Name : CARRY_MUX2
// File Name : mux2.v

View File

@ -84,6 +84,7 @@ run-task fpga_verilog/mux_design/tree_structure $@
echo -e "Testing Verilog generation with routing multiplexers implemented by standard cell MUX2";
run-task fpga_verilog/mux_design/stdcell_mux2 $@
run-task fpga_verilog/mux_design/stdcell_mux2_last_stage $@
echo -e "Testing Verilog generation with routing multiplexers implemented by local encoders";
run-task fpga_verilog/mux_design/local_encoder $@

View File

@ -0,0 +1,37 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# 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=vpr_blif
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N8_stdcell_laststage_mux_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N8_tileable_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
[SYNTHESIS_PARAM]
bench0_top = and2
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
bench0_chan_width = 300
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=