diff --git a/docs/source/manual/arch_lang/circuit_library.rst b/docs/source/manual/arch_lang/circuit_library.rst index 4ec803f99..0e515b84b 100644 --- a/docs/source/manual/arch_lang/circuit_library.rst +++ b/docs/source/manual/arch_lang/circuit_library.rst @@ -53,6 +53,7 @@ Here, we focus these common syntax and we will detail special syntax in :ref:`ci + @@ -129,12 +130,16 @@ Input and Output Buffers Pass Gate Logic ^^^^^^^^^^^^^^^ +.. note:: pass-gate logic are used in building multiplexers and LUTs. + .. option:: - ``circuit_model_name=""`` 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:: + + - ``circuit_model_name=""`` 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: diff --git a/docs/source/manual/arch_lang/circuit_model_examples.rst b/docs/source/manual/arch_lang/circuit_model_examples.rst index 94f1d5e02..5bc928c6c 100644 --- a/docs/source/manual/arch_lang/circuit_model_examples.rst +++ b/docs/source/manual/arch_lang/circuit_model_examples.rst @@ -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 @@ -631,12 +639,34 @@ Standard Cell Multiplexer -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 + + + + + + + + + + + + +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 diff --git a/docs/source/manual/arch_lang/figures/stdcellmux.png b/docs/source/manual/arch_lang/figures/stdcellmux.png new file mode 100644 index 000000000..d2d08c7b1 Binary files /dev/null and b/docs/source/manual/arch_lang/figures/stdcellmux.png differ diff --git a/libs/libarchopenfpga/src/check_circuit_library.cpp b/libs/libarchopenfpga/src/check_circuit_library.cpp index 62a71a3a1..a9852a7e5 100644 --- a/libs/libarchopenfpga/src/check_circuit_library.cpp +++ b/libs/libarchopenfpga/src/check_circuit_library.cpp @@ -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) { diff --git a/libs/libarchopenfpga/src/circuit_library.cpp b/libs/libarchopenfpga/src/circuit_library.cpp index 241f63c7a..28c00aa7b 100644 --- a/libs/libarchopenfpga/src/circuit_library.cpp +++ b/libs/libarchopenfpga/src/circuit_library.cpp @@ -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; } diff --git a/libs/libarchopenfpga/src/circuit_library.h b/libs/libarchopenfpga/src/circuit_library.h index 30caef09c..2c511d59c 100644 --- a/libs/libarchopenfpga/src/circuit_library.h +++ b/libs/libarchopenfpga/src/circuit_library.h @@ -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 pass_gate_logic_model_names_; vtr::vector pass_gate_logic_model_ids_; + vtr::vector + last_stage_pass_gate_logic_model_names_; + vtr::vector + last_stage_pass_gate_logic_model_ids_; /* Port information */ vtr::vector port_ids_; diff --git a/libs/libarchopenfpga/src/read_xml_circuit_library.cpp b/libs/libarchopenfpga/src/read_xml_circuit_library.cpp index 13ff84800..9fdc05265 100644 --- a/libs/libarchopenfpga/src/read_xml_circuit_library.cpp +++ b/libs/libarchopenfpga/src/read_xml_circuit_library.cpp @@ -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 diff --git a/libs/libarchopenfpga/src/write_xml_circuit_library.cpp b/libs/libarchopenfpga/src/write_xml_circuit_library.cpp index ac6867cea..42e392685 100644 --- a/libs/libarchopenfpga/src/write_xml_circuit_library.cpp +++ b/libs/libarchopenfpga/src/write_xml_circuit_library.cpp @@ -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" + << "" + << "\n"; } /* Write the ports of circuit model */ diff --git a/openfpga/src/fabric/build_mux_modules.cpp b/openfpga/src/fabric/build_mux_modules.cpp index 3233db768..5d9fb93d7 100644 --- a/openfpga/src/fabric/build_mux_modules.cpp +++ b/openfpga/src/fabric/build_mux_modules.cpp @@ -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 last_stage_std_cell_input_ports = + circuit_lib.model_ports_by_type(last_stage_std_cell_model, + CIRCUIT_MODEL_PORT_INPUT, true); + std::vector 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 last_stage_std_cell_module_inputs; + std::vector 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> 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, diff --git a/openfpga_flow/openfpga_arch/README.md b/openfpga_flow/openfpga_arch/README.md index a2cc2f6ee..6bd3535ed 100644 --- a/openfpga_flow/openfpga_arch/README.md +++ b/openfpga_flow/openfpga_arch/README.md @@ -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 - : The technology node which the delay numbers are extracted from. diff --git a/openfpga_flow/openfpga_arch/k6_frac_N8_stdcell_laststage_mux_40nm_openfpga.xml b/openfpga_flow/openfpga_arch/k6_frac_N8_stdcell_laststage_mux_40nm_openfpga.xml new file mode 100644 index 000000000..024b4fc13 --- /dev/null +++ b/openfpga_flow/openfpga_arch/k6_frac_N8_stdcell_laststage_mux_40nm_openfpga.xml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/openfpga_cell_library/verilog/mux2.v b/openfpga_flow/openfpga_cell_library/verilog/mux2.v index fed7858ba..4326a0017 100644 --- a/openfpga_flow/openfpga_cell_library/verilog/mux2.v +++ b/openfpga_flow/openfpga_cell_library/verilog/mux2.v @@ -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 diff --git a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh index 7f418b15d..6d6cb4829 100755 --- a/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh +++ b/openfpga_flow/regression_test_scripts/fpga_verilog_reg_test.sh @@ -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 $@ diff --git a/openfpga_flow/tasks/fpga_verilog/mux_design/stdcell_mux2_last_stage/config/task.conf b/openfpga_flow/tasks/fpga_verilog/mux_design/stdcell_mux2_last_stage/config/task.conf new file mode 100644 index 000000000..a70315f2d --- /dev/null +++ b/openfpga_flow/tasks/fpga_verilog/mux_design/stdcell_mux2_last_stage/config/task.conf @@ -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=