diff --git a/README.md b/README.md index efc0d0ad3..b6b67116c 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ [![Documentation Status](https://readthedocs.org/projects/openfpga/badge/?version=master)](https://openfpga.readthedocs.io/en/master/?badge=master) ## Introduction -The OpenFPGA framework is the **first open-source FPGA IP generator** supporting highly-customizable homogeneous FPGA architectures. OpenFPGA provides a full set of EDA support for customized FPGAs, including Verilog-to-bitstream generation and self-testing verification [testbenches/scripts](./testbenches/scripts) OpenFPGA opens the door to democratizing FPGA technology and EDA techniques, with agile prototyping approaches and constantly evolving EDA tools for chip designers and researchers. +The OpenFPGA framework is the **first open-source FPGA IP generator** supporting highly-customizable homogeneous FPGA architectures. OpenFPGA provides a full set of EDA support for customized FPGAs, including Verilog-to-bitstream generation and self-testing verification. OpenFPGA opens the door to democratizing FPGA technology and EDA techniques, with agile prototyping approaches and constantly evolving EDA tools for chip designers and researchers. ## Compilation -Dependencies and help using docker can be found [**here**](./docs/source/tutorials/building.rst). +Dependencies and help using docker can be found [**here**](./docs/source/tutorials/compile.rst). **Compilation Steps:** ```bash @@ -31,7 +31,6 @@ python3 openfpga_flow/scripts/run_fpga_task.py compilation_verification --debug We currently target OpenFPGA for: 1. Ubuntu 18.04 2. Red Hat 7.5 - 3. MacOS Mojave 10.14.4 *The tool was tested with these operating systems. It might work with earlier versions and other distributions.* @@ -39,7 +38,4 @@ We currently target OpenFPGA for: OpenFPGA's [full documentation](https://openfpga.readthedocs.io/en/master/) includes tutorials, descriptions of the design flow, and tool options. ## Tutorials -You can find some tutorials in the [**./tutorials**](./tutorials) folder. This will help you get more familiar with the tool and use OpenFPGA under different configurations. - -Through those tutorials, users can learn how to use the flow and install the different dependencies. -The [tutorial index](./tutorials/tutorial_index.md) will guide you through training and explain the folder oraganization as well as introducing some tips and commonly used keywords. +You can find some tutorials in the [**./tutorials**](./docs/source/tutorials/) folder. This will help you get more familiar with the tool and use OpenFPGA under different configurations. diff --git a/docs/source/arch_lang/addon_vpr_syntax.rst b/docs/source/arch_lang/addon_vpr_syntax.rst index c6ac221a2..18f61703a 100644 --- a/docs/source/arch_lang/addon_vpr_syntax.rst +++ b/docs/source/arch_lang/addon_vpr_syntax.rst @@ -10,10 +10,18 @@ Models, Complex blocks and Physical Tiles Each ```` should contain a ```` that describe the physical implementation of the ````. Note that this is fully compatible to the VPR architecture XML syntax. -```` should include the models that describe the primitive ```` in physical mode. - +.. note:: ```` should include the models that describe the primitive ```` in physical mode. + .. note:: Currently, OpenFPGA only supports 1 ```` to be defined under each ```` +.. option:: /> + + OpenFPGA allows users to define it a mode is packable for VPR. + By default, the packable is set to ``true``. + This is mainly used for the mode that describes the physical implementation, which is typically not packable. Disable it in the packing and signficantly accelerate the packing runtime. + + .. note:: Once a mode is set to unpackable, its child modes will be unpackable as well. + Layout ~~~~~~ diff --git a/docs/source/arch_lang/circuit_model_examples.rst b/docs/source/arch_lang/circuit_model_examples.rst index 3a749e49d..9b689d2f7 100644 --- a/docs/source/arch_lang/circuit_model_examples.rst +++ b/docs/source/arch_lang/circuit_model_examples.rst @@ -260,7 +260,6 @@ Template - .. option:: - ``topology="AND|OR|MUX2"`` Specify the logic functionality of a gate. As for standard cells, the size of each port is limited to 1. Currently, only 2-input and single-output logic gates are supported. @@ -290,6 +289,29 @@ This example shows: - Propagation delay from input ``a`` to ``out`` is 10ps in rising edge and and 8ps in falling edge - Propagation delay from input ``b`` to ``out`` is 10ps in rising edge and 7ps in falling edge +MUX2 Gate Example +``````````````````````` + +.. code-block:: xml + + + + + + + + + + + +This example shows: + - A 2-input MUX gate with two inputs ``in0`` and ``in1``, a select port ``sel`` and an output port ``out`` + - The Verilog of MUX2 gate is provided by the user in the netlist ``sc_mux.v`` + - The use of ``lib_name`` to bind to a Verilog module with different port names. + - When binding to the Verilog module, the inputs will be swapped. In other words, ``in0`` of the circuit model will be wired to the input ``B`` of the MUX2 cell, while ``in1`` of the circuit model will be wired to the input ``A`` of the MUX2 cell. + +.. note:: OpenFPGA requires a fixed truth table for the ``MUX2`` gate. 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. + Multiplexers ~~~~~~~~~~~~ @@ -330,6 +352,8 @@ Template .. note:: For tree-like multiplexers, they can be built with standard cell MUX2. To enable this, users should define a ``circuit_model``, which describes a 2-input multiplexer (See details and examples in how to define a logic gate using ``circuit_model``. In this case, the ``circuit_model_name`` in the ``pass_gate_logic`` should be the name of MUX2 ``circuit_model``. +.. note:: When multiplexers are not provided by users, the size of ports do not have to be consistent with actual numbers in the architecture. + One-level Mux Example ````````````````````` @@ -398,6 +422,26 @@ This example shows: - The multiplexer will be built by transmission gate using the circuit model ``tgate`` - The multiplexer will have 4 inputs and 3 SRAMs to control which datapath to propagate +Standard Cell Multiplexer Example +````````````````````````````````` +.. code-block:: xml + + + + + + + + + + + +This example shows: + - 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 + Look-Up Tables ~~~~~~~~~~~~~~ diff --git a/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp b/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp index 3114276ae..5daef1310 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp @@ -262,7 +262,12 @@ ArchDirect read_xml_direct_circuit(pugi::xml_node& Node, arch_direct.set_circuit_model(direct, direct_model); /* Add more information*/ - std::string direct_type_name = get_attribute(xml_direct, "type", loc_data).as_string(); + std::string direct_type_name = get_attribute(xml_direct, "type", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string("none"); + /* If not defined, we go to the next */ + if (std::string("none") == direct_type_name) { + continue; + } + e_direct_type direct_type = string_to_direct_type(direct_type_name); if (NUM_DIRECT_TYPES == direct_type) { diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index 24ef13dea..5fe043f8e 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -289,6 +289,11 @@ void Shell::run_script_mode(const char* script_file_name, T& context) { return; } + /* Consider that each line may not end due to the continued line charactor + * Use cmd_line to conjunct multiple lines + */ + std::string cmd_line; + /* Read line by line */ while (getline(fp, line)) { /* If the line that starts with '#', it is commented, we can skip */ @@ -302,9 +307,43 @@ void Shell::run_script_mode(const char* script_file_name, T& context) { if (cmd_end_pos != std::string::npos) { cmd_part = line.substr(0, cmd_end_pos); } - /* Process the command only when the line is not empty */ - if (!cmd_part.empty()) { - execute_command(cmd_part.c_str(), context); + + /* Remove the space at the end of the line + * So that we can check easily if there is a continued line in the end + */ + cmd_part.erase(std::find_if(cmd_part.rbegin(), cmd_part.rend(), [](int ch) { + return !std::isspace(ch); + }).base(), cmd_part.end()); + + /* If the line ends with '\', this is a continued line, parse the next until it ends */ + if ('\\' == cmd_part.back()) { + /* Pop up the last charactor and conjunct to cmd_line */ + cmd_part.pop_back(); + + if (!cmd_part.empty()) { + cmd_line += cmd_part; + } + /* Not finished yet. Parse the next line */ + continue; + } else { + /* End of this line, if cmd_line is empty, + * there is no previous lines, cache the part we have + * and then execute the command + */ + cmd_line += cmd_part; + } + + /* Remove the space at the beginning of the line */ + cmd_line.erase(cmd_line.begin(), std::find_if(cmd_line.begin(), cmd_line.end(), [](int ch) { + return !std::isspace(ch); + })); + + /* Process the command only when the full command line in ended */ + if (!cmd_line.empty()) { + VTR_LOG("\nCommand line to execute: %s\n", cmd_line.c_str()); + execute_command(cmd_line.c_str(), context); + /* Empty the line ready to start a new line */ + cmd_line.clear(); } } fp.close(); diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index f5f2c3c7e..3d97fee47 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -166,7 +166,7 @@ enum e_interconnect { NUM_INTERC_TYPES /* Xifan Tang - Invalid types for interconnect */ }; /* Xifan Tang - String versions of interconnection type */ -constexpr std::array INTERCONNECT_TYPE_STRING = {{"complete", "direct", "mux"}}; +constexpr std::array INTERCONNECT_TYPE_STRING = {{"unknown", "complete", "direct", "mux"}}; /* Orientations. */ enum e_side : unsigned char { @@ -822,6 +822,9 @@ struct t_mode { t_pb_type* parent_pb_type = nullptr; int index = 0; + /* Xifan Tang: Specify if the mode is packable or not */ + bool packable = true; + /* Power related members */ t_mode_power* mode_power = nullptr; diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index cabb17bbb..cf2dd72c3 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -1956,6 +1956,20 @@ static void ProcessMode(pugi::xml_node Parent, t_mode* mode, const bool timing_e mode->name = vtr::strdup(Prop); } + /* Xifan Tang: parse XML about if this mode is packable or not */ + mode->packable = true; + /* If the parent mode is not packable, all the child mode should be unpackable as well */ + if (nullptr != mode->parent_pb_type->parent_mode) { + mode->packable = mode->parent_pb_type->parent_mode->packable; + } + /* Override if user specify */ + mode->packable = get_attribute(Parent, "packable", loc_data, ReqOpt::OPTIONAL).as_bool(mode->packable); + if (false == mode->packable) { + VTR_LOG("mode '%s[%s]' is defined by user to be not packable\n", + mode->parent_pb_type->name, + mode->name); + } + mode->num_pb_type_children = count_children(Parent, "pb_type", loc_data, ReqOpt::OPTIONAL); if (mode->num_pb_type_children > 0) { mode->pb_type_children = new t_pb_type[mode->num_pb_type_children]; diff --git a/openfpga/src/annotation/annotate_pb_graph.cpp b/openfpga/src/annotation/annotate_pb_graph.cpp index 2b78f2f0e..081acf900 100644 --- a/openfpga/src/annotation/annotate_pb_graph.cpp +++ b/openfpga/src/annotation/annotate_pb_graph.cpp @@ -49,17 +49,48 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod VTR_ASSERT(nullptr != child_physical_mode); std::map interc_num_inputs; - /* Initialize the counter */ - for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) { - interc_num_inputs[interc] = 0; + + /* Find all the interconnects sourced from the input and clock pins */ + for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { + for (int iedge = 0; iedge < pb_graph_node->input_pins[iport][ipin].num_input_edges; ++iedge) { + t_interconnect* interc = pb_graph_node->input_pins[iport][ipin].input_edges[iedge]->interconnect; + /* Ensure that the interconnect is unique in the list */ + if (0 < interc_num_inputs.count(interc)) { + continue; + } + /* Unique interconnect, initialize the counter to be zero */ + interc_num_inputs[interc] = 0; + } + } + } + + for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { + for (int iedge = 0; iedge < pb_graph_node->clock_pins[iport][ipin].num_input_edges; ++iedge) { + t_interconnect* interc = pb_graph_node->clock_pins[iport][ipin].input_edges[iedge]->interconnect; + /* Ensure that the interconnect is unique in the list */ + if (0 < interc_num_inputs.count(interc)) { + continue; + } + /* Unique interconnect, initialize the counter to be zero */ + interc_num_inputs[interc] = 0; + } + } + } + + /* Check: all the element should be initialized to 0 */ + for (const auto& pair : interc_num_inputs) { + VTR_ASSERT(nullptr != pair.first); + VTR_ASSERT(0 == pair.second); } /* We only care input and clock pins */ for (int iport = 0; iport < pb_graph_node->num_input_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_input_pins[iport]; ++ipin) { /* For each interconnect, we count the total number of inputs */ - for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) { - interc_num_inputs[interc] += pb_graph_pin_inputs(&(pb_graph_node->input_pins[iport][ipin]), interc).size(); + for (const auto& pair : interc_num_inputs) { + interc_num_inputs[pair.first] += pb_graph_pin_inputs(&(pb_graph_node->input_pins[iport][ipin]), pair.first).size(); } } } @@ -67,29 +98,33 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod for (int iport = 0; iport < pb_graph_node->num_clock_ports; ++iport) { for (int ipin = 0; ipin < pb_graph_node->num_clock_pins[iport]; ++ipin) { /* For each interconnect, we count the total number of inputs */ - for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) { - interc_num_inputs[interc] += pb_graph_pin_inputs(&(pb_graph_node->clock_pins[iport][ipin]), interc).size(); + for (const auto& pair : interc_num_inputs) { + interc_num_inputs[pair.first] += pb_graph_pin_inputs(&(pb_graph_node->clock_pins[iport][ipin]), pair.first).size(); } } } /* For each interconnect that has more than 1 input, we can infer the physical type */ - for (t_interconnect* interc : pb_mode_interconnects(child_physical_mode)) { + for (const auto& pair : interc_num_inputs) { + t_interconnect* interc = pair.first; + size_t actual_interc_num_inputs = pair.second; /* If the number inputs for an interconnect is zero, this is a 0-driver pin * we just set 1 to use direct wires */ - if (0 == interc_num_inputs[interc]) { - interc_num_inputs[interc] = 1; + if (0 == actual_interc_num_inputs) { + actual_interc_num_inputs = 1; } - e_interconnect interc_physical_type = pb_interconnect_physical_type(interc, interc_num_inputs[interc]); + e_interconnect interc_physical_type = pb_interconnect_physical_type(interc, actual_interc_num_inputs); if (interc_physical_type == vpr_device_annotation.interconnect_physical_type(interc)) { /* Skip annotation if we have already done! */ continue; } VTR_LOGV(verbose_output, "Infer physical type '%s' of interconnect '%s' (was '%s')\n", - INTERCONNECT_TYPE_STRING[interc_physical_type], interc->name, INTERCONNECT_TYPE_STRING[interc->type]); + INTERCONNECT_TYPE_STRING[interc_physical_type], + interc->name, + INTERCONNECT_TYPE_STRING[interc->type]); vpr_device_annotation.add_interconnect_physical_type(interc, interc_physical_type); } } @@ -99,9 +134,82 @@ void rec_build_vpr_pb_graph_interconnect_physical_type_annotation(t_pb_graph_nod return; } - /* Recursively visit all the child pb_graph_nodes */ + /* Find the physical mode of current pb_graph node */ t_mode* physical_mode = vpr_device_annotation.physical_mode(pb_graph_node->pb_type); VTR_ASSERT(nullptr != physical_mode); + + /* Before going recursive, we should check the interconnect between output pins + * Note that this is NOT applicable to primitive pb_graph nodes!!! + * + * pb_graph_node + * -------------------------------+ + * | + * child_pb_graph_node | + * -------------------+ | + * | | + * output_pin +<----------+ output_pin + * | | + * -------------------+ | + * + */ + { /* Use a code block to use local variables freely */ + std::map interc_num_inputs; + /* Find all the interconnects sourced from the output pins */ + for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { + for (int iedge = 0; iedge < pb_graph_node->output_pins[iport][ipin].num_input_edges; ++iedge) { + t_interconnect* interc = pb_graph_node->output_pins[iport][ipin].input_edges[iedge]->interconnect; + /* Ensure that the interconnect is unique in the list */ + if (0 < interc_num_inputs.count(interc)) { + continue; + } + /* Unique interconnect, initialize the counter to be zero */ + interc_num_inputs[interc] = 0; + } + } + } + + /* Check: all the element should be initialized to 0 */ + for (const auto& pair : interc_num_inputs) { + VTR_ASSERT(nullptr != pair.first); + VTR_ASSERT(0 == pair.second); + } + + /* We only care input and clock pins */ + for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) { + for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) { + /* For each interconnect, we count the total number of inputs */ + for (const auto& pair : interc_num_inputs) { + interc_num_inputs[pair.first] += pb_graph_pin_inputs(&(pb_graph_node->output_pins[iport][ipin]), pair.first).size(); + } + } + } + /* For each interconnect that has more than 1 input, we can infer the physical type */ + for (const auto& pair : interc_num_inputs) { + t_interconnect* interc = pair.first; + size_t actual_interc_num_inputs = pair.second; + /* If the number inputs for an interconnect is zero, this is a 0-driver pin + * we just set 1 to use direct wires + */ + if (0 == actual_interc_num_inputs) { + actual_interc_num_inputs = 1; + } + + e_interconnect interc_physical_type = pb_interconnect_physical_type(interc, actual_interc_num_inputs); + if (interc_physical_type == vpr_device_annotation.interconnect_physical_type(interc)) { + /* Skip annotation if we have already done! */ + continue; + } + VTR_LOGV(verbose_output, + "Infer physical type '%s' of interconnect '%s' (was '%s')\n", + INTERCONNECT_TYPE_STRING[interc_physical_type], + interc->name, + INTERCONNECT_TYPE_STRING[interc->type]); + vpr_device_annotation.add_interconnect_physical_type(interc, interc_physical_type); + } + } + + /* Recursively visit all the child pb_graph_nodes */ for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) { /* Each child may exist multiple times in the hierarchy*/ for (int jpb = 0; jpb < physical_mode->pb_type_children[ipb].num_pb; ++jpb) { diff --git a/openfpga/src/base/openfpga_pb_pin_fixup.cpp b/openfpga/src/base/openfpga_pb_pin_fixup.cpp index 3e6fec2f7..cc91bdebe 100644 --- a/openfpga/src/base/openfpga_pb_pin_fixup.cpp +++ b/openfpga/src/base/openfpga_pb_pin_fixup.cpp @@ -121,7 +121,8 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct } /* Ignore used in local cluster only, reserved one CLB pin */ - if (false == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size()) { + if ( (ClusterNetId::INVALID() != cluster_net_id) + && (0 == clustering_ctx.clb_nlist.net_sinks(cluster_net_id).size())) { continue; } diff --git a/openfpga/src/base/openfpga_title.cpp b/openfpga/src/base/openfpga_title.cpp index 41616c8bd..ca39fe2e6 100644 --- a/openfpga/src/base/openfpga_title.cpp +++ b/openfpga/src/base/openfpga_title.cpp @@ -8,7 +8,7 @@ * Generate a string of openfpga title introduction * This is mainly used when launching OpenFPGA shell *******************************************************************/ -const char* create_openfpga_title() { +std::string create_openfpga_title() { std::string title; title += std::string("\n"); @@ -49,5 +49,5 @@ const char* create_openfpga_title() { title += std::string("THE SOFTWARE.\n"); title += std::string("\n"); - return title.c_str(); + return title; } diff --git a/openfpga/src/base/openfpga_title.h b/openfpga/src/base/openfpga_title.h index b4826964a..8f4ab1e90 100644 --- a/openfpga/src/base/openfpga_title.h +++ b/openfpga/src/base/openfpga_title.h @@ -9,6 +9,6 @@ /******************************************************************** * Function declaration *******************************************************************/ -const char* create_openfpga_title(); +std::string create_openfpga_title(); #endif diff --git a/openfpga/src/fabric/build_grid_modules.cpp b/openfpga/src/fabric/build_grid_modules.cpp index 741632d1c..95e435f6f 100644 --- a/openfpga/src/fabric/build_grid_modules.cpp +++ b/openfpga/src/fabric/build_grid_modules.cpp @@ -145,6 +145,8 @@ void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, } /******************************************************************** + * Add module nets between primitive module and its internal circuit module + * This is only applicable to the primitive module of a grid *******************************************************************/ static void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager, diff --git a/openfpga/src/main.cpp b/openfpga/src/main.cpp index eb88c2c65..e1f813e9b 100644 --- a/openfpga/src/main.cpp +++ b/openfpga/src/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char** argv) { */ openfpga::Shell shell("OpenFPGA"); - shell.add_title(create_openfpga_title()); + shell.add_title(create_openfpga_title().c_str()); /* Add vpr commands */ openfpga::add_vpr_commands(shell); diff --git a/openfpga/src/repack/check_lb_rr_graph.cpp b/openfpga/src/repack/check_lb_rr_graph.cpp index 9b3adbf8f..64b286b62 100644 --- a/openfpga/src/repack/check_lb_rr_graph.cpp +++ b/openfpga/src/repack/check_lb_rr_graph.cpp @@ -79,8 +79,8 @@ static bool check_lb_rr_graph_dangling_nodes(const LbRRGraph& lb_rr_graph) { if ((0 == lb_rr_graph.node_in_edges(node).size()) && (0 == lb_rr_graph.node_out_edges(node).size())) { /* Print a warning! */ - VTR_LOG_WARN("Node %s is dangling (zero fan-in and zero fan-out)!\n", - node); + VTR_LOG_WARN("Node %lu is dangling (zero fan-in and zero fan-out)!\n", + size_t(node)); VTR_LOG_WARN("Node details for debugging:\n"); print_lb_rr_node(lb_rr_graph, node); no_dangling = false; diff --git a/openfpga/test_openfpga_arch/k6_N10_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_N10_40nm_openfpga.xml index d93495f6b..17eb8b550 100644 --- a/openfpga/test_openfpga_arch/k6_N10_40nm_openfpga.xml +++ b/openfpga/test_openfpga_arch/k6_N10_40nm_openfpga.xml @@ -96,7 +96,6 @@ - @@ -106,7 +105,6 @@ - @@ -116,7 +114,6 @@ - @@ -127,7 +124,6 @@ - @@ -150,7 +146,6 @@ - @@ -161,7 +156,6 @@ - diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_40nm_openfpga.xml index b750f9736..c43614ae8 100644 --- a/openfpga/test_openfpga_arch/k6_frac_N10_40nm_openfpga.xml +++ b/openfpga/test_openfpga_arch/k6_frac_N10_40nm_openfpga.xml @@ -110,7 +110,6 @@ - @@ -120,7 +119,6 @@ - @@ -130,7 +128,6 @@ - @@ -141,7 +138,6 @@ - @@ -167,7 +163,6 @@ - @@ -178,7 +173,6 @@ - diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml index 98823698f..cf619cd27 100644 --- a/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml +++ b/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml @@ -110,7 +110,6 @@ - @@ -120,7 +119,6 @@ - @@ -130,7 +128,6 @@ - @@ -141,7 +138,6 @@ - @@ -168,7 +164,6 @@ - @@ -179,7 +174,6 @@ - @@ -189,7 +183,6 @@ - diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml index 9f37c1293..4ddf1dd0b 100644 --- a/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml +++ b/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_40nm_openfpga.xml @@ -110,7 +110,6 @@ - @@ -120,7 +119,6 @@ - @@ -130,7 +128,6 @@ - @@ -141,7 +138,6 @@ - @@ -168,7 +164,6 @@ - @@ -179,7 +174,6 @@ - @@ -189,7 +183,6 @@ - @@ -200,7 +193,6 @@ - diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_aib_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_aib_40nm_openfpga.xml index ea56fe036..f0e84e167 100644 --- a/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_aib_40nm_openfpga.xml +++ b/openfpga/test_openfpga_arch/k6_frac_N10_adder_chain_mem16K_aib_40nm_openfpga.xml @@ -110,7 +110,6 @@ - @@ -120,7 +119,6 @@ - @@ -130,7 +128,6 @@ - @@ -141,7 +138,6 @@ - @@ -168,7 +164,6 @@ - @@ -179,7 +174,6 @@ - @@ -189,7 +183,6 @@ - @@ -200,7 +193,6 @@ - @@ -213,7 +205,6 @@ - diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_adder_column_chain_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_adder_column_chain_40nm_openfpga.xml new file mode 100644 index 000000000..d70ebcb2d --- /dev/null +++ b/openfpga/test_openfpga_arch/k6_frac_N10_adder_column_chain_40nm_openfpga.xml @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_adder_register_chain_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_adder_register_chain_40nm_openfpga.xml new file mode 100644 index 000000000..81a9582dc --- /dev/null +++ b/openfpga/test_openfpga_arch/k6_frac_N10_adder_register_chain_40nm_openfpga.xml @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_adder_register_scan_chain_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_adder_register_scan_chain_40nm_openfpga.xml new file mode 100644 index 000000000..840a2e3bb --- /dev/null +++ b/openfpga/test_openfpga_arch/k6_frac_N10_adder_register_scan_chain_40nm_openfpga.xml @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_spyio_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_spyio_40nm_openfpga.xml index 2b432ce86..547c742c8 100644 --- a/openfpga/test_openfpga_arch/k6_frac_N10_spyio_40nm_openfpga.xml +++ b/openfpga/test_openfpga_arch/k6_frac_N10_spyio_40nm_openfpga.xml @@ -110,7 +110,6 @@ - @@ -120,7 +119,6 @@ - @@ -130,7 +128,6 @@ - @@ -141,7 +138,6 @@ - @@ -167,7 +163,6 @@ - @@ -178,7 +173,6 @@ - diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_stdcell_mux_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_stdcell_mux_40nm_openfpga.xml new file mode 100644 index 000000000..d3e3d1f6c --- /dev/null +++ b/openfpga/test_openfpga_arch/k6_frac_N10_stdcell_mux_40nm_openfpga.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga/test_openfpga_arch/k6_frac_N10_tree_mux_40nm_openfpga.xml b/openfpga/test_openfpga_arch/k6_frac_N10_tree_mux_40nm_openfpga.xml new file mode 100644 index 000000000..8052fb2dc --- /dev/null +++ b/openfpga/test_openfpga_arch/k6_frac_N10_tree_mux_40nm_openfpga.xml @@ -0,0 +1,251 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + 10e-12 5e-12 + + + 10e-12 5e-12 + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga/test_script/and_k6_frac.openfpga b/openfpga/test_script/and_k6_frac.openfpga index 63746cd71..e14811f49 100644 --- a/openfpga/test_script/and_k6_frac.openfpga +++ b/openfpga/test_script/and_k6_frac.openfpga @@ -8,7 +8,7 @@ read_openfpga_arch -f ./test_openfpga_arch/k6_frac_N10_40nm_openfpga.xml #write_openfpga_arch -f ./arch_echo.xml # Annotate the OpenFPGA architecture to VPR data base -link_openfpga_arch --activity_file ./test_blif/and.act --sort_gsb_chan_node_in_edges #--verbose +link_openfpga_arch --activity_file ./test_blif/and.act --sort_gsb_chan_node_in_edges --verbose # Check and correct any naming conflicts in the BLIF netlist check_netlist_naming_conflict --fix --report ./netlist_renaming.xml diff --git a/openfpga/test_script/and_k6_frac_tileable_adder_column_chain.openfpga b/openfpga/test_script/and_k6_frac_tileable_adder_column_chain.openfpga new file mode 100644 index 000000000..fbcdda185 --- /dev/null +++ b/openfpga/test_script/and_k6_frac_tileable_adder_column_chain.openfpga @@ -0,0 +1,62 @@ +# Run VPR for the 'and' design +vpr ./test_vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml ./test_blif/and.blif --route_chan_width 40 --clock_modeling route #--write_rr_graph example_rr_graph.xml + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ./test_openfpga_arch/k6_frac_N10_adder_column_chain_40nm_openfpga.xml + +# Write out the architecture XML as a proof +#write_openfpga_arch -f ./arch_echo.xml + +# Annotate the OpenFPGA architecture to VPR data base +link_openfpga_arch --activity_file ./test_blif/and.act --sort_gsb_chan_node_in_edges #--verbose + +# Write GSB to XML for debugging +write_gsb_to_xml --file /var/tmp/xtang/openfpga_test_src/gsb_xml + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup #--verbose + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --duplicate_grid_pin --verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --file /var/tmp/xtang/openfpga_test_src/fabric_indepenent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src/SRC --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src/SRC --reference_benchmark_file_path /var/tmp/xtang/and.v --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini /var/tmp/xtang/openfpga_test_src/simulation_deck.ini + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file /var/tmp/xtang/openfpga_test_src/SDC + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file /var/tmp/xtang/openfpga_test_src/SDC_analysis + +# Finish and exit OpenFPGA +exit diff --git a/openfpga/test_script/and_k6_frac_tileable_adder_register_scan_chain.openfpga b/openfpga/test_script/and_k6_frac_tileable_adder_register_scan_chain.openfpga new file mode 100644 index 000000000..864fea78d --- /dev/null +++ b/openfpga/test_script/and_k6_frac_tileable_adder_register_scan_chain.openfpga @@ -0,0 +1,63 @@ +# Run VPR for the 'and' design +vpr ./test_vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_40nm.xml ./test_blif/and.blif --route_chan_width 40 --clock_modeling route #--write_rr_graph example_rr_graph.xml + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ./test_openfpga_arch/k6_frac_N10_adder_register_scan_chain_40nm_openfpga.xml + +# Write out the architecture XML as a proof +#write_openfpga_arch -f ./arch_echo.xml + +# Annotate the OpenFPGA architecture to VPR data base +link_openfpga_arch --activity_file ./test_blif/and.act --sort_gsb_chan_node_in_edges #--verbose + +# Write GSB to XML for debugging +write_gsb_to_xml --file /var/tmp/xtang/openfpga_test_src/gsb_xml + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup #--verbose + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --duplicate_grid_pin --verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --file /var/tmp/xtang/openfpga_test_src/fabric_indepenent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src/SRC --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src/SRC --reference_benchmark_file_path /var/tmp/xtang/and.v --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini /var/tmp/xtang/openfpga_test_src/simulation_deck.ini + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file /var/tmp/xtang/openfpga_test_src/SDC + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc \ + --file /var/tmp/xtang/openfpga_test_src/SDC_analysis + +# Finish and exit OpenFPGA +exit diff --git a/openfpga/test_script/and_k6_frac_tileable_stdcell_mux2.openfpga b/openfpga/test_script/and_k6_frac_tileable_stdcell_mux2.openfpga new file mode 100644 index 000000000..04ff99d8c --- /dev/null +++ b/openfpga/test_script/and_k6_frac_tileable_stdcell_mux2.openfpga @@ -0,0 +1,59 @@ +# Run VPR for the 'and' design +vpr ./test_vpr_arch/k6_frac_N10_tileable_40nm.xml ./test_blif/and.blif --clock_modeling route #--write_rr_graph example_rr_graph.xml + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ./test_openfpga_arch/k6_frac_N10_stdcell_mux_40nm_openfpga.xml + +# Write out the architecture XML as a proof +#write_openfpga_arch -f ./arch_echo.xml + +# Annotate the OpenFPGA architecture to VPR data base +link_openfpga_arch --activity_file ./test_blif/and.act --sort_gsb_chan_node_in_edges #--verbose + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup #--verbose + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --duplicate_grid_pin #--verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --file /var/tmp/xtang/openfpga_test_src/fabric_indepenent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src/SRC --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src/SRC --reference_benchmark_file_path /var/tmp/xtang/and.v --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini /var/tmp/xtang/openfpga_test_src/simulation_deck.ini + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file /var/tmp/xtang/openfpga_test_src/SDC + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file /var/tmp/xtang/openfpga_test_src/SDC_analysis + +# Finish and exit OpenFPGA +exit diff --git a/openfpga/test_script/and_k6_frac_tileable_tree_mux.openfpga b/openfpga/test_script/and_k6_frac_tileable_tree_mux.openfpga new file mode 100644 index 000000000..95cd2a3c3 --- /dev/null +++ b/openfpga/test_script/and_k6_frac_tileable_tree_mux.openfpga @@ -0,0 +1,59 @@ +# Run VPR for the 'and' design +vpr ./test_vpr_arch/k6_frac_N10_tileable_40nm.xml ./test_blif/and.blif --clock_modeling route #--write_rr_graph example_rr_graph.xml + +# Read OpenFPGA architecture definition +read_openfpga_arch -f ./test_openfpga_arch/k6_frac_N10_tree_mux_40nm_openfpga.xml + +# Write out the architecture XML as a proof +#write_openfpga_arch -f ./arch_echo.xml + +# Annotate the OpenFPGA architecture to VPR data base +link_openfpga_arch --activity_file ./test_blif/and.act --sort_gsb_chan_node_in_edges #--verbose + +# Check and correct any naming conflicts in the BLIF netlist +check_netlist_naming_conflict --fix --report ./netlist_renaming.xml + +# Apply fix-up to clustering nets based on routing results +pb_pin_fixup --verbose + +# Apply fix-up to Look-Up Table truth tables based on packing results +lut_truth_table_fixup #--verbose + +# Build the module graph +# - Enabled compression on routing architecture modules +# - Enable pin duplication on grid modules +build_fabric --compress_routing --duplicate_grid_pin #--verbose + +# Repack the netlist to physical pbs +# This must be done before bitstream generator and testbench generation +# Strongly recommend it is done after all the fix-up have been applied +repack #--verbose + +# Build the bitstream +# - Output the fabric-independent bitstream to a file +build_architecture_bitstream --verbose --file /var/tmp/xtang/openfpga_test_src/fabric_indepenent_bitstream.xml + +# Build fabric-dependent bitstream +build_fabric_bitstream --verbose + +# Write the Verilog netlist for FPGA fabric +# - Enable the use of explicit port mapping in Verilog netlist +write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src/SRC --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --print_user_defined_template --verbose + +# Write the Verilog testbench for FPGA fabric +# - We suggest the use of same output directory as fabric Verilog netlists +# - Must specify the reference benchmark file if you want to output any testbenches +# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA +# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase +# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts +write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src/SRC --reference_benchmark_file_path /var/tmp/xtang/and.v --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini /var/tmp/xtang/openfpga_test_src/simulation_deck.ini + +# Write the SDC files for PnR backend +# - Turn on every options here +write_pnr_sdc --file /var/tmp/xtang/openfpga_test_src/SDC + +# Write the SDC to run timing analysis for a mapped FPGA fabric +write_analysis_sdc --file /var/tmp/xtang/openfpga_test_src/SDC_analysis + +# Finish and exit OpenFPGA +exit diff --git a/openfpga/test_vpr_arch/k6_N10_40nm.xml b/openfpga/test_vpr_arch/k6_N10_40nm.xml index 630011e84..83b4948a8 100644 --- a/openfpga/test_vpr_arch/k6_N10_40nm.xml +++ b/openfpga/test_vpr_arch/k6_N10_40nm.xml @@ -139,7 +139,7 @@ - + diff --git a/openfpga/test_vpr_arch/k6_N10_tileable_40nm.xml b/openfpga/test_vpr_arch/k6_N10_tileable_40nm.xml index d86d7aa62..ceacbb3f2 100644 --- a/openfpga/test_vpr_arch/k6_N10_tileable_40nm.xml +++ b/openfpga/test_vpr_arch/k6_N10_tileable_40nm.xml @@ -139,7 +139,7 @@ - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml index ef9268810..8476a5155 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml @@ -158,7 +158,7 @@ - + @@ -230,7 +230,7 @@ - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_40nm.xml index bbe041562..1fb82be72 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_40nm.xml @@ -245,7 +245,7 @@ - + @@ -321,7 +321,7 @@ - + @@ -371,21 +371,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml index 850eb5450..e0d7ce812 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_adder_chain_mem16K_40nm.xml @@ -282,7 +282,7 @@ - + @@ -358,7 +358,7 @@ - + @@ -408,21 +408,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_40nm.xml index 2c528c13c..146a170e5 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_40nm.xml @@ -158,7 +158,7 @@ - + @@ -230,7 +230,7 @@ - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml index eea76837f..8f1dfd10e 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml @@ -245,7 +245,7 @@ - + @@ -321,7 +321,7 @@ - + @@ -371,21 +371,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml index 9422c3a09..8254a0583 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_40nm.xml @@ -282,7 +282,7 @@ - + @@ -358,7 +358,7 @@ - + @@ -408,21 +408,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_aib_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_aib_40nm.xml index e196cb83c..35eedb327 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_aib_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_aib_40nm.xml @@ -348,7 +348,7 @@ - + @@ -424,7 +424,7 @@ - + @@ -474,21 +474,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_multi_io_capacity_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_multi_io_capacity_40nm.xml index 8eb6f32bf..d23c34960 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_multi_io_capacity_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_multi_io_capacity_40nm.xml @@ -316,7 +316,7 @@ - + @@ -392,7 +392,7 @@ - + @@ -442,21 +442,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_reduced_io_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_reduced_io_40nm.xml index 6f8c4cfae..bb06c5f39 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_reduced_io_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_mem16K_reduced_io_40nm.xml @@ -285,7 +285,7 @@ - + @@ -361,7 +361,7 @@ - + @@ -411,21 +411,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml index f07f16c80..1bb8ffe23 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_chain_wide_mem16K_40nm.xml @@ -282,7 +282,7 @@ - + @@ -358,7 +358,7 @@ - + @@ -408,21 +408,26 @@ - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_register_chain_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_register_chain_40nm.xml new file mode 100644 index 000000000..77dedbcb0 --- /dev/null +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_register_chain_40nm.xml @@ -0,0 +1,696 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + + + + clb.clk + clb.cin clb.regin + clb.O[9:0] clb.I[19:0] + clb.cout clb.regout clb.O[19:10] clb.I[39:20] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_40nm.xml new file mode 100644 index 000000000..f83919c7c --- /dev/null +++ b/openfpga/test_vpr_arch/k6_frac_N10_tileable_adder_register_scan_chain_40nm.xml @@ -0,0 +1,734 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + clb.clk + clb.cin clb.regin clb.scin + clb.O[9:0] clb.I[19:0] + clb.cout clb.regout clb.scout clb.O[19:10] clb.I[39:20] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 235e-12 + 235e-12 + 235e-12 + 235e-12 + 235e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 195e-12 + 195e-12 + 195e-12 + 195e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vpr/src/pack/cluster.cpp b/vpr/src/pack/cluster.cpp index fa9d4d8f8..51de31f7e 100644 --- a/vpr/src/pack/cluster.cpp +++ b/vpr/src/pack/cluster.cpp @@ -1458,6 +1458,11 @@ static enum e_block_pack_status try_place_atom_block_rec(const t_pb_graph_node* } pb_type = pb_graph_node->pb_type; + /* Xifan Tang: bypass unpackable modes */ + if (false == pb_type->parent_mode->packable) { + return BLK_FAILED_FEASIBLE; + } + is_primitive = (pb_type->num_modes == 0); if (is_primitive) { diff --git a/vpr/src/pack/cluster_router.cpp b/vpr/src/pack/cluster_router.cpp index d94691053..7f2cd37d9 100644 --- a/vpr/src/pack/cluster_router.cpp +++ b/vpr/src/pack/cluster_router.cpp @@ -1173,6 +1173,10 @@ static void expand_node_all_modes(t_lb_router_data* router_data, t_expansion_nod if (cur_mode != -1 && mode != cur_mode) { continue; } + /* Xifan Tang: Do not expand in unpackable modes */ + if (false == pin->parent_node->pb_type->parent_mode->packable) { + continue; + } /* Check whether a mode is illegal. If it is then the node will not be expanded */ bool is_illegal = false; diff --git a/vpr/src/pack/prepack.cpp b/vpr/src/pack/prepack.cpp index 28e8c2bc5..dd9d1da3f 100644 --- a/vpr/src/pack/prepack.cpp +++ b/vpr/src/pack/prepack.cpp @@ -791,6 +791,13 @@ t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_pack_pat * TODO: Need to investigate better mapping strategies than first-fit */ for (i = 0; i < num_packing_patterns; i++) { + + /* Xifan Tang: skip patterns that belong to unpackable modes */ + if ( (nullptr != list_of_pack_patterns[i].root_block->pb_type->parent_mode) + && (false == list_of_pack_patterns[i].root_block->pb_type->parent_mode->packable) ) { + continue; + } + best_pattern = 0; for (j = 1; j < num_packing_patterns; j++) { if (is_used[best_pattern]) { @@ -799,7 +806,7 @@ t_pack_molecule* alloc_and_load_pack_molecules(t_pack_patterns* list_of_pack_pat best_pattern = j; } } - VTR_ASSERT(is_used[best_pattern] == false); + VTR_ASSERT(is_used[best_pattern] == false); is_used[best_pattern] = true; auto blocks = atom_ctx.nlist.blocks(); @@ -1213,6 +1220,11 @@ static t_pb_graph_node* get_expected_lowest_cost_primitive_for_atom_block_in_pb_ } } else { for (i = 0; i < curr_pb_graph_node->pb_type->num_modes; i++) { + /* Xifan Tang: early fail if this primitive in a unpackable mode */ + if (false == curr_pb_graph_node->pb_type->modes[i].packable) { + continue; + } + for (j = 0; j < curr_pb_graph_node->pb_type->modes[i].num_pb_type_children; j++) { *cost = UNDEFINED; cur = get_expected_lowest_cost_primitive_for_atom_block_in_pb_graph_node(blk_id, &curr_pb_graph_node->child_pb_graph_nodes[i][j][0], cost); @@ -1545,6 +1557,13 @@ static t_pb_graph_pin* get_connected_primitive_pin(const t_pb_graph_pin* cluster * will be only one pin connected to the very first adder in the cluster. */ static void get_all_connected_primitive_pins(const t_pb_graph_pin* cluster_input_pin, std::vector& connected_primitive_pins) { + + /* Xifan Tang: Skip pins belong to unpackable modes */ + if ( (nullptr != cluster_input_pin->parent_node->pb_type->parent_mode) + && (false == cluster_input_pin->parent_node->pb_type->parent_mode->packable) ) { + return; + } + for (int iedge = 0; iedge < cluster_input_pin->num_output_edges; iedge++) { const auto& output_edge = cluster_input_pin->output_edges[iedge]; for (int ipin = 0; ipin < output_edge->num_output_pins; ipin++) { diff --git a/vpr7_x2p/libarchfpgavpr7/SRC/check_circuit_library.cpp b/vpr7_x2p/libarchfpgavpr7/SRC/check_circuit_library.cpp index e6f49a1c0..f0ed79a1c 100644 --- a/vpr7_x2p/libarchfpgavpr7/SRC/check_circuit_library.cpp +++ b/vpr7_x2p/libarchfpgavpr7/SRC/check_circuit_library.cpp @@ -352,9 +352,10 @@ size_t check_circuit_library_ports(const CircuitLibrary& circuit_lib) { /* Check global ports: make sure all the global ports are input ports */ for (const auto& port : circuit_lib.ports()) { if ( (circuit_lib.port_is_global(port)) - && (!circuit_lib.is_input_port(port)) ) { + && (!circuit_lib.is_input_port(port)) + && (!circuit_lib.is_output_port(port)) ) { vpr_printf(TIO_MESSAGE_ERROR, - "Circuit port (type=%s) of model (name=%s) is defined as global but not an input port!\n", + "Circuit port (type=%s) of model (name=%s) is defined as global but not an input/output port!\n", CIRCUIT_MODEL_PORT_TYPE_STRING[size_t(circuit_lib.port_type(port))], circuit_lib.model_name(port).c_str()); num_err++; diff --git a/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.cpp b/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.cpp index 5b7c7b62d..2a5154e44 100644 --- a/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.cpp +++ b/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.cpp @@ -767,6 +767,12 @@ size_t CircuitLibrary::port_default_value(const CircuitPortId& circuit_port_id) return port_default_values_[circuit_port_id]; } +/* Return a flag if the port is used in mode-selection purpuse of a circuit model */ +bool CircuitLibrary::port_is_io(const CircuitPortId& circuit_port_id) const { + /* validate the circuit_port_id */ + VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); + return port_is_io_[circuit_port_id]; +} /* Return a flag if the port is used in mode-selection purpuse of a circuit model */ bool CircuitLibrary::port_is_mode_select(const CircuitPortId& circuit_port_id) const { @@ -1212,6 +1218,7 @@ CircuitPortId CircuitLibrary::add_model_port(const CircuitModelId& model_id, port_lib_names_.emplace_back(); port_inv_prefix_.emplace_back(); port_default_values_.push_back(-1); + port_is_io_.push_back(false); port_is_mode_select_.push_back(false); port_is_global_.push_back(false); port_is_reset_.push_back(false); @@ -1282,6 +1289,15 @@ void CircuitLibrary::set_port_default_value(const CircuitPortId& circuit_port_id return; } +/* Set the is_mode_select for a port of a circuit model */ +void CircuitLibrary::set_port_is_io(const CircuitPortId& circuit_port_id, + const bool& is_io) { + /* validate the circuit_port_id */ + VTR_ASSERT(valid_circuit_port_id(circuit_port_id)); + port_is_io_[circuit_port_id] = is_io; + return; +} + /* Set the is_mode_select for a port of a circuit model */ void CircuitLibrary::set_port_is_mode_select(const CircuitPortId& circuit_port_id, const bool& is_mode_select) { diff --git a/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.h b/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.h index 8080d2ea3..b76e2be63 100644 --- a/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.h +++ b/vpr7_x2p/libarchfpgavpr7/SRC/circuit_library.h @@ -281,6 +281,7 @@ class CircuitLibrary { std::string port_lib_name(const CircuitPortId& circuit_port_id) const; std::string port_inv_prefix(const CircuitPortId& circuit_port_id) const; size_t port_default_value(const CircuitPortId& circuit_port_id) const; + bool port_is_io(const CircuitPortId& circuit_port_id) const; bool port_is_mode_select(const CircuitPortId& circuit_port_id) const; bool port_is_global(const CircuitPortId& circuit_port_id) const; bool port_is_reset(const CircuitPortId& circuit_port_id) const; @@ -351,6 +352,8 @@ class CircuitLibrary { const std::string& inv_prefix); void set_port_default_value(const CircuitPortId& circuit_port_id, const size_t& default_val); + void set_port_is_io(const CircuitPortId& circuit_port_id, + const bool& is_io); void set_port_is_mode_select(const CircuitPortId& circuit_port_id, const bool& is_mode_select); void set_port_is_global(const CircuitPortId& circuit_port_id, @@ -534,6 +537,7 @@ class CircuitLibrary { vtr::vector port_lib_names_; vtr::vector port_inv_prefix_; vtr::vector port_default_values_; + vtr::vector port_is_io_; vtr::vector port_is_mode_select_; vtr::vector port_is_global_; vtr::vector port_is_reset_; diff --git a/vpr7_x2p/libarchfpgavpr7/SRC/read_xml_spice.c b/vpr7_x2p/libarchfpgavpr7/SRC/read_xml_spice.c index c630dc37f..4c613e076 100644 --- a/vpr7_x2p/libarchfpgavpr7/SRC/read_xml_spice.c +++ b/vpr7_x2p/libarchfpgavpr7/SRC/read_xml_spice.c @@ -783,6 +783,11 @@ static void ProcessSpiceModelPort(ezxml_t Node, /* Output mast of a fracturable LUT, which is to identify which intermediate LUT output will be connected to outputs */ ProcessSpiceModelPortLutOutputMask(Node, port); + if (SPICE_MODEL_PORT_INPUT == port->type) { + port->is_io = GetBooleanProperty(Node, "io", FALSE, FALSE); + ezxml_set_attr(Node, "io", NULL); + } + /* See if this is a global signal * We assume that global signals are shared by all the SPICE Model/blocks. * We need to check if other SPICE model has the same port name @@ -1748,6 +1753,7 @@ CircuitLibrary build_circuit_library(int num_spice_model, t_spice_model* spice_m circuit_lib.set_port_default_value(port_id, spice_models[imodel].ports[iport].default_val); + circuit_lib.set_port_is_io(port_id, TRUE == spice_models[imodel].ports[iport].is_io); circuit_lib.set_port_is_mode_select(port_id, TRUE == spice_models[imodel].ports[iport].mode_select); circuit_lib.set_port_is_global(port_id, TRUE == spice_models[imodel].ports[iport].is_global); circuit_lib.set_port_is_reset(port_id, TRUE == spice_models[imodel].ports[iport].is_reset); diff --git a/vpr7_x2p/libarchfpgavpr7/SRC/spice_types.h b/vpr7_x2p/libarchfpgavpr7/SRC/spice_types.h index 26f30b164..97e1b02dc 100644 --- a/vpr7_x2p/libarchfpgavpr7/SRC/spice_types.h +++ b/vpr7_x2p/libarchfpgavpr7/SRC/spice_types.h @@ -164,6 +164,7 @@ struct s_spice_model_port { boolean mode_select; int default_val; /* Global port properties */ + boolean is_io; boolean is_global; boolean is_reset; boolean is_set; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp index 4f1e21d80..7a61ae6c8 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.cpp @@ -1343,10 +1343,13 @@ std::string generate_pb_type_port_name(t_port* pb_type_port) { ********************************************************************/ std::string generate_fpga_global_io_port_name(const std::string& prefix, const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model) { + const CircuitModelId& circuit_model, + const CircuitPortId& circuit_port) { std::string port_name(prefix); port_name += circuit_lib.model_name(circuit_model); + port_name += std::string("_"); + port_name += circuit_lib.port_prefix(circuit_port); return port_name; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h index ad0a5932e..a62523f59 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_naming.h @@ -232,7 +232,8 @@ std::string generate_pb_type_port_name(t_port* pb_type_port); std::string generate_fpga_global_io_port_name(const std::string& prefix, const CircuitLibrary& circuit_lib, - const CircuitModelId& circuit_model); + const CircuitModelId& circuit_model, + const CircuitPortId& circuit_port); std::string generate_fpga_top_module_name(); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp index 0281a5a5a..2cce352a3 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.cpp @@ -117,7 +117,7 @@ std::string ModuleManager::module_name(const ModuleId& module_id) const { /* Get the string of a module port type */ std::string ModuleManager::module_port_type_str(const enum e_module_port_type& port_type) const { - std::array MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}}; + std::array MODULE_PORT_TYPE_STRING = {{"GLOBAL PORTS", "GPIN PORTS", "GPOUT PORTS", "GPIO PORTS", "INOUT PORTS", "INPUT PORTS", "OUTPUT PORTS", "CLOCK PORTS"}}; return MODULE_PORT_TYPE_STRING[port_type]; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h index 9097dd603..7aaf528f3 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager.h @@ -26,6 +26,8 @@ class ModuleManager { public: /* Private data structures */ enum e_module_port_type { MODULE_GLOBAL_PORT, /* Global inputs */ + MODULE_GPIN_PORT, /* General-purpose input */ + MODULE_GPOUT_PORT, /* General-purpose outputs, could be used for spypads */ MODULE_GPIO_PORT, /* General-purpose IOs, which are data IOs of the fabric */ MODULE_INOUT_PORT, /* Normal (non-global) inout ports */ MODULE_INPUT_PORT, /* Normal (non-global) input ports */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp index f8c79a238..927506096 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/module_manager_utils.cpp @@ -37,7 +37,18 @@ ModuleId add_circuit_model_to_module_manager(ModuleManager& module_manager, /* Find global ports and add one by one */ for (const auto& port : circuit_lib.model_global_ports(circuit_model, false)) { BasicPort port_info(circuit_lib.port_prefix(port), circuit_lib.port_size(port)); - module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT); + if ( (SPICE_MODEL_PORT_INPUT == circuit_lib.port_type(port)) + && (false == circuit_lib.port_is_io(port)) ) { + module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT); + } else if (SPICE_MODEL_PORT_CLOCK == circuit_lib.port_type(port)) { + module_manager.add_port(module, port_info, ModuleManager::MODULE_GLOBAL_PORT); + } else if ( (SPICE_MODEL_PORT_INPUT == circuit_lib.port_type(port)) + && (true == circuit_lib.port_is_io(port)) ) { + module_manager.add_port(module, port_info, ModuleManager::MODULE_GPIN_PORT); + } else { + VTR_ASSERT(SPICE_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)); + module_manager.add_port(module, port_info, ModuleManager::MODULE_GPOUT_PORT); + } } /* Find other ports and add one by one */ @@ -925,19 +936,35 @@ size_t find_module_num_config_bits(const ModuleManager& module_manager, } /******************************************************************** - * Add GPIO ports to the module: + * Add General purpose I/O ports to the module: * In this function, the following tasks are done: - * 1. find all the GPIO ports from the child modules and build a list of it, - * 2. Merge all the GPIO ports with the same name + * 1. find all the I/O ports from the child modules and build a list of it, + * 2. Merge all the I/O ports with the same name * 3. add the ports to the pb_module * 4. add module nets to connect to the GPIO ports of each sub module + * + * Module + * ----------------------+ + * | + * child[0] | + * -----------+ | + * |----------+----> outputA[0] + * -----------+ | + * | + * child[1] | + * -----------+ | + * |----------+----> outputA[1] + * -----------+ | + * * Note: This function should be call ONLY after all the sub modules (instances) * have been added to the pb_module! * Otherwise, some GPIO ports of the sub modules may be missed! *******************************************************************/ -void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, - const ModuleId& module_id) { +static +void add_module_io_ports_from_child_modules(ModuleManager& module_manager, + const ModuleId& module_id, + const ModuleManager::e_module_port_type& module_port_type) { std::vector gpio_ports_to_add; /* Iterate over the child modules */ @@ -945,7 +972,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, /* Iterate over the child instances */ for (size_t i = 0; i < module_manager.num_instance(module_id, child); ++i) { /* Find all the global ports, whose port type is special */ - for (BasicPort gpio_port : module_manager.module_ports_by_type(child, ModuleManager::MODULE_GPIO_PORT)) { + for (BasicPort gpio_port : module_manager.module_ports_by_type(child, module_port_type)) { /* If this port is not mergeable, we update the list */ bool is_mergeable = false; for (BasicPort& gpio_port_to_add : gpio_ports_to_add) { @@ -973,7 +1000,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, std::vector gpio_port_ids; /* Add the gpio ports for the module */ for (const BasicPort& gpio_port_to_add : gpio_ports_to_add) { - ModulePortId port_id = module_manager.add_port(module_id, gpio_port_to_add, ModuleManager::MODULE_GPIO_PORT); + ModulePortId port_id = module_manager.add_port(module_id, gpio_port_to_add, module_port_type); gpio_port_ids.push_back(port_id); } @@ -984,7 +1011,7 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, /* Iterate over the child instances */ for (const size_t& child_instance : module_manager.child_module_instances(module_id, child)) { /* Find all the global ports, whose port type is special */ - for (ModulePortId child_gpio_port_id : module_manager.module_port_ids_by_type(child, ModuleManager::MODULE_GPIO_PORT)) { + for (ModulePortId child_gpio_port_id : module_manager.module_port_ids_by_type(child, module_port_type)) { BasicPort child_gpio_port = module_manager.module_port(child, child_gpio_port_id); /* Find the port with the same name! */ for (size_t iport = 0; iport < gpio_ports_to_add.size(); ++iport) { @@ -995,8 +1022,22 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, for (const size_t& pin_id : child_gpio_port.pins()) { /* Reach here, it means this is the port we want, create a net and configure its source and sink */ ModuleNetId net = module_manager.create_module_net(module_id); - module_manager.add_module_net_source(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]); - module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id); + /* - For GPIO and GPIN ports + * the source of the net is the current module + * the sink of the net is the child module + * - For GPOUT ports + * the source of the net is the child module + * the sink of the net is the current module + */ + if ( (ModuleManager::MODULE_GPIO_PORT == module_port_type) + || (ModuleManager::MODULE_GPIN_PORT == module_port_type) ) { + module_manager.add_module_net_source(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]); + module_manager.add_module_net_sink(module_id, net, child, child_instance, child_gpio_port_id, pin_id); + } else { + VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_port_type); + module_manager.add_module_net_sink(module_id, net, module_id, 0, gpio_port_ids[iport], gpio_port_lsb[iport]); + module_manager.add_module_net_source(module_id, net, child, child_instance, child_gpio_port_id, pin_id); + } /* Update the LSB counter */ gpio_port_lsb[iport]++; } @@ -1014,6 +1055,27 @@ void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, } } +/******************************************************************** + * Add GPIO ports to the module: + * In this function, the following tasks are done: + * 1. find all the GPIO ports from the child modules and build a list of it, + * 2. Merge all the GPIO ports with the same name + * 3. add the ports to the pb_module + * 4. add module nets to connect to the GPIO ports of each sub module + * + * Note: This function should be call ONLY after all the sub modules (instances) + * have been added to the pb_module! + * Otherwise, some GPIO ports of the sub modules may be missed! + *******************************************************************/ +void add_module_gpio_ports_from_child_modules(ModuleManager& module_manager, + const ModuleId& module_id) { + add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPIO_PORT); + + add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPIN_PORT); + + add_module_io_ports_from_child_modules(module_manager, module_id, ModuleManager::MODULE_GPOUT_PORT); +} + /******************************************************************** * Add global ports to the module: * In this function, the following tasks are done: diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp index a0ead11dd..c7578292a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/module_builder/build_grid_modules.cpp @@ -140,6 +140,41 @@ void add_grid_module_nets_connect_pb_type_ports(ModuleManager& module_manager, } } +/******************************************************************** + * Add module nets between primitive module and its internal circuit module + * This is only applicable to the primitive module of a grid + *******************************************************************/ +static +void add_primitive_module_fpga_global_io_port(ModuleManager& module_manager, + const ModuleId& primitive_module, + const ModuleId& logic_module, + const size_t& logic_instance_id, + const ModuleManager::e_module_port_type& module_io_port_type, + const CircuitLibrary& circuit_lib, + const CircuitModelId& primitive_model, + const CircuitPortId& circuit_port) { + BasicPort module_port(generate_fpga_global_io_port_name(std::string(gio_inout_prefix), circuit_lib, primitive_model, circuit_port), circuit_lib.port_size(circuit_port)); + ModulePortId primitive_io_port_id = module_manager.add_port(primitive_module, module_port, module_io_port_type); + ModulePortId logic_io_port_id = module_manager.find_module_port(logic_module, circuit_lib.port_prefix(circuit_port)); + BasicPort logic_io_port = module_manager.module_port(logic_module, logic_io_port_id); + VTR_ASSERT(logic_io_port.get_width() == module_port.get_width()); + + /* Wire the GPIO port form primitive_module to the logic module!*/ + for (size_t pin_id = 0; pin_id < module_port.pins().size(); ++pin_id) { + ModuleNetId net = module_manager.create_module_net(primitive_module); + if ( (ModuleManager::MODULE_GPIO_PORT == module_io_port_type) + || (ModuleManager::MODULE_GPIN_PORT == module_io_port_type) ) { + module_manager.add_module_net_source(primitive_module, net, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]); + module_manager.add_module_net_sink(primitive_module, net, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]); + } else { + VTR_ASSERT(ModuleManager::MODULE_GPOUT_PORT == module_io_port_type); + module_manager.add_module_net_source(primitive_module, net, logic_module, logic_instance_id, logic_io_port_id, logic_io_port.pins()[pin_id]); + module_manager.add_module_net_sink(primitive_module, net, primitive_module, 0, primitive_io_port_id, module_port.pins()[pin_id]); + } + } +} + + /******************************************************************** * Print Verilog modules of a primitive node in the pb_graph_node graph * This generic function can support all the different types of primitive nodes @@ -274,18 +309,32 @@ void build_primitive_block_module(ModuleManager& module_manager, if (SPICE_MODEL_IOPAD == circuit_lib.model_type(primitive_model)) { std::vector primitive_model_inout_ports = circuit_lib.model_ports_by_type(primitive_model, SPICE_MODEL_PORT_INOUT); for (auto port : primitive_model_inout_ports) { - BasicPort module_port(generate_fpga_global_io_port_name(std::string(gio_inout_prefix), circuit_lib, primitive_model), circuit_lib.port_size(port)); - ModulePortId primitive_gpio_port_id = module_manager.add_port(primitive_module, module_port, ModuleManager::MODULE_GPIO_PORT); - ModulePortId logic_gpio_port_id = module_manager.find_module_port(logic_module, circuit_lib.port_prefix(port)); - BasicPort logic_gpio_port = module_manager.module_port(logic_module, logic_gpio_port_id); - VTR_ASSERT(logic_gpio_port.get_width() == module_port.get_width()); + add_primitive_module_fpga_global_io_port(module_manager, primitive_module, + logic_module, logic_instance_id, + ModuleManager::MODULE_GPIO_PORT, + circuit_lib, + primitive_model, + port); + } + } - /* Wire the GPIO port form primitive_module to the logic module!*/ - for (size_t pin_id = 0; pin_id < module_port.pins().size(); ++pin_id) { - ModuleNetId net = module_manager.create_module_net(primitive_module); - module_manager.add_module_net_source(primitive_module, net, primitive_module, 0, primitive_gpio_port_id, module_port.pins()[pin_id]); - module_manager.add_module_net_sink(primitive_module, net, logic_module, logic_instance_id, logic_gpio_port_id, logic_gpio_port.pins()[pin_id]); - } + /* Find the other i/o ports required by the primitive node, and add them to the module */ + for (const auto& port : circuit_lib.model_global_ports(primitive_model, false)) { + if ( (SPICE_MODEL_PORT_INPUT == circuit_lib.port_type(port)) + && (true == circuit_lib.port_is_io(port)) ) { + add_primitive_module_fpga_global_io_port(module_manager, primitive_module, + logic_module, logic_instance_id, + ModuleManager::MODULE_GPIN_PORT, + circuit_lib, + primitive_model, + port); + } else if (SPICE_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) { + add_primitive_module_fpga_global_io_port(module_manager, primitive_module, + logic_module, logic_instance_id, + ModuleManager::MODULE_GPOUT_PORT, + circuit_lib, + primitive_model, + port); } } } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp index 4d892f05f..19c7e59a4 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_writer_utils.cpp @@ -125,6 +125,8 @@ void print_verilog_module_definition(std::fstream& fp, /* port type2type mapping */ std::map port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT; @@ -184,6 +186,8 @@ void print_verilog_module_ports(std::fstream& fp, /* port type2type mapping */ std::map port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_INPUT; + port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_INPUT; + port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_OUTPUT; port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_INOUT; port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_INOUT; port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_INPUT; @@ -340,6 +344,8 @@ void print_verilog_module_instance(std::fstream& fp, /* port type2type mapping */ std::map port_type2type_map; port_type2type_map[ModuleManager::MODULE_GLOBAL_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_GPIN_PORT] = VERILOG_PORT_CONKT; + port_type2type_map[ModuleManager::MODULE_GPOUT_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_GPIO_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_INOUT_PORT] = VERILOG_PORT_CONKT; port_type2type_map[ModuleManager::MODULE_INPUT_PORT] = VERILOG_PORT_CONKT;