diff --git a/.travis/basic_reg_test.sh b/.travis/basic_reg_test.sh index f0782fec6..207953644 100755 --- a/.travis/basic_reg_test.sh +++ b/.travis/basic_reg_test.sh @@ -106,4 +106,7 @@ python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/tile_organization/top echo -e "Testing tiles with pins only on bottom and right sides"; python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/tile_organization/bottom_right_custom_pins --debug --show_thread_logs +echo -e "Testing global port definition from tiles"; +python3 openfpga_flow/scripts/run_fpga_task.py basic_tests/global_tile_ports/global_tile_clock --debug --show_thread_logs + end_section "OpenFPGA.TaskTun" diff --git a/docs/source/manual/arch_lang/annotate_vpr_arch.rst b/docs/source/manual/arch_lang/annotate_vpr_arch.rst index d990e3092..4010cb4fc 100644 --- a/docs/source/manual/arch_lang/annotate_vpr_arch.rst +++ b/docs/source/manual/arch_lang/annotate_vpr_arch.rst @@ -49,6 +49,43 @@ Similar to the Switch Boxes and Connection Blocks, the channel wire segments in - ``circuit_model_name=""`` should match a circuit model whose type is ``chan_wire`` defined in :ref:`circuit_library`. +Physical Tile Annotation +~~~~~~~~~~~~~~~~~~~~~~~~ + +Original VPR architecture description contains ```` XML nodes to define physical tile pins. +OpenFPGA allows users to define pin/port of physical tiles as global ports. + +Here is an example: + +.. code-block:: xml + + + + + +- ``name=""`` is the port name to appear in the top-level FPGA fabric. + +- ``tile_port=""`` is the port name of a physical tile, e.g., ``tile_port="clb.clk"``. + +.. note:: The port of physical tile must be a valid port of the physical definition in VPR architecture! + +.. note:: The linked port of physical tile must meet the following requirements: + + - If the ``global_port`` is set as clock through ``is_clock="true"``, the port of the physical tile must also be a clock port. + - If not a clock, the port of the physical tile must be defined as non-clock global + - The port of the physical tile should have zero connectivity (``Fc=0``) in VPR architecture + +- ``is_clock=""`` define if the global port is a clock port at the top-level FPGA fabric. An operating clock port will be driven by proper signals in auto-generated testbenches. + +- ``is_reset=""`` define if the global port is a reset port at the top-level FPGA fabric. An operating reset port will be driven by proper signals in testbenches. + +- ``is_set=""`` define if the global port is a set port at the top-level FPGA fabric. An operating set port will be driven by proper signals in testbenches. + +.. note:: A port can only be defined as ``clock`` or ``set`` or ``reset``. + +.. note:: All the global port from a physical tile port is only used in operating phase. Any ports for programmable use are not allowed! + + Primitive Blocks inside Multi-mode Configurable Logic Blocks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/libopenfpga/libarchopenfpga/src/openfpga_arch.h b/libopenfpga/libarchopenfpga/src/openfpga_arch.h index 68d0b6f68..38d920c6e 100644 --- a/libopenfpga/libarchopenfpga/src/openfpga_arch.h +++ b/libopenfpga/libarchopenfpga/src/openfpga_arch.h @@ -9,6 +9,7 @@ #include "simulation_setting.h" #include "config_protocol.h" #include "arch_direct.h" +#include "tile_annotation.h" #include "pb_type_annotation.h" /* namespace openfpga begins */ @@ -51,6 +52,11 @@ struct Arch { */ ArchDirect arch_direct; + /* Physical tile annotations: + * Global port definition for tile ports + */ + TileAnnotation tile_annotations; + /* Pb type annotations * Bind from operating to physical * Bind from physical to circuit model diff --git a/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp b/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp index e8ce6aeab..bbeb893c0 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp @@ -21,6 +21,7 @@ #include "read_xml_simulation_setting.h" #include "read_xml_config_protocol.h" #include "read_xml_routing_circuit.h" +#include "read_xml_tile_annotation.h" #include "read_xml_pb_type_annotation.h" #include "read_xml_openfpga_arch.h" #include "openfpga_arch_linker.h" @@ -103,6 +104,9 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) { openfpga_arch.arch_direct = read_xml_direct_circuit(xml_openfpga_arch, loc_data, openfpga_arch.circuit_lib); + /* Parse the pb_type annotation */ + openfpga_arch.tile_annotations = read_xml_tile_annotations(xml_openfpga_arch, loc_data); + /* Parse the pb_type annotation */ openfpga_arch.pb_type_annotations = read_xml_pb_type_annotations(xml_openfpga_arch, loc_data); diff --git a/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp b/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp new file mode 100644 index 000000000..692cd2288 --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp @@ -0,0 +1,107 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML modeling OpenFPGA architecture to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "read_xml_util.h" + +/* Headers from libopenfpgautil */ +#include "openfpga_tokenizer.h" +#include "openfpga_port_parser.h" + +#include "read_xml_tile_annotation.h" + +/******************************************************************** + * Parse XML description for an interconnection annotation + * under a XML node + *******************************************************************/ +static +void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, + const pugiutil::loc_data& loc_data, + openfpga::TileAnnotation& tile_annotation) { + /* We have two mandatory XML attributes + * 1. name of the port + * 2. name of the tile and ports in the format of . + */ + const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string(); + const std::string& tile_port_name_attr = get_attribute(xml_tile, "tile_port", loc_data).as_string(); + + /* Extract the tile name */ + openfpga::StringToken tokenizer(tile_port_name_attr); + std::vector tile_port_tokens = tokenizer.split('.'); + if (2 != tile_port_tokens.size()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), + "Invalid tile_port attribute '%s'! Valid format is .\n", + tile_port_name_attr.c_str()); + } + /* Extract the tile port information */ + openfpga::PortParser tile_port_parser(tile_port_tokens[1]); + + TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr, tile_port_tokens[0], tile_port_parser.port()); + + /* Report any duplicated port names */ + if (TileGlobalPortId::INVALID() == tile_global_port_id) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), + "Invalid port name '%s' which is defined more than once in the global port list!\n", + name_attr.c_str()); + } + + /* Get is_clock attributes */ + tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + + /* Get is_set attributes */ + tile_annotation.set_global_port_is_set(tile_global_port_id, get_attribute(xml_tile, "is_set", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + + /* Get is_reset attributes */ + tile_annotation.set_global_port_is_reset(tile_global_port_id, get_attribute(xml_tile, "is_reset", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); + + /* Get default_value attributes */ + tile_annotation.set_global_port_default_value(tile_global_port_id, get_attribute(xml_tile, "default_value", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0)); + + /* Ensure valid port attributes */ + if (false == tile_annotation.valid_global_port_attributes(tile_global_port_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), + "Invalid port attributes for '%s'! A port can only be clock or set or reset.\n", + name_attr.c_str()); + } +} + +/******************************************************************** + * Top function to parse XML description about tile annotation + *******************************************************************/ +openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data) { + openfpga::TileAnnotation tile_annotations; + + /* Parse configuration protocol root node */ + pugi::xml_node xml_annotations = get_single_child(Node, "tile_annotations", loc_data, pugiutil::ReqOpt::OPTIONAL); + + /* Not found, we can return */ + if (!xml_annotations) { + return tile_annotations; + } + + /* Iterate over the children under this node, + * each child should be named after + */ + for (pugi::xml_node xml_tile_global_port : xml_annotations.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_tile_global_port.name() != std::string("global_port")) { + bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"}); + } + read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, tile_annotations); + } + + return tile_annotations; +} diff --git a/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.h b/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.h new file mode 100644 index 000000000..0c32684e8 --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.h @@ -0,0 +1,17 @@ +#ifndef READ_XML_TILE_ANNOTATION_H +#define READ_XML_TILE_ANNOTATION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "pugixml_util.hpp" +#include "pugixml.hpp" +#include "tile_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data); + +#endif diff --git a/libopenfpga/libarchopenfpga/src/tile_annotation.cpp b/libopenfpga/libarchopenfpga/src/tile_annotation.cpp new file mode 100644 index 000000000..5bef68a31 --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/tile_annotation.cpp @@ -0,0 +1,144 @@ +/************************************************************************ + * Member functions for class TileAnnotation + ***********************************************************************/ +#include "vtr_assert.h" + +#include "tile_annotation.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +TileAnnotation::TileAnnotation() { + return; +} + +/************************************************************************ + * Public Accessors : aggregates + ***********************************************************************/ +TileAnnotation::global_port_range TileAnnotation::global_ports() const { + return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end()); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_names_[global_port_id]; +} + +std::string TileAnnotation::global_port_tile_name(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_tile_names_[global_port_id]; +} + +BasicPort TileAnnotation::global_port_tile_port(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_tile_ports_[global_port_id]; +} + +bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_clock_[global_port_id]; +} + +bool TileAnnotation::global_port_is_set(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_set_[global_port_id]; +} + +bool TileAnnotation::global_port_is_reset(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_reset_[global_port_id]; +} + +size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_default_values_[global_port_id]; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name, + const std::string& tile_name, + const BasicPort& tile_port) { + /* Ensure that the name is unique */ + std::map::iterator it = global_port_name2ids_.find(port_name); + if (it != global_port_name2ids_.end()) { + return TileGlobalPortId::INVALID(); + } + + /* This is a legal name. we can create a new id */ + TileGlobalPortId port_id = TileGlobalPortId(global_port_ids_.size()); + global_port_ids_.push_back(port_id); + global_port_names_.push_back(port_name); + global_port_tile_names_.push_back(tile_name); + global_port_tile_ports_.push_back(tile_port); + global_port_is_clock_.push_back(false); + global_port_is_set_.push_back(false); + global_port_is_reset_.push_back(false); + global_port_default_values_.push_back(0); + + /* Register in the name-to-id map */ + global_port_name2ids_[port_name] = port_id; + + return port_id; +} + +void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id, + const bool& is_clock) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_clock_[global_port_id] = is_clock; +} + +void TileAnnotation::set_global_port_is_set(const TileGlobalPortId& global_port_id, + const bool& is_set) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_set_[global_port_id] = is_set; +} + +void TileAnnotation::set_global_port_is_reset(const TileGlobalPortId& global_port_id, + const bool& is_reset) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_reset_[global_port_id] = is_reset; +} + +void TileAnnotation::set_global_port_default_value(const TileGlobalPortId& global_port_id, + const size_t& default_value) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_default_values_[global_port_id] = default_value; +} + +/************************************************************************ + * Internal invalidators/validators + ***********************************************************************/ +/* Validators */ +bool TileAnnotation::valid_global_port_id(const TileGlobalPortId& global_port_id) const { + return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] ); +} + +bool TileAnnotation::valid_global_port_attributes(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + + int attribute_counter = 0; + + if (true == global_port_is_clock_[global_port_id]) { + attribute_counter++; + } + + if (true == global_port_is_reset_[global_port_id]) { + attribute_counter++; + } + + if (true == global_port_is_set_[global_port_id]) { + attribute_counter++; + } + + return ((0 == attribute_counter) || (1 == attribute_counter)); +} + +} /* namespace openfpga ends */ diff --git a/libopenfpga/libarchopenfpga/src/tile_annotation.h b/libopenfpga/libarchopenfpga/src/tile_annotation.h new file mode 100644 index 000000000..b87ceb74a --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/tile_annotation.h @@ -0,0 +1,86 @@ +#ifndef TILE_ANNOTATION_H +#define TILE_ANNOTATION_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include +#include +#include + +#include "vtr_vector.h" + +#include "openfpga_port.h" + +#include "tile_annotation_fwd.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/******************************************************************** + * This file include the declaration of data structures + * to store physical tile annotation, including + * 1. global port definition where a tile port can be treated as a + * global port of the FPGA fabric + * + * Note: + * 1. Keep this data structure as general as possible. It is supposed + * to contain the raw data from architecture XML! If you want to link + * to other data structures, please create another one in other header files + *******************************************************************/ +class TileAnnotation { + public: /* Types */ + typedef vtr::vector::const_iterator global_port_iterator; + /* Create range */ + typedef vtr::Range global_port_range; + public: /* Constructor */ + TileAnnotation(); + public: /* Public accessors: aggregators */ + global_port_range global_ports() const; + public: /* Public accessors */ + std::string global_port_name(const TileGlobalPortId& global_port_id) const; + std::string global_port_tile_name(const TileGlobalPortId& global_port_id) const; + BasicPort global_port_tile_port(const TileGlobalPortId& global_port_id) const; + bool global_port_is_clock(const TileGlobalPortId& global_port_id) const; + bool global_port_is_set(const TileGlobalPortId& global_port_id) const; + bool global_port_is_reset(const TileGlobalPortId& global_port_id) const; + size_t global_port_default_value(const TileGlobalPortId& global_port_id) const; + public: /* Public mutators */ + /* By default, we do not set it as a clock. + * Users should set it through the set_global_port_is_clock() function + */ + TileGlobalPortId create_global_port(const std::string& port_name, + const std::string& tile_name, + const BasicPort& tile_port); + void set_global_port_is_clock(const TileGlobalPortId& global_port_id, + const bool& is_clock); + void set_global_port_is_set(const TileGlobalPortId& global_port_id, + const bool& is_set); + void set_global_port_is_reset(const TileGlobalPortId& global_port_id, + const bool& is_reset); + void set_global_port_default_value(const TileGlobalPortId& global_port_id, + const size_t& default_value); + public: /* Public validator */ + bool valid_global_port_id(const TileGlobalPortId& global_port_id) const; + /* Validate attributes of a given global port + * - A port can only be defined as clock or set or reset + */ + bool valid_global_port_attributes(const TileGlobalPortId& global_port_id) const; + private: /* Internal data */ + /* Global port information for tiles */ + vtr::vector global_port_ids_; + vtr::vector global_port_names_; + vtr::vector global_port_tile_names_; + vtr::vector global_port_tile_ports_; + vtr::vector global_port_is_clock_; + vtr::vector global_port_is_reset_; + vtr::vector global_port_is_set_; + vtr::vector global_port_default_values_; + + /* A fast lookup for port names */ + std::map global_port_name2ids_; +}; + +} /* namespace openfpga ends */ + +#endif diff --git a/libopenfpga/libarchopenfpga/src/tile_annotation_fwd.h b/libopenfpga/libarchopenfpga/src/tile_annotation_fwd.h new file mode 100644 index 000000000..742b0ed52 --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/tile_annotation_fwd.h @@ -0,0 +1,22 @@ +/************************************************************************ + * A header file for TileAnnotation class, including critical data declaration + * Please include this file only for using any TileAnnotation data structure + * Refer to tile_annotation.h for more details + ***********************************************************************/ + +/************************************************************************ + * Create strong id for tile global ports to avoid illegal type casting + ***********************************************************************/ +#ifndef TILE_ANNOTATION_FWD_H +#define TILE_ANNOTATION_FWD_H + +#include "vtr_strong_id.h" + +struct tile_global_port_id_tag; + +typedef vtr::StrongId TileGlobalPortId; + +/* Short declaration of class */ +class TileAnnotation; + +#endif diff --git a/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp b/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp index 2c5134d4e..f64e1970e 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp @@ -16,6 +16,7 @@ #include "write_xml_simulation_setting.h" #include "write_xml_config_protocol.h" #include "write_xml_routing_circuit.h" +#include "write_xml_tile_annotation.h" #include "write_xml_pb_type_annotation.h" #include "write_xml_openfpga_arch.h" @@ -59,7 +60,10 @@ void write_xml_openfpga_arch(const char* fname, write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.arch_direct); /* Write the pb_type annotations */ - openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch. pb_type_annotations); + openfpga::write_xml_tile_annotations(fp, fname, openfpga_arch.tile_annotations); + + /* Write the pb_type annotations */ + openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch.pb_type_annotations); fp << "" << "\n"; diff --git a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp index 2bc512d85..e9b36522c 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_pb_type_annotation.cpp @@ -66,6 +66,7 @@ std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_ } /******************************************************************** + * FIXME: Use a common function to output ports * Generate the full hierarchy name for a operating pb_type *******************************************************************/ static diff --git a/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp b/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp new file mode 100644 index 000000000..a3214d4df --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp @@ -0,0 +1,94 @@ +/******************************************************************** + * This file includes functions that outputs tile annotations to XML format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "openfpga_digest.h" + +/* Headers from readarchopenfpga library */ +#include "write_xml_utils.h" +#include "write_xml_tile_annotation.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/******************************************************************** + * FIXME: Use a common function to output ports + * Generate the full hierarchy name for a operating pb_type + *******************************************************************/ +static +std::string generate_tile_port_name(const BasicPort& pb_port) { + std::string port_name; + + /* Output format: [:] */ + port_name += pb_port.get_name(); + port_name += std::string("["); + port_name += std::to_string(pb_port.get_lsb()); + port_name += std::string(":"); + port_name += std::to_string(pb_port.get_msb()); + port_name += std::string("]"); + + return port_name; +} + +/******************************************************************** + * A writer to output a device variation in a technology library to XML format + *******************************************************************/ +static +void write_xml_tile_annotation_global_port(std::fstream& fp, + const char* fname, + const openfpga::TileAnnotation& tile_annotation, + const TileGlobalPortId& global_port_id) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + fp << "\t\t" << "" << "\n"; +} + +/******************************************************************** + * A writer to output tile annotations to XML format + *******************************************************************/ +void write_xml_tile_annotations(std::fstream& fp, + const char* fname, + const TileAnnotation& tile_annotation) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node for pb_type annotations, + * we apply a tab becuase pb_type annotations is just a subnode + * under the root node + */ + fp << "\t" << "" << "\n"; + + /* Write device model one by one */ + for (const TileGlobalPortId& global_port_id : tile_annotation.global_ports()) { + write_xml_tile_annotation_global_port(fp, fname, tile_annotation, global_port_id); + } + + /* Write the root node for pb_type annotations */ + fp << "\t" << "" << "\n"; +} + +} /* namespace openfpga ends */ diff --git a/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.h b/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.h new file mode 100644 index 000000000..e50536a42 --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.h @@ -0,0 +1,22 @@ +#ifndef WRITE_XML_TILE_ANNOTATION_H +#define WRITE_XML_TILE_ANNOTATION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "tile_annotation.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +/* namespace openfpga begins */ +namespace openfpga { + +void write_xml_tile_annotations(std::fstream& fp, + const char* fname, + const TileAnnotation& tile_annotation); + +} /* namespace openfpga ends */ + +#endif diff --git a/openfpga/src/base/openfpga_build_fabric.cpp b/openfpga/src/base/openfpga_build_fabric.cpp index b5793cdb6..08e9ef4f8 100644 --- a/openfpga/src/base/openfpga_build_fabric.cpp +++ b/openfpga/src/base/openfpga_build_fabric.cpp @@ -17,6 +17,7 @@ #include "fabric_hierarchy_writer.h" #include "fabric_key_writer.h" #include "build_fabric_io_location_map.h" +#include "build_fabric_global_port_info.h" #include "openfpga_build_fabric.h" /* Include global variables of VPR */ @@ -120,6 +121,11 @@ int build_fabric(OpenfpgaContext& openfpga_ctx, openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map(openfpga_ctx.module_graph(), g_vpr_ctx.device().grid); + /* Build fabric global port information */ + openfpga_ctx.mutable_fabric_global_port_info() = build_fabric_global_port_info(openfpga_ctx.module_graph(), + openfpga_ctx.arch().tile_annotations, + openfpga_ctx.arch().circuit_lib); + /* Output fabric key if user requested */ if (true == cmd_context.option_enable(cmd, opt_write_fabric_key)) { std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key); diff --git a/openfpga/src/base/openfpga_context.h b/openfpga/src/base/openfpga_context.h index 47427a452..c59219ed2 100644 --- a/openfpga/src/base/openfpga_context.h +++ b/openfpga/src/base/openfpga_context.h @@ -19,6 +19,7 @@ #include "fabric_bitstream.h" #include "device_rr_gsb.h" #include "io_location_map.h" +#include "fabric_global_port_info.h" /******************************************************************** * This file includes the declaration of the date structure @@ -65,6 +66,7 @@ class OpenfpgaContext : public Context { const openfpga::BitstreamManager& bitstream_manager() const { return bitstream_manager_; } const openfpga::FabricBitstream& fabric_bitstream() const { return fabric_bitstream_; } const openfpga::IoLocationMap& io_location_map() const { return io_location_map_; } + const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const { return fabric_global_port_info_; } const std::unordered_map& net_activity() const { return net_activity_; } const openfpga::NetlistManager& verilog_netlists() const { return verilog_netlists_; } const openfpga::NetlistManager& spice_netlists() const { return spice_netlists_; } @@ -85,6 +87,7 @@ class OpenfpgaContext : public Context { openfpga::BitstreamManager& mutable_bitstream_manager() { return bitstream_manager_; } openfpga::FabricBitstream& mutable_fabric_bitstream() { return fabric_bitstream_; } openfpga::IoLocationMap& mutable_io_location_map() { return io_location_map_; } + openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() { return fabric_global_port_info_; } std::unordered_map& mutable_net_activity() { return net_activity_; } openfpga::NetlistManager& mutable_verilog_netlists() { return verilog_netlists_; } openfpga::NetlistManager& mutable_spice_netlists() { return spice_netlists_; } @@ -123,6 +126,7 @@ class OpenfpgaContext : public Context { /* Fabric module graph */ openfpga::ModuleManager module_graph_; openfpga::IoLocationMap io_location_map_; + openfpga::FabricGlobalPortInfo fabric_global_port_info_; /* Bitstream database */ openfpga::BitstreamManager bitstream_manager_; diff --git a/openfpga/src/base/openfpga_pb_pin_fixup.cpp b/openfpga/src/base/openfpga_pb_pin_fixup.cpp index 17c48fb5b..944a85c70 100644 --- a/openfpga/src/base/openfpga_pb_pin_fixup.cpp +++ b/openfpga/src/base/openfpga_pb_pin_fixup.cpp @@ -17,6 +17,7 @@ #include "openfpga_side_manager.h" #include "pb_type_utils.h" +#include "openfpga_physical_tile_utils.h" #include "openfpga_pb_pin_fixup.h" /* Include global variables of VPR */ @@ -25,28 +26,6 @@ /* begin namespace openfpga */ namespace openfpga { -/******************************************************************** - * Give a given pin index, find the side where this pin is located - * on the physical tile - * Note: - * - Need to check if the pin_width_offset and pin_height_offset - * are properly set in VPR!!! - *******************************************************************/ -static -std::vector find_logic_tile_pin_side(t_physical_tile_type_ptr physical_tile, - const int& physical_pin) { - std::vector pin_sides; - for (const e_side& side_cand : {TOP, RIGHT, BOTTOM, LEFT}) { - int pin_width_offset = physical_tile->pin_width_offset[physical_pin]; - int pin_height_offset = physical_tile->pin_height_offset[physical_pin]; - if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset][side_cand][physical_pin]) { - pin_sides.push_back(side_cand); - } - } - - return pin_sides; -} - /******************************************************************** * Fix up the pb pin mapping results for a given clustered block * 1. For each input/output pin of a clustered pb, @@ -86,7 +65,7 @@ void update_cluster_pin_with_post_routing_results(const DeviceContext& device_ct VTR_ASSERT(class_inf.type == RECEIVER); rr_node_type = IPIN; } - std::vector pin_sides = find_logic_tile_pin_side(physical_tile, physical_pin); + std::vector pin_sides = find_physical_tile_pin_side(physical_tile, physical_pin, border_side); /* As some grid has height/width offset, we may not have the pin on any side */ if (0 == pin_sides.size()) { continue; diff --git a/openfpga/src/base/openfpga_read_arch.cpp b/openfpga/src/base/openfpga_read_arch.cpp index ce7aed6ba..1e58ec373 100644 --- a/openfpga/src/base/openfpga_read_arch.cpp +++ b/openfpga/src/base/openfpga_read_arch.cpp @@ -12,10 +12,14 @@ #include "read_xml_openfpga_arch.h" #include "check_circuit_library.h" #include "circuit_library_utils.h" +#include "check_tile_annotation.h" #include "write_xml_openfpga_arch.h" #include "openfpga_read_arch.h" +/* Include global variables of VPR */ +#include "globals.h" + /* begin namespace openfpga */ namespace openfpga { @@ -44,8 +48,9 @@ int read_arch(OpenfpgaContext& openfpga_context, /* Check the architecture: * 1. Circuit library - * 2. Technology library (TODO) - * 3. Simulation settings (TODO) + * 2. Tile annotation + * 3. Technology library (TODO) + * 4. Simulation settings (TODO) */ if (false == check_circuit_library(openfpga_context.arch().circuit_lib)) { return CMD_EXEC_FATAL_ERROR; @@ -57,6 +62,12 @@ int read_arch(OpenfpgaContext& openfpga_context, return CMD_EXEC_FATAL_ERROR; } + if (false == check_tile_annotation(openfpga_context.arch().tile_annotations, + openfpga_context.arch().circuit_lib, + g_vpr_ctx.device().physical_tile_types)) { + return CMD_EXEC_FATAL_ERROR; + } + return CMD_EXEC_SUCCESS; } diff --git a/openfpga/src/base/openfpga_sdc.cpp b/openfpga/src/base/openfpga_sdc.cpp index 9bcbc26df..f82e0656f 100644 --- a/openfpga/src/base/openfpga_sdc.cpp +++ b/openfpga/src/base/openfpga_sdc.cpp @@ -80,11 +80,6 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, options.set_generate_sdc_pnr(true); } - /* Collect global ports from the circuit library: - * TODO: should we place this in the OpenFPGA context? - */ - std::vector global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib); - /* Execute only when sdc is enabled */ if (true == options.generate_sdc_pnr()) { print_pnr_sdc(options, @@ -96,7 +91,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx, openfpga_ctx.module_graph(), openfpga_ctx.mux_lib(), openfpga_ctx.arch().circuit_lib, - global_ports, + openfpga_ctx.fabric_global_port_info(), openfpga_ctx.flow_manager().compress_routing()); } @@ -193,17 +188,11 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx, options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit))); } - /* Collect global ports from the circuit library: - * TODO: should we place this in the OpenFPGA context? - */ - std::vector global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib); - if (true == options.generate_sdc_analysis()) { print_analysis_sdc(options, 1./openfpga_ctx.simulation_setting().operating_clock_frequency(), g_vpr_ctx, openfpga_ctx, - global_ports, openfpga_ctx.flow_manager().compress_routing()); } diff --git a/openfpga/src/base/openfpga_verilog.cpp b/openfpga/src/base/openfpga_verilog.cpp index 69c0b60d4..efa77aaf7 100644 --- a/openfpga/src/base/openfpga_verilog.cpp +++ b/openfpga/src/base/openfpga_verilog.cpp @@ -96,6 +96,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx, g_vpr_ctx.atom(), g_vpr_ctx.placement(), openfpga_ctx.io_location_map(), + openfpga_ctx.fabric_global_port_info(), openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib, openfpga_ctx.simulation_setting(), diff --git a/openfpga/src/fabric/build_device_module.cpp b/openfpga/src/fabric/build_device_module.cpp index 3b54b28a9..0df7c4aa7 100644 --- a/openfpga/src/fabric/build_device_module.cpp +++ b/openfpga/src/fabric/build_device_module.cpp @@ -114,6 +114,7 @@ int build_device_module_graph(ModuleManager& module_manager, decoder_lib, openfpga_ctx.arch().circuit_lib, vpr_device_ctx.grid, + openfpga_ctx.arch().tile_annotations, vpr_device_ctx.rr_graph, openfpga_ctx.device_rr_gsb(), openfpga_ctx.tile_direct(), diff --git a/openfpga/src/fabric/build_fabric_global_port_info.cpp b/openfpga/src/fabric/build_fabric_global_port_info.cpp new file mode 100644 index 000000000..44a09d199 --- /dev/null +++ b/openfpga/src/fabric/build_fabric_global_port_info.cpp @@ -0,0 +1,90 @@ +/******************************************************************** + * This file includes functions that are used to build the global port + * information for the top-level module of the FPGA fabric + * It helps OpenFPGA to build testbenches with the attributes of the global ports + *******************************************************************/ +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_time.h" +#include "vtr_log.h" + +#include "openfpga_naming.h" + +#include "circuit_library_utils.h" +#include "build_fabric_global_port_info.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Find all the GPIO ports in the grid module + * and cache their port/pin index in the top-level module + *******************************************************************/ +FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager, + const TileAnnotation& tile_annotation, + const CircuitLibrary& circuit_lib) { + vtr::ScopedStartFinishTimer timer("Create global port info for top module"); + + FabricGlobalPortInfo fabric_global_port_info; + + /* Find top-level module */ + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = module_manager.find_module(top_module_name); + if (true != module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR("Unable to find the top-level module '%s'!\n", + top_module_name.c_str()); + exit(1); + } + + /* Add the global ports from circuit library */ + for (const CircuitPortId& global_port : find_circuit_library_global_ports(circuit_lib)) { + /* We should find a port in the top module */ + ModulePortId module_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(global_port)); + /* Only add those ports have been defined in top-level module */ + if (false == module_manager.valid_module_port_id(top_module, module_port)) { + continue; + } + /* Add the port information */ + FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port); + fabric_global_port_info.set_global_port_is_clock(fabric_port, CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)); + fabric_global_port_info.set_global_port_is_reset(fabric_port, circuit_lib.port_is_reset(global_port)); + fabric_global_port_info.set_global_port_is_set(fabric_port, circuit_lib.port_is_set(global_port)); + fabric_global_port_info.set_global_port_is_prog(fabric_port, circuit_lib.port_is_prog(global_port)); + fabric_global_port_info.set_global_port_is_config_enable(fabric_port, circuit_lib.port_is_config_enable(global_port)); + fabric_global_port_info.set_global_port_default_value(fabric_port, circuit_lib.port_default_value(global_port)); + } + + /* Add the global ports from tile annotation */ + for (const TileGlobalPortId& global_port : tile_annotation.global_ports()) { + /* We should find a port in the top module */ + ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(global_port)); + /* Only add those ports have been defined in top-level module */ + if (false == module_manager.valid_module_port_id(top_module, module_port)) { + continue; + } + /* Avoid adding redundant ports */ + bool already_in_list = false; + for (const FabricGlobalPortId& port : fabric_global_port_info.global_ports()) { + if (module_port == fabric_global_port_info.global_module_port(port)) { + already_in_list = true; + break; + } + } + if (true == already_in_list) { + continue; + } + /* Add the port information */ + FabricGlobalPortId fabric_port = fabric_global_port_info.create_global_port(module_port); + fabric_global_port_info.set_global_port_is_clock(fabric_port, tile_annotation.global_port_is_clock(global_port)); + fabric_global_port_info.set_global_port_is_reset(fabric_port, tile_annotation.global_port_is_reset(global_port)); + fabric_global_port_info.set_global_port_is_set(fabric_port, tile_annotation.global_port_is_set(global_port)); + fabric_global_port_info.set_global_port_default_value(fabric_port, tile_annotation.global_port_default_value(global_port)); + } + + return fabric_global_port_info; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_fabric_global_port_info.h b/openfpga/src/fabric/build_fabric_global_port_info.h new file mode 100644 index 000000000..5625d379f --- /dev/null +++ b/openfpga/src/fabric/build_fabric_global_port_info.h @@ -0,0 +1,27 @@ +#ifndef BUILD_FABRIC_GLOBAL_PORT_INFO_H +#define BUILD_FABRIC_GLOBAL_PORT_INFO_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ + +#include +#include "tile_annotation.h" +#include "circuit_library.h" +#include "fabric_global_port_info.h" +#include "module_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +FabricGlobalPortInfo build_fabric_global_port_info(const ModuleManager& module_manager, + const TileAnnotation& tile_annotation, + const CircuitLibrary& circuit_lib); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fabric/build_top_module.cpp b/openfpga/src/fabric/build_top_module.cpp index ef45bb4bc..80d6e768c 100644 --- a/openfpga/src/fabric/build_top_module.cpp +++ b/openfpga/src/fabric/build_top_module.cpp @@ -287,6 +287,7 @@ int build_top_module(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, const DeviceGrid& grids, + const TileAnnotation& tile_annotation, const RRGraph& rr_graph, const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, @@ -345,6 +346,12 @@ int build_top_module(ModuleManager& module_manager, */ add_module_global_ports_from_child_modules(module_manager, top_module); + /* Add global ports from grid ports that are defined as global in tile annotation */ + status = add_top_module_global_ports_from_grid_modules(module_manager, top_module, tile_annotation, grids, grid_instance_ids); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + /* Add GPIO ports from the sub-modules under this Verilog module * This is a much easier job after adding sub modules (instances), * we just need to find all the I/O ports from the child modules and build a list of it diff --git a/openfpga/src/fabric/build_top_module.h b/openfpga/src/fabric/build_top_module.h index a12250c07..1905a3b1b 100644 --- a/openfpga/src/fabric/build_top_module.h +++ b/openfpga/src/fabric/build_top_module.h @@ -8,6 +8,7 @@ #include #include "vtr_geometry.h" #include "device_grid.h" +#include "tile_annotation.h" #include "rr_graph_obj.h" #include "device_rr_gsb.h" #include "circuit_library.h" @@ -29,6 +30,7 @@ int build_top_module(ModuleManager& module_manager, DecoderLibrary& decoder_lib, const CircuitLibrary& circuit_lib, const DeviceGrid& grids, + const TileAnnotation& tile_annotation, const RRGraph& rr_graph, const DeviceRRGSB& device_rr_gsb, const TileDirect& tile_direct, diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 060639136..8843f5210 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -6,14 +6,21 @@ #include "vtr_assert.h" #include "vtr_time.h" +/* Headers from openfpgashell library */ +#include "command_exit_codes.h" + /* Headers from openfpgautil library */ #include "openfpga_side_manager.h" +/* Headers from vpr library */ +#include "vpr_utils.h" + #include "openfpga_reserved_words.h" #include "openfpga_naming.h" #include "pb_type_utils.h" #include "rr_gsb_utils.h" #include "openfpga_physical_tile_utils.h" +#include "openfpga_device_grid_utils.h" #include "module_manager_utils.h" #include "build_top_module_utils.h" @@ -683,4 +690,166 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager, } } +/******************************************************************** + * Add global port connection for a given port of a physical tile + * that are defined as global in tile annotation + *******************************************************************/ +static +void build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager, + const ModuleId& top_module, + const ModulePortId& top_module_port, + const TileAnnotation& tile_annotation, + const TileGlobalPortId& tile_global_port, + const DeviceGrid& grids, + const vtr::Point& grid_coordinate, + const e_side& border_side, + const vtr::Matrix& grid_instance_ids) { + + t_physical_tile_type_ptr physical_tile = grids[grid_coordinate.x()][grid_coordinate.y()].type; + /* Ensure physical tile matches the global port definition */ + VTR_ASSERT(std::string(physical_tile->name) == tile_annotation.global_port_tile_name(tile_global_port)); + + /* Find the port of the grid module according to the tile annotation */ + int grid_pin_index = physical_tile->num_pins; + for (const t_physical_tile_port& tile_port : physical_tile->ports) { + if (std::string(tile_port.name) == tile_annotation.global_port_tile_port(tile_global_port).get_name()) { + /* Port size must match!!! */ + VTR_ASSERT(size_t(tile_port.num_pins) == tile_annotation.global_port_tile_port(tile_global_port).get_width()); + /* TODO: Should check there is only port matching!!! */ + grid_pin_index = tile_port.absolute_first_pin_index; + break; + } + } + /* Ensure the pin index is valid */ + VTR_ASSERT(grid_pin_index < physical_tile->num_pins); + + /* Find the module name for this type of grid */ + std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX); + std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(physical_tile->name), is_io_type(physical_tile), border_side); + ModuleId grid_module = module_manager.find_module(grid_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(grid_module)); + size_t grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()]; + + /* Find the module pin */ + size_t grid_pin_width = physical_tile->pin_width_offset[grid_pin_index]; + size_t grid_pin_height = physical_tile->pin_height_offset[grid_pin_index]; + std::vector pin_sides = find_physical_tile_pin_side(physical_tile, grid_pin_index, border_side); + for (const e_side& pin_side : pin_sides) { + std::string grid_port_name = generate_grid_port_name(grid_coordinate, + grid_pin_width, grid_pin_height, + pin_side, + grid_pin_index, false); + ModulePortId grid_port_id = module_manager.find_module_port(grid_module, grid_port_name); + VTR_ASSERT(true == module_manager.valid_module_port_id(grid_module, grid_port_id)); + + /* Build nets */ + add_module_bus_nets(module_manager, top_module, + top_module, 0, top_module_port, + grid_module, grid_instance, grid_port_id); + } +} + +/******************************************************************** + * Add global ports from grid ports that are defined as global in tile annotation + *******************************************************************/ +int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, + const ModuleId& top_module, + const TileAnnotation& tile_annotation, + const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids) { + + /* Add the global ports which are yet added to the top-level module + * (in different names than the global ports defined in circuit library + */ + std::vector global_ports_to_add; + for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { + ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); + if (ModulePortId::INVALID() == module_port) { + BasicPort global_port_to_add; + global_port_to_add.set_name(tile_annotation.global_port_name(tile_global_port)); + global_port_to_add.set_width(tile_annotation.global_port_tile_port(tile_global_port).get_width()); + global_ports_to_add.push_back(global_port_to_add); + } + } + + for (const BasicPort& global_port_to_add : global_ports_to_add) { + module_manager.add_port(top_module, global_port_to_add, ModuleManager::MODULE_GLOBAL_PORT); + } + + /* Add module nets */ + std::map>> io_coordinates = generate_perimeter_grid_coordinates( grids); + + for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { + /* Must found one valid port! */ + ModulePortId top_module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); + VTR_ASSERT(ModulePortId::INVALID() != top_module_port); + + /* Spot the port from child modules from core grids */ + for (size_t ix = 1; ix < grids.width() - 1; ++ix) { + for (size_t iy = 1; iy < grids.height() - 1; ++iy) { + /* Bypass EMPTY tiles */ + if (true == is_empty_type(grids[ix][iy].type)) { + continue; + } + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ( (0 < grids[ix][iy].width_offset) + || (0 < grids[ix][iy].height_offset)) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string(grids[ix][iy].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) { + continue; + } + + /* Create nets and finish connection build-up */ + build_top_module_global_net_for_given_grid_module(module_manager, + top_module, + top_module_port, + tile_annotation, + tile_global_port, + grids, + vtr::Point(ix, iy), + NUM_SIDES, + grid_instance_ids); + + } + } + + /* Walk through all the grids on the perimeter, which are I/O grids */ + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coordinate : io_coordinates[io_side]) { + /* Bypass EMPTY grid */ + if (true == is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { + continue; + } + + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ( (0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) + || (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) { + continue; + } + + /* Create nets and finish connection build-up */ + build_top_module_global_net_for_given_grid_module(module_manager, + top_module, + top_module_port, + tile_annotation, + tile_global_port, + grids, + io_coordinate, + io_side, + grid_instance_ids); + } + } + } + + return CMD_EXEC_SUCCESS; +} + } /* end namespace openfpga */ diff --git a/openfpga/src/fabric/build_top_module_connection.h b/openfpga/src/fabric/build_top_module_connection.h index 7f7d06905..d400205d2 100644 --- a/openfpga/src/fabric/build_top_module_connection.h +++ b/openfpga/src/fabric/build_top_module_connection.h @@ -10,6 +10,7 @@ #include "device_grid.h" #include "rr_graph_obj.h" #include "device_rr_gsb.h" +#include "tile_annotation.h" #include "module_manager.h" /******************************************************************** @@ -30,6 +31,12 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager, const bool& compact_routing_hierarchy, const bool& duplicate_grid_pin); +int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, + const ModuleId& top_module, + const TileAnnotation& tile_annotation, + const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids); + } /* end namespace openfpga */ #endif diff --git a/openfpga/src/fabric/fabric_global_port_info.cpp b/openfpga/src/fabric/fabric_global_port_info.cpp new file mode 100644 index 000000000..08ea8444d --- /dev/null +++ b/openfpga/src/fabric/fabric_global_port_info.cpp @@ -0,0 +1,137 @@ +/************************************************************************ + * Member functions for class FabricGlobalPortInfo + ***********************************************************************/ +#include "vtr_assert.h" + +#include "fabric_global_port_info.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +FabricGlobalPortInfo::FabricGlobalPortInfo() { + return; +} + +/************************************************************************ + * Public Accessors : aggregates + ***********************************************************************/ +FabricGlobalPortInfo::global_port_range FabricGlobalPortInfo::global_ports() const { + return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end()); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +ModulePortId FabricGlobalPortInfo::global_module_port(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_module_ports_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_clock(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_clock_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_set(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_set_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_reset(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_reset_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_prog(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_prog_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_config_enable_[global_port_id]; +} + +bool FabricGlobalPortInfo::global_port_is_io(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_is_io_[global_port_id]; +} + +size_t FabricGlobalPortInfo::global_port_default_value(const FabricGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_default_values_[global_port_id]; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +FabricGlobalPortId FabricGlobalPortInfo::create_global_port(const ModulePortId& module_port) { + /* This is a legal name. we can create a new id */ + FabricGlobalPortId port_id = FabricGlobalPortId(global_port_ids_.size()); + global_port_ids_.push_back(port_id); + global_module_ports_.push_back(module_port); + global_port_is_clock_.push_back(false); + global_port_is_set_.push_back(false); + global_port_is_reset_.push_back(false); + global_port_is_prog_.push_back(false); + global_port_is_io_.push_back(false); + global_port_is_config_enable_.push_back(false); + global_port_default_values_.push_back(0); + + return port_id; +} + +void FabricGlobalPortInfo::set_global_port_is_clock(const FabricGlobalPortId& global_port_id, + const bool& is_clock) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_clock_[global_port_id] = is_clock; +} + +void FabricGlobalPortInfo::set_global_port_is_set(const FabricGlobalPortId& global_port_id, + const bool& is_set) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_set_[global_port_id] = is_set; +} + +void FabricGlobalPortInfo::set_global_port_is_reset(const FabricGlobalPortId& global_port_id, + const bool& is_reset) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_reset_[global_port_id] = is_reset; +} + +void FabricGlobalPortInfo::set_global_port_is_prog(const FabricGlobalPortId& global_port_id, + const bool& is_prog) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_prog_[global_port_id] = is_prog; +} + +void FabricGlobalPortInfo::set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, + const bool& is_config_enable) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_config_enable_[global_port_id] = is_config_enable; +} + +void FabricGlobalPortInfo::set_global_port_is_io(const FabricGlobalPortId& global_port_id, + const bool& is_io) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_is_io_[global_port_id] = is_io; +} + +void FabricGlobalPortInfo::set_global_port_default_value(const FabricGlobalPortId& global_port_id, + const size_t& default_value) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_default_values_[global_port_id] = default_value; +} + +/************************************************************************ + * Internal invalidators/validators + ***********************************************************************/ +/* Validators */ +bool FabricGlobalPortInfo::valid_global_port_id(const FabricGlobalPortId& global_port_id) const { + return ( size_t(global_port_id) < global_port_ids_.size() ) && ( global_port_id == global_port_ids_[global_port_id] ); +} + +} /* namespace openfpga ends */ diff --git a/openfpga/src/fabric/fabric_global_port_info.h b/openfpga/src/fabric/fabric_global_port_info.h new file mode 100644 index 000000000..31c67583e --- /dev/null +++ b/openfpga/src/fabric/fabric_global_port_info.h @@ -0,0 +1,79 @@ +#ifndef FABRIC_GLOBAL_PORT_INFO_H +#define FABRIC_GLOBAL_PORT_INFO_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include +#include + +#include "vtr_vector.h" +#include "module_manager_fwd.h" + +#include "fabric_global_port_info_fwd.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/******************************************************************** + * A data structure to store necessary information for the global + * ports that have been defined for the FPGA fabric + * + * Currently the global port information is mainly used for testbench generation + *******************************************************************/ +class FabricGlobalPortInfo { + public: /* Types */ + typedef vtr::vector::const_iterator global_port_iterator; + /* Create range */ + typedef vtr::Range global_port_range; + public: /* Constructor */ + FabricGlobalPortInfo(); + public: /* Public accessors: aggregators */ + global_port_range global_ports() const; + public: /* Public accessors */ + ModulePortId global_module_port(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_clock(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_set(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_reset(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_prog(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_config_enable(const FabricGlobalPortId& global_port_id) const; + bool global_port_is_io(const FabricGlobalPortId& global_port_id) const; + size_t global_port_default_value(const FabricGlobalPortId& global_port_id) const; + public: /* Public mutators */ + /* By default, we do not set it as a clock. + * Users should set it through the set_global_port_is_clock() function + */ + FabricGlobalPortId create_global_port(const ModulePortId& module_port); + void set_global_port_is_clock(const FabricGlobalPortId& global_port_id, + const bool& is_clock); + void set_global_port_is_set(const FabricGlobalPortId& global_port_id, + const bool& is_set); + void set_global_port_is_reset(const FabricGlobalPortId& global_port_id, + const bool& is_reset); + void set_global_port_is_prog(const FabricGlobalPortId& global_port_id, + const bool& is_prog); + void set_global_port_is_config_enable(const FabricGlobalPortId& global_port_id, + const bool& is_config_enable); + void set_global_port_is_io(const FabricGlobalPortId& global_port_id, + const bool& is_io); + void set_global_port_default_value(const FabricGlobalPortId& global_port_id, + const size_t& default_value); + public: /* Public validator */ + bool valid_global_port_id(const FabricGlobalPortId& global_port_id) const; + private: /* Internal data */ + /* Global port information for tiles */ + vtr::vector global_port_ids_; + vtr::vector global_module_ports_; + vtr::vector global_port_is_clock_; + vtr::vector global_port_is_reset_; + vtr::vector global_port_is_set_; + vtr::vector global_port_is_prog_; + vtr::vector global_port_is_config_enable_; + vtr::vector global_port_is_io_; + vtr::vector global_port_default_values_; +}; + +} /* namespace openfpga ends */ + +#endif + diff --git a/openfpga/src/fabric/fabric_global_port_info_fwd.h b/openfpga/src/fabric/fabric_global_port_info_fwd.h new file mode 100644 index 000000000..35a7dcd04 --- /dev/null +++ b/openfpga/src/fabric/fabric_global_port_info_fwd.h @@ -0,0 +1,22 @@ +/************************************************************************ + * A header file for FabricGlobalPortList class, including critical data declaration + * Please include this file only for using any FabricGlobalPortList data structure + * Refer to fabric_global_port_list.h for more details + ***********************************************************************/ + +/************************************************************************ + * Create strong id for fabric global ports to avoid illegal type casting + ***********************************************************************/ +#ifndef FABRIC_GLOBAL_PORT_INFO_FWD_H +#define FABRIC_GLOBAL_PORT_INFO_FWD_H + +#include "vtr_strong_id.h" + +struct fabric_global_port_id_tag; + +typedef vtr::StrongId FabricGlobalPortId; + +/* Short declaration of class */ +class FabricGlobalPortInfo; + +#endif diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp b/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp index 8f8b57561..f8dec09be 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer.cpp @@ -44,8 +44,7 @@ void print_analysis_sdc_io_delays(std::fstream& fp, const IoLocationMap& io_location_map, const ModuleManager& module_manager, const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo& fabric_global_port_info, const float& critical_path_delay) { /* Validate the file stream */ valid_file_stream(fp); @@ -57,17 +56,17 @@ void print_analysis_sdc_io_delays(std::fstream& fp, /* Get clock port from the global port */ std::vector operating_clock_ports; - for (const CircuitPortId& clock_port : global_ports) { - if (CIRCUIT_MODEL_PORT_CLOCK != circuit_lib.port_type(clock_port)) { + for (const FabricGlobalPortId& clock_port : fabric_global_port_info.global_ports()) { + if (false == fabric_global_port_info.global_port_is_clock(clock_port)) { continue; } /* We only constrain operating clock here! */ - if (true == circuit_lib.port_is_prog(clock_port)) { + if (true == fabric_global_port_info.global_port_is_prog(clock_port)) { continue; } /* Find the module port and Update the operating port list */ - ModulePortId module_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(clock_port)); + ModulePortId module_port = fabric_global_port_info.global_module_port(clock_port); operating_clock_ports.push_back(module_manager.module_port(top_module, module_port)); } @@ -181,8 +180,7 @@ static void print_analysis_sdc_disable_global_ports(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports) { + const FabricGlobalPortInfo& fabric_global_port_info) { /* Validate file stream */ valid_file_stream(fp); @@ -191,31 +189,19 @@ void print_analysis_sdc_disable_global_ports(std::fstream& fp, fp << "# Disable timing for global ports " << std::endl; fp << "##################################################" << std::endl; - for (const CircuitPortId& global_port : global_ports) { + for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { /* Skip operating clock here! */ - if ( (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)) - && (false == circuit_lib.port_is_prog(global_port)) ) { + if ( (true == fabric_global_port_info.global_port_is_clock(global_port)) + && (false == fabric_global_port_info.global_port_is_prog(global_port)) ) { continue; } /* Skip any gpio port here! */ - if ( (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(global_port)) - && (true == circuit_lib.port_is_io(global_port)) ) { + if (true == fabric_global_port_info.global_port_is_io(global_port)) { continue; } - /* Skip any gpio port here! */ - if (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(global_port)) { - continue; - } - - /* Skip any gpio port here! */ - if ( (CIRCUIT_MODEL_PORT_INOUT == circuit_lib.port_type(global_port)) - && (true == circuit_lib.port_is_io(global_port)) ) { - continue; - } - - ModulePortId module_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(global_port)); + ModulePortId module_port = fabric_global_port_info.global_module_port(global_port); BasicPort port_to_disable = module_manager.module_port(top_module, module_port); print_sdc_disable_port_timing(fp, port_to_disable); @@ -230,7 +216,6 @@ void print_analysis_sdc(const AnalysisSdcOption& option, const float& critical_path_delay, const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, - const std::vector& global_ports, const bool& compact_routing_hierarchy) { /* Create the file name for Verilog netlist */ std::string sdc_fname(option.sdc_dir() + generate_analysis_sdc_file_name(vpr_ctx.atom().nlist.netlist_name(), std::string(SDC_ANALYSIS_FILE_NAME))); @@ -261,13 +246,13 @@ void print_analysis_sdc(const AnalysisSdcOption& option, vpr_ctx.atom(), vpr_ctx.placement(), openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.io_location_map(), openfpga_ctx.module_graph(), top_module, - openfpga_ctx.arch().circuit_lib, global_ports, + openfpga_ctx.fabric_global_port_info(), critical_path_delay); /* Disable the timing for global ports */ print_analysis_sdc_disable_global_ports(fp, openfpga_ctx.module_graph(), top_module, - openfpga_ctx.arch().circuit_lib, global_ports); + openfpga_ctx.fabric_global_port_info()); /* Disable the timing for configuration cells */ rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, option.flatten_names(), diff --git a/openfpga/src/fpga_sdc/analysis_sdc_writer.h b/openfpga/src/fpga_sdc/analysis_sdc_writer.h index c3d08794a..225c2f982 100644 --- a/openfpga/src/fpga_sdc/analysis_sdc_writer.h +++ b/openfpga/src/fpga_sdc/analysis_sdc_writer.h @@ -21,7 +21,6 @@ void print_analysis_sdc(const AnalysisSdcOption& option, const float& critical_path_delay, const VprContext& vpr_ctx, const OpenfpgaContext& openfpga_ctx, - const std::vector& global_ports, const bool& compact_routing_hierarchy); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp index 4e6ef4925..d258ca640 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.cpp @@ -61,21 +61,22 @@ static void print_pnr_sdc_global_clock_ports(std::fstream& fp, const float& programming_critical_path_delay, const float& operating_critical_path_delay, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports) { + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { valid_file_stream(fp); /* Get clock port from the global port */ - for (const CircuitPortId& clock_port : global_ports) { - if (CIRCUIT_MODEL_PORT_CLOCK != circuit_lib.port_type(clock_port)) { + for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + if (false == fabric_global_port_info.global_port_is_clock(global_port)) { continue; } /* Reach here, it means a clock port and we need print constraints */ float clock_period = operating_critical_path_delay; /* For programming clock, we give a fixed period */ - if (true == circuit_lib.port_is_prog(clock_port)) { + if (true == fabric_global_port_info.global_port_is_prog(global_port)) { clock_period = programming_critical_path_delay; /* Print comments */ fp << "##################################################" << std::endl; @@ -88,8 +89,9 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp, fp << "##################################################" << std::endl; } - for (const size_t& pin : circuit_lib.pins(clock_port)) { - BasicPort port_to_constrain(circuit_lib.port_prefix(clock_port), pin, pin); + BasicPort clock_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(global_port)); + for (const size_t& pin : clock_port.pins()) { + BasicPort port_to_constrain(clock_port.get_name(), pin, pin); print_pnr_sdc_clock_port(fp, port_to_constrain, @@ -109,14 +111,15 @@ void print_pnr_sdc_global_clock_ports(std::fstream& fp, static void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, const float& operating_critical_path_delay, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports) { + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& fabric_global_port_info) { valid_file_stream(fp); /* For non-clock port from the global port: give a fixed period */ - for (const CircuitPortId& global_port : global_ports) { - if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)) { + for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + if (true == fabric_global_port_info.global_port_is_clock(global_port)) { continue; } @@ -127,8 +130,9 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, /* Reach here, it means a non-clock global port and we need print constraints */ float clock_period = operating_critical_path_delay; - for (const size_t& pin : circuit_lib.pins(global_port)) { - BasicPort port_to_constrain(circuit_lib.port_prefix(global_port), pin, pin); + BasicPort non_clock_port = module_manager.module_port(top_module, fabric_global_port_info.global_module_port(global_port)); + for (const size_t& pin : non_clock_port.pins()) { + BasicPort port_to_constrain(non_clock_port.get_name(), pin, pin); print_pnr_sdc_clock_port(fp, port_to_constrain, @@ -151,8 +155,9 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp, void print_pnr_sdc_global_ports(const std::string& sdc_dir, const float& programming_critical_path_delay, const float& operating_critical_path_delay, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& global_ports, const bool& constrain_non_clock_port) { /* Create the file name for Verilog netlist */ @@ -174,13 +179,13 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir, print_pnr_sdc_global_clock_ports(fp, programming_critical_path_delay, operating_critical_path_delay, - circuit_lib, + module_manager, top_module, global_ports); if (true == constrain_non_clock_port) { print_pnr_sdc_global_non_clock_ports(fp, operating_critical_path_delay, - circuit_lib, + module_manager, top_module, global_ports); } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_global_port.h b/openfpga/src/fpga_sdc/pnr_sdc_global_port.h index 444482106..e17dd0d9b 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_global_port.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_global_port.h @@ -6,7 +6,8 @@ *******************************************************************/ #include #include -#include "circuit_library.h" +#include "module_manager.h" +#include "fabric_global_port_info.h" /******************************************************************** * Function declaration @@ -18,8 +19,9 @@ namespace openfpga { void print_pnr_sdc_global_ports(const std::string& sdc_dir, const float& programming_critical_path_delay, const float& operating_critical_path_delay, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const ModuleManager& module_manager, + const ModuleId& top_module, + const FabricGlobalPortInfo& global_ports, const bool& constrain_non_clock_port); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp index c02988462..d6596eba1 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp @@ -327,22 +327,22 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, const ModuleManager& module_manager, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo& global_ports, const bool& compact_routing_hierarchy) { - + + std::string top_module_name = generate_fpga_top_module_name(); + ModuleId top_module = module_manager.find_module(top_module_name); + VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + /* Constrain global ports */ if (true == sdc_options.constrain_global_port()) { print_pnr_sdc_global_ports(sdc_options.sdc_dir(), programming_critical_path_delay, operating_critical_path_delay, - circuit_lib, global_ports, + module_manager, top_module, global_ports, sdc_options.constrain_non_clock_global_port()); } - std::string top_module_name = generate_fpga_top_module_name(); - ModuleId top_module = module_manager.find_module(top_module_name); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); - /* Output Design Constraints to disable outputs of memory cells */ if (true == sdc_options.constrain_configurable_memory_outputs()) { print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(), diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_writer.h index 1016d57da..38aff2a2c 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.h @@ -12,6 +12,7 @@ #include "module_manager.h" #include "mux_library.h" #include "circuit_library.h" +#include "fabric_global_port_info.h" #include "pnr_sdc_option.h" /******************************************************************** @@ -30,7 +31,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options, const ModuleManager& module_manager, const MuxLibrary& mux_lib, const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo& global_ports, const bool& compact_routing_hierarchy); } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 81ad7478f..29ecab1f7 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -153,6 +153,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const IoLocationMap &io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, const VprNetlistAnnotation &netlist_annotation, const CircuitLibrary &circuit_lib, const SimulationSetting &simulation_setting, @@ -172,17 +173,12 @@ void fpga_verilog_testbench(const ModuleManager &module_manager, print_verilog_simulation_preprocessing_flags(std::string(src_dir_path), options); - /* Collect global ports from the circuit library: - * TODO: should we place this in the OpenFPGA context? - */ - std::vector global_ports = find_circuit_library_global_ports(circuit_lib); - /* Generate wrapper module for FPGA fabric (mapped by the input benchmark and pre-configured testbench for verification */ if (true == options.print_formal_verification_top_netlist()) { std::string formal_verification_top_netlist_file_path = src_dir_path + netlist_name + std::string(FORMAL_VERIFICATION_VERILOG_FILE_POSTFIX); print_verilog_preconfig_top_module(module_manager, bitstream_manager, config_protocol, - circuit_lib, global_ports, + circuit_lib, fabric_global_port_info, atom_ctx, place_ctx, io_location_map, netlist_annotation, netlist_name, @@ -207,7 +203,7 @@ void fpga_verilog_testbench(const ModuleManager &module_manager, print_verilog_top_testbench(module_manager, bitstream_manager, fabric_bitstream, config_protocol, - circuit_lib, global_ports, + fabric_global_port_info, atom_ctx, place_ctx, io_location_map, netlist_annotation, netlist_name, diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index 1af656d7d..92a16ba8f 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -20,6 +20,7 @@ #include "fabric_bitstream.h" #include "simulation_setting.h" #include "io_location_map.h" +#include "fabric_global_port_info.h" #include "vpr_netlist_annotation.h" #include "fabric_verilog_options.h" #include "verilog_testbench_options.h" @@ -47,6 +48,7 @@ void fpga_verilog_testbench(const ModuleManager& module_manager, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const IoLocationMap& io_location_map, + const FabricGlobalPortInfo &fabric_global_port_info, const VprNetlistAnnotation& netlist_annotation, const CircuitLibrary& circuit_lib, const SimulationSetting& simulation_parameters, diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 9500044be..033fcc346 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -118,8 +118,7 @@ namespace openfpga static void print_verilog_preconfig_top_module_connect_global_ports(std::fstream &fp, const ModuleManager &module_manager, const ModuleId &top_module, - const CircuitLibrary &circuit_lib, - const std::vector &global_ports, + const FabricGlobalPortInfo &fabric_global_ports, const std::vector &benchmark_clock_port_names) { /* Validate the file stream */ @@ -127,40 +126,16 @@ namespace openfpga print_verilog_comment(fp, std::string("----- Begin Connect Global ports of FPGA top module -----")); - /* Global ports of the top module in module manager do not carry any attributes, - * such as is_clock, is_set, etc. - * Therefore, for each global port in the top module, we find the circuit port in the circuit library - * which share the same name. We can access to the attributes. - * To gurantee the correct link between global ports in module manager and those in circuit library - * We have performed some critical check in check_circuit_library() for global ports, - * where we guarantee all the global ports share the same name must have the same attributes. - * So that each global port with the same name is unique! - */ - for (const BasicPort &module_global_port : module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GLOBAL_PORT)) - { - CircuitPortId linked_circuit_port_id = CircuitPortId::INVALID(); - /* Find the circuit port with the same name */ - for (const CircuitPortId &circuit_port_id : global_ports) - { - if (0 != module_global_port.get_name().compare(circuit_lib.port_prefix(circuit_port_id))) - { - continue; - } - linked_circuit_port_id = circuit_port_id; - break; - } - /* Must find one valid circuit port */ - VTR_ASSERT(CircuitPortId::INVALID() != linked_circuit_port_id); - /* Port size should match! */ - VTR_ASSERT(module_global_port.get_width() == circuit_lib.port_size(linked_circuit_port_id)); + for (const FabricGlobalPortId& global_port_id : fabric_global_ports.global_ports()) { + ModulePortId module_global_port_id = fabric_global_ports.global_module_port(global_port_id); + VTR_ASSERT(ModuleManager::MODULE_GLOBAL_PORT == module_manager.port_type(top_module, module_global_port_id)); + BasicPort module_global_port = module_manager.module_port(top_module, module_global_port_id); /* Now, for operating clock port, we should wire it to the clock of benchmark! */ - if ((CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(linked_circuit_port_id)) && (false == circuit_lib.port_is_prog(linked_circuit_port_id))) - { + if ((true == fabric_global_ports.global_port_is_clock(global_port_id)) + && (false == fabric_global_ports.global_port_is_prog(global_port_id))) { /* Wiring to each pin of the global port: benchmark clock is always 1-bit */ - for (const size_t &pin : module_global_port.pins()) - { - for (const std::string &clock_port_name : benchmark_clock_port_names) - { + for (const size_t &pin : module_global_port.pins()) { + for (const std::string &clock_port_name : benchmark_clock_port_names) { BasicPort module_clock_pin(module_global_port.get_name(), pin, pin); BasicPort benchmark_clock_pin(clock_port_name + std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), 1); print_verilog_wire_connection(fp, module_clock_pin, benchmark_clock_pin, false); @@ -171,7 +146,7 @@ namespace openfpga } /* For other ports, give an default value */ - std::vector default_values(module_global_port.get_width(), circuit_lib.port_default_value(linked_circuit_port_id)); + std::vector default_values(module_global_port.get_width(), fabric_global_ports.global_port_default_value(global_port_id)); print_verilog_wire_constant_values(fp, module_global_port, default_values); } @@ -430,7 +405,7 @@ namespace openfpga const BitstreamManager &bitstream_manager, const ConfigProtocol &config_protocol, const CircuitLibrary &circuit_lib, - const std::vector &global_ports, + const FabricGlobalPortInfo &global_ports, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const IoLocationMap &io_location_map, @@ -475,7 +450,7 @@ namespace openfpga /* Connect FPGA top module global ports to constant or benchmark global signals! */ print_verilog_preconfig_top_module_connect_global_ports(fp, module_manager, top_module, - circuit_lib, global_ports, + global_ports, benchmark_clock_port_names); /* Connect I/Os to benchmark I/Os or constant driver */ diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h index 498c67628..878795bcb 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.h @@ -11,6 +11,7 @@ #include "module_manager.h" #include "bitstream_manager.h" #include "io_location_map.h" +#include "fabric_global_port_info.h" #include "config_protocol.h" #include "vpr_netlist_annotation.h" @@ -25,7 +26,7 @@ void print_verilog_preconfig_top_module(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const ConfigProtocol &config_protocol, const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo &global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const IoLocationMap& io_location_map, diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 6753f6626..dbcb737e0 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -6,7 +6,6 @@ #include #include - /* Headers from vtrutil library */ #include "vtr_log.h" #include "vtr_assert.h" @@ -24,6 +23,7 @@ #include "openfpga_atom_netlist_utils.h" #include "fabric_bitstream_utils.h" +#include "fabric_global_port_info_utils.h" #include "verilog_constants.h" #include "verilog_writer_utils.h" @@ -62,54 +62,6 @@ constexpr char* TOP_TB_CLOCK_REG_POSTFIX = "_reg"; constexpr char* AUTOCHECK_TOP_TESTBENCH_VERILOG_MODULE_POSTFIX = "_autocheck_top_tb"; -/******************************************************************** - * Identify global reset ports for programming - *******************************************************************/ -static -std::vector find_global_programming_reset_ports(const CircuitLibrary& circuit_lib, - const std::vector& global_ports) { - /* Try to find global reset ports for programming */ - std::vector global_prog_reset_ports; - for (const CircuitPortId& global_port : global_ports) { - VTR_ASSERT(true == circuit_lib.port_is_global(global_port)); - if (false == circuit_lib.port_is_prog(global_port)) { - continue; - } - VTR_ASSERT(true == circuit_lib.port_is_prog(global_port)); - VTR_ASSERT( (false == circuit_lib.port_is_reset(global_port)) - || (false == circuit_lib.port_is_set(global_port))); - if (true == circuit_lib.port_is_reset(global_port)) { - global_prog_reset_ports.push_back(global_port); - } - } - - return global_prog_reset_ports; -} - -/******************************************************************** - * Identify global set ports for programming - *******************************************************************/ -static -std::vector find_global_programming_set_ports(const CircuitLibrary& circuit_lib, - const std::vector& global_ports) { - /* Try to find global set ports for programming */ - std::vector global_prog_set_ports; - for (const CircuitPortId& global_port : global_ports) { - VTR_ASSERT(true == circuit_lib.port_is_global(global_port)); - if (false == circuit_lib.port_is_prog(global_port)) { - continue; - } - VTR_ASSERT(true == circuit_lib.port_is_prog(global_port)); - VTR_ASSERT( (false == circuit_lib.port_is_reset(global_port)) - || (false == circuit_lib.port_is_set(global_port))); - if (true == circuit_lib.port_is_set(global_port)) { - global_prog_set_ports.push_back(global_port); - } - } - - return global_prog_set_ports; -} - /******************************************************************** * Print local wires for flatten memory (standalone) configuration protocols *******************************************************************/ @@ -300,8 +252,7 @@ static void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo& fabric_global_port_info, const bool& active_global_prog_reset, const bool& active_global_prog_set) { /* Validate the file stream */ @@ -310,8 +261,8 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, print_verilog_comment(fp, std::string("----- Begin connecting global ports of FPGA fabric to stimuli -----")); /* Connect global clock ports to operating or programming clock signal */ - for (const CircuitPortId& model_global_port : global_ports) { - if (CIRCUIT_MODEL_PORT_CLOCK != circuit_lib.port_type(model_global_port)) { + for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { + if (false == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Reach here, it means we have a global clock to deal with: @@ -321,15 +272,15 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, * connect it to the local wire of operating clock */ /* Find the module port */ - ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port)); + ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); BasicPort stimuli_clock_port; - if (true == circuit_lib.port_is_prog(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_clock_port.set_name(std::string(TOP_TB_PROG_CLOCK_PORT_NAME)); stimuli_clock_port.set_width(1); } else { - VTR_ASSERT_SAFE(false == circuit_lib.port_is_prog(model_global_port)); + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port)); stimuli_clock_port.set_name(std::string(TOP_TB_OP_CLOCK_PORT_NAME)); stimuli_clock_port.set_width(1); } @@ -339,21 +290,21 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, */ print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), stimuli_clock_port, - 1 == circuit_lib.port_default_value(model_global_port)); + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } /* Connect global configuration done ports to configuration done signal */ - for (const CircuitPortId& model_global_port : global_ports) { + for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } - if (false == circuit_lib.port_is_config_enable(model_global_port)) { + if (false == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { continue; } /* Reach here, it means we have a configuration done port to deal with */ /* Find the module port */ - ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port)); + ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); BasicPort stimuli_config_done_port(std::string(TOP_TB_CONFIG_DONE_PORT_NAME), 1); @@ -363,37 +314,37 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, */ print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), stimuli_config_done_port, - 1 == circuit_lib.port_default_value(model_global_port)); + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } /* Connect global reset ports to operating or programming reset signal */ - for (const CircuitPortId& model_global_port : global_ports) { + for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Bypass config_done signals, they have been processed */ - if (true == circuit_lib.port_is_config_enable(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { continue; } - if (false == circuit_lib.port_is_reset(model_global_port)) { + if (false == fabric_global_port_info.global_port_is_reset(fabric_global_port)) { continue; } /* Reach here, it means we have a reset port to deal with */ /* Find the module port */ - ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port)); + ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); /* For global programming reset port, we will active only when specified */ BasicPort stimuli_reset_port; bool activate = true; - if (true == circuit_lib.port_is_prog(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_reset_port.set_name(std::string(TOP_TB_PROG_RESET_PORT_NAME)); stimuli_reset_port.set_width(1); activate = active_global_prog_reset; } else { - VTR_ASSERT_SAFE(false == circuit_lib.port_is_prog(model_global_port)); + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port)); stimuli_reset_port.set_name(std::string(TOP_TB_RESET_PORT_NAME)); stimuli_reset_port.set_width(1); } @@ -404,47 +355,47 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, if (true == activate) { print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), stimuli_reset_port, - 1 == circuit_lib.port_default_value(model_global_port)); + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } else { VTR_ASSERT_SAFE(false == activate); print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port), - std::vector(1, circuit_lib.port_default_value(model_global_port))); + std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); } } /* Connect global set ports to operating or programming set signal */ - for (const CircuitPortId& model_global_port : global_ports) { + for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Bypass config_done signals, they have been processed */ - if (true == circuit_lib.port_is_config_enable(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { continue; } /* Bypass reset signals, they have been processed */ - if (true == circuit_lib.port_is_reset(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_reset(fabric_global_port)) { continue; } - if (false == circuit_lib.port_is_set(model_global_port)) { + if (false == fabric_global_port_info.global_port_is_set(fabric_global_port)) { continue; } /* Reach here, it means we have a set port to deal with */ /* Find the module port */ - ModulePortId module_global_port = module_manager.find_module_port(top_module, circuit_lib.port_prefix(model_global_port)); + ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); /* For global programming set port, we will active only when specified */ BasicPort stimuli_set_port; bool activate = true; - if (true == circuit_lib.port_is_prog(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_prog(fabric_global_port)) { stimuli_set_port.set_name(std::string(TOP_TB_PROG_SET_PORT_NAME)); stimuli_set_port.set_width(1); activate = active_global_prog_set; } else { - VTR_ASSERT_SAFE(false == circuit_lib.port_is_prog(model_global_port)); + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_prog(fabric_global_port)); stimuli_set_port.set_name(std::string(TOP_TB_SET_PORT_NAME)); stimuli_set_port.set_width(1); } @@ -455,56 +406,51 @@ void print_verilog_top_testbench_global_ports_stimuli(std::fstream& fp, if (true == activate) { print_verilog_wire_connection(fp, module_manager.module_port(top_module, module_global_port), stimuli_set_port, - 1 == circuit_lib.port_default_value(model_global_port)); + 1 == fabric_global_port_info.global_port_default_value(fabric_global_port)); } else { VTR_ASSERT_SAFE(false == activate); print_verilog_wire_constant_values(fp, module_manager.module_port(top_module, module_global_port), - std::vector(1, circuit_lib.port_default_value(model_global_port))); + std::vector(1, fabric_global_port_info.global_port_default_value(fabric_global_port))); } } /* For the rest of global ports, wire them to constant signals */ - for (const CircuitPortId& model_global_port : global_ports) { + for (const FabricGlobalPortId& fabric_global_port : fabric_global_port_info.global_ports()) { /* Bypass clock signals, they have been processed */ - if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_clock(fabric_global_port)) { continue; } /* Bypass config_done signals, they have been processed */ - if (true == circuit_lib.port_is_config_enable(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_config_enable(fabric_global_port)) { continue; } /* Bypass reset signals, they have been processed */ - if (true == circuit_lib.port_is_reset(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_reset(fabric_global_port)) { continue; } /* Bypass set signals, they have been processed */ - if (true == circuit_lib.port_is_set(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_set(fabric_global_port)) { continue; } /* Bypass io signals, they do not need any drivers */ - if (true == circuit_lib.port_is_io(model_global_port)) { + if (true == fabric_global_port_info.global_port_is_io(fabric_global_port)) { continue; } /* Find the port name, gpio port has special names */ std::string port_name; - if (true == circuit_lib.port_is_io(model_global_port)) { - port_name = generate_fpga_global_io_port_name(std::string(GIO_INOUT_PREFIX), circuit_lib, circuit_lib.port_parent_model(model_global_port), model_global_port); - } else { - VTR_ASSERT_SAFE(false == circuit_lib.port_is_io(model_global_port)); - port_name = circuit_lib.port_prefix(model_global_port); - } + VTR_ASSERT_SAFE(false == fabric_global_port_info.global_port_is_io(fabric_global_port)); /* Reach here, it means we have a port to deal with */ /* Find the module port and wire it to constant values */ - ModulePortId module_global_port = module_manager.find_module_port(top_module, port_name); + ModulePortId module_global_port = fabric_global_port_info.global_module_port(fabric_global_port); VTR_ASSERT(true == module_manager.valid_module_port_id(top_module, module_global_port)); BasicPort module_port = module_manager.module_port(top_module, module_global_port); - std::vector default_values(module_port.get_width(), circuit_lib.port_default_value(model_global_port)); + std::vector default_values(module_port.get_width(), fabric_global_port_info.global_port_default_value(fabric_global_port)); print_verilog_wire_constant_values(fp, module_port, default_values); } @@ -1279,8 +1225,8 @@ void print_verilog_top_testbench_vanilla_bitstream(std::fstream& fp, static bool find_bit_value_to_skip_for_fast_configuration(const e_config_protocol_type& config_protocol_type, const bool& fast_configuration, - const std::vector& global_prog_reset_ports, - const std::vector& global_prog_set_ports, + const std::vector& global_prog_reset_ports, + const std::vector& global_prog_set_ports, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream) { @@ -1824,8 +1770,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const IoLocationMap& io_location_map, @@ -1860,8 +1805,8 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, std::vector clock_port_names = find_atom_netlist_clock_port_names(atom_ctx.nlist, netlist_annotation); /* Preparation: find all the reset/set ports for programming usage */ - std::vector global_prog_reset_ports = find_global_programming_reset_ports(circuit_lib, global_ports); - std::vector global_prog_set_ports = find_global_programming_set_ports(circuit_lib, global_ports); + std::vector global_prog_reset_ports = find_fabric_global_programming_reset_ports(global_ports); + std::vector global_prog_set_ports = find_fabric_global_programming_set_ports(global_ports); /* Identify if we can apply fast configuration */ bool apply_fast_configuration = fast_configuration; @@ -1935,7 +1880,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, /* Generate stimuli for global ports or connect them to existed signals */ print_verilog_top_testbench_global_ports_stimuli(fp, module_manager, top_module, - circuit_lib, global_ports, + global_ports, active_global_prog_reset, active_global_prog_set); diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.h b/openfpga/src/fpga_verilog/verilog_top_testbench.h index 64d0e0b26..6aeb5578b 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.h +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.h @@ -9,10 +9,10 @@ #include "module_manager.h" #include "bitstream_manager.h" #include "fabric_bitstream.h" -#include "circuit_library.h" #include "config_protocol.h" #include "vpr_context.h" #include "io_location_map.h" +#include "fabric_global_port_info.h" #include "vpr_netlist_annotation.h" #include "simulation_setting.h" @@ -27,8 +27,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager, const BitstreamManager& bitstream_manager, const FabricBitstream& fabric_bitstream, const ConfigProtocol& config_protocol, - const CircuitLibrary& circuit_lib, - const std::vector& global_ports, + const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const IoLocationMap& io_location_map, diff --git a/openfpga/src/utils/check_tile_annotation.cpp b/openfpga/src/utils/check_tile_annotation.cpp new file mode 100644 index 000000000..75d1eeaf5 --- /dev/null +++ b/openfpga/src/utils/check_tile_annotation.cpp @@ -0,0 +1,229 @@ +/************************************************************************ + * Check functions for the content of tile annotation to avoid conflicts with + * other data structures + * These functions are not universal methods for the TileAnnotation class + * They are made to ease the development in some specific purposes + * Please classify such functions in this file + ***********************************************************************/ + +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "openfpga_physical_tile_utils.h" +#include "circuit_library_utils.h" +#include "check_tile_annotation.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Check if the tile annotation is valid without any conflict with + * circuit library content. + * Items to check: + * - The global port defined in tile annotation has no conflicts with + * the global ports which are defined in circuit library: + * - If a port has the same name, must ensure that its attributes are the same + * i.e., is_clock, is_reset, is_set + * - Otherwise, error out + *******************************************************************/ +static +int check_tile_annotation_conflicts_with_circuit_library(const TileAnnotation& tile_annotation, + const CircuitLibrary& circuit_lib) { + int num_err = 0; + + std::vector ckt_global_ports = find_circuit_library_global_ports(circuit_lib); + for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { + for (const CircuitPortId& ckt_global_port : ckt_global_ports) { + if (tile_annotation.global_port_name(tile_global_port) != circuit_lib.port_prefix(ckt_global_port)) { + continue; + } + /* All the global clock port here must be operating clock */ + bool is_both_op_signal = !circuit_lib.port_is_prog(ckt_global_port); + if (false == is_both_op_signal) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library, which is defined for programming usage!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); + num_err++; + } + + /* Error out if one is defined as clock while another is not */ + bool is_clock_attr_same = (tile_annotation.global_port_is_clock(tile_global_port) != (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(ckt_global_port))); + if (false == is_clock_attr_same) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library but has different definition as clock!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); + num_err++; + } + + /* Error out if one is defined as reset while another is not */ + bool is_reset_attr_same = (tile_annotation.global_port_is_reset(tile_global_port) != circuit_lib.port_is_reset(ckt_global_port)); + if (false == is_reset_attr_same) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library but has different definition as reset!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); + num_err++; + } + + /* Error out if one is defined as set while another is not */ + bool is_set_attr_same = (tile_annotation.global_port_is_set(tile_global_port) != circuit_lib.port_is_set(ckt_global_port)); + if (false == is_set_attr_same) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Global port '%s' in tile annotation share the same name as global port '%s' in circuit library but has different definition as set!\n", + tile_annotation.global_port_name(tile_global_port).c_str(), + circuit_lib.port_prefix(ckt_global_port).c_str()); + num_err++; + } + } + } + + return num_err; +} + +/******************************************************************** + * Check if the tile annotation is valid without any conflict with + * physical tile definition. + * Items to check: + * - The global port defined in tile annotation is a valid port/pin in + * the physical tile definition. + * - If the port properties match: + * - the port in physical tile should have Fc = 0 + * - a clock port should be also a clock port in physical tile + * - a non-clock port should be defined as a non-clock global port in physical tile + *******************************************************************/ +static +int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& tile_annotation, + const std::vector& physical_tile_types) { + int num_err = 0; + + for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { + /* Must find a valid physical tile in the same name */ + size_t found_matched_physical_tile = 0; + size_t found_matched_physical_tile_port = 0; + for (const t_physical_tile_type& physical_tile : physical_tile_types) { + if (std::string(physical_tile.name) != tile_annotation.global_port_tile_name(tile_global_port)) { + continue; + } + + /* Found a match, increment the counter */ + found_matched_physical_tile++; + + /* Must found a valid port where both port name and port size must match!!! */ + for (const t_physical_tile_port& tile_port : physical_tile.ports) { + if (std::string(tile_port.name) != tile_annotation.global_port_tile_port(tile_global_port).get_name()) { + continue; + } + if (size_t(tile_port.num_pins) != tile_annotation.global_port_tile_port(tile_global_port).get_width()) { + continue; + } + + /* Check if port property matches */ + int grid_pin_index = tile_port.absolute_first_pin_index; + + if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), + tile_annotation.global_port_tile_port(tile_global_port).get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name); + num_err++; + } + + if ((false == tile_port.is_clock) + && (false == tile_port.is_non_clock_global)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), + tile_annotation.global_port_tile_port(tile_global_port).get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name); + num_err++; + } + + float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index); + if (0. != pin_Fc) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), + tile_annotation.global_port_tile_port(tile_global_port).get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name, pin_Fc); + + } + + found_matched_physical_tile_port++; + } + } + + /* If we found no match, error out */ + if (0 == found_matched_physical_tile) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile name '%s' in tile annotation '%s' does not match any physical tile!\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + if (0 == found_matched_physical_tile_port) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), + tile_annotation.global_port_tile_port(tile_global_port).get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + + /* If we found more than 1 match, error out */ + if (1 < found_matched_physical_tile) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + if (1 < found_matched_physical_tile_port) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1physical tile port!\n", + tile_annotation.global_port_tile_name(tile_global_port).c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), + tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), + tile_annotation.global_port_tile_port(tile_global_port).get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + } + + return num_err; +} + +/******************************************************************** + * Check if the tile annotation is valid without any conflict with + * circuit library content and physical tiles. + *******************************************************************/ +bool check_tile_annotation(const TileAnnotation& tile_annotation, + const CircuitLibrary& circuit_lib, + const std::vector& physical_tile_types) { + int num_err = 0; + num_err += check_tile_annotation_conflicts_with_circuit_library(tile_annotation, circuit_lib); + + num_err += check_tile_annotation_conflicts_with_physical_tile(tile_annotation, physical_tile_types); + + VTR_LOG("Found %ld errors when checking tile annotation!\n", + num_err); + return (0 == num_err); +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/utils/check_tile_annotation.h b/openfpga/src/utils/check_tile_annotation.h new file mode 100644 index 000000000..7b2216a27 --- /dev/null +++ b/openfpga/src/utils/check_tile_annotation.h @@ -0,0 +1,25 @@ +#ifndef CHECK_TILE_ANNOTATION_H +#define CHECK_TILE_ANNOTATION_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "tile_annotation.h" +#include "circuit_library.h" +#include "physical_types.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +bool check_tile_annotation(const TileAnnotation& tile_annotations, + const CircuitLibrary& circuit_lib, + const std::vector& physical_tile_types); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/utils/fabric_global_port_info_utils.cpp b/openfpga/src/utils/fabric_global_port_info_utils.cpp new file mode 100644 index 000000000..3200a8fbd --- /dev/null +++ b/openfpga/src/utils/fabric_global_port_info_utils.cpp @@ -0,0 +1,61 @@ +/************************************************************************ + * Function to perform fundamental operation for the fabric global ports + * These functions are not universal methods for the FabricGlobalPortInfo class + * They are made to ease the development in some specific purposes + * Please classify such functions in this file + ***********************************************************************/ + +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "fabric_global_port_info_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Identify global reset ports for programming + *******************************************************************/ +std::vector find_fabric_global_programming_reset_ports(const FabricGlobalPortInfo& fabric_global_port_info) { + /* Try to find global reset ports for programming */ + std::vector global_prog_reset_ports; + for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + if (false == fabric_global_port_info.global_port_is_prog(global_port)) { + continue; + } + VTR_ASSERT(true == fabric_global_port_info.global_port_is_prog(global_port)); + VTR_ASSERT( (false == fabric_global_port_info.global_port_is_reset(global_port)) + || (false == fabric_global_port_info.global_port_is_set(global_port))); + if (true == fabric_global_port_info.global_port_is_reset(global_port)) { + global_prog_reset_ports.push_back(global_port); + } + } + + return global_prog_reset_ports; +} + +/******************************************************************** + * Identify global set ports for programming + *******************************************************************/ +std::vector find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info) { + /* Try to find global set ports for programming */ + std::vector global_prog_set_ports; + for (const FabricGlobalPortId& global_port : fabric_global_port_info.global_ports()) { + if (false == fabric_global_port_info.global_port_is_prog(global_port)) { + continue; + } + VTR_ASSERT(true == fabric_global_port_info.global_port_is_prog(global_port)); + VTR_ASSERT( (false == fabric_global_port_info.global_port_is_reset(global_port)) + || (false == fabric_global_port_info.global_port_is_set(global_port))); + if (true == fabric_global_port_info.global_port_is_set(global_port)) { + global_prog_set_ports.push_back(global_port); + } + } + + return global_prog_set_ports; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/utils/fabric_global_port_info_utils.h b/openfpga/src/utils/fabric_global_port_info_utils.h new file mode 100644 index 000000000..457c0018e --- /dev/null +++ b/openfpga/src/utils/fabric_global_port_info_utils.h @@ -0,0 +1,23 @@ +#ifndef FABRIC_GLOBAL_PORT_INFO_UTILS_H +#define FABRIC_GLOBAL_PORT_INFO_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "fabric_global_port_info.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +std::vector find_fabric_global_programming_reset_ports(const FabricGlobalPortInfo& fabric_global_port_info); + +std::vector find_fabric_global_programming_set_ports(const FabricGlobalPortInfo& fabric_global_port_info); + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/utils/module_manager_utils.cpp b/openfpga/src/utils/module_manager_utils.cpp index 7d4d92d9b..4a719b9a1 100644 --- a/openfpga/src/utils/module_manager_utils.cpp +++ b/openfpga/src/utils/module_manager_utils.cpp @@ -564,7 +564,6 @@ void add_primitive_pb_type_module_nets(ModuleManager& module_manager, BasicPort des_port = module_manager.module_port(child_module, des_module_port_id); /* Port size must match */ - if (src_port.get_width() != des_port.get_width()) VTR_ASSERT(src_port.get_width() == des_port.get_width()); /* For each pin, generate the nets. @@ -588,9 +587,9 @@ void add_primitive_pb_type_module_nets(ModuleManager& module_manager, for (size_t pin_id = 0; pin_id < src_port.pins().size(); ++pin_id) { ModuleNetId net = module_manager.create_module_net(pb_type_module); /* Add net source */ - module_manager.add_module_net_sink(pb_type_module, net, pb_type_module, 0, src_module_port_id, src_port.pins()[pin_id]); - /* Add net sink */ module_manager.add_module_net_source(pb_type_module, net, child_module, child_instance_id, des_module_port_id, des_port.pins()[pin_id]); + /* Add net sink */ + module_manager.add_module_net_sink(pb_type_module, net, pb_type_module, 0, src_module_port_id, src_port.pins()[pin_id]); } break; default: diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.cpp b/openfpga/src/utils/openfpga_physical_tile_utils.cpp index 9b4eeba16..95942ccaf 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.cpp +++ b/openfpga/src/utils/openfpga_physical_tile_utils.cpp @@ -8,12 +8,50 @@ #include "vtr_assert.h" #include "vtr_time.h" +/* Headers from openfpgautil library */ +#include "openfpga_side_manager.h" + #include "openfpga_device_grid_utils.h" #include "openfpga_physical_tile_utils.h" /* begin namespace openfpga */ namespace openfpga { +/******************************************************************** + * Give a given pin index, find the side where this pin is located + * on the physical tile + * Note: + * - Need to check if the pin_width_offset and pin_height_offset + * are properly set in VPR!!! + *******************************************************************/ +std::vector find_physical_tile_pin_side(t_physical_tile_type_ptr physical_tile, + const int& physical_pin, + const e_side& border_side) { + std::vector pin_sides; + for (const e_side& side_cand : {TOP, RIGHT, BOTTOM, LEFT}) { + int pin_width_offset = physical_tile->pin_width_offset[physical_pin]; + int pin_height_offset = physical_tile->pin_height_offset[physical_pin]; + if (true == physical_tile->pinloc[pin_width_offset][pin_height_offset][side_cand][physical_pin]) { + pin_sides.push_back(side_cand); + } + } + + /* For regular grid, we should have pin only one side! + * I/O grids: VPR creates the grid with duplicated pins on every side + * but the expected side (only used side) will be opposite side of the border side! + */ + if (NUM_SIDES == border_side) { + VTR_ASSERT(1 == pin_sides.size()); + } else { + SideManager side_manager(border_side); + VTR_ASSERT(pin_sides.end() != std::find(pin_sides.begin(), pin_sides.end(), side_manager.get_opposite())); + pin_sides.clear(); + pin_sides.push_back(side_manager.get_opposite()); + } + + return pin_sides; +} + /******************************************************************** * Find the Fc of a pin in physical tile *******************************************************************/ diff --git a/openfpga/src/utils/openfpga_physical_tile_utils.h b/openfpga/src/utils/openfpga_physical_tile_utils.h index b2b39ab65..b30ac4b76 100644 --- a/openfpga/src/utils/openfpga_physical_tile_utils.h +++ b/openfpga/src/utils/openfpga_physical_tile_utils.h @@ -17,6 +17,10 @@ /* begin namespace openfpga */ namespace openfpga { +std::vector find_physical_tile_pin_side(t_physical_tile_type_ptr physical_tile, + const int& physical_pin, + const e_side& border_side); + float find_physical_tile_pin_Fc(t_physical_tile_type_ptr type, const int& pin); diff --git a/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_cc_openfpga.xml new file mode 100644 index 000000000..d3f4baf4b --- /dev/null +++ b/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_cc_openfpga.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + 10e-12 + + + 10e-12 + + + + + + + + + + + + + 10e-12 5e-12 5e-12 + + + 10e-12 5e-12 5e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_clock/config/task.conf b/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_clock/config/task.conf new file mode 100644 index 000000000..55f5a13d0 --- /dev/null +++ b/openfpga_flow/tasks/basic_tests/global_tile_ports/global_tile_clock/config/task.conf @@ -0,0 +1,34 @@ +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# Configuration file for running experiments +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs +# Each job execute fpga_flow script on combination of architecture & benchmark +# timeout_each_job is timeout for each job +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +[GENERAL] +run_engine=openfpga_shell +power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml +power_analysis = true +spice_output=false +verilog_output=true +timeout_each_job = 20*60 +fpga_flow=yosys_vpr + +[OpenFPGA_SHELL] +openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/configuration_chain_example_script.openfpga +openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_GlobalTileClk_cc_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/k4_N4_tileable_GlobalTileClk_40nm.xml + +[BENCHMARKS] +bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v + +[SYNTHESIS_PARAM] +bench0_top = and2 +bench0_chan_width = 300 + +[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH] +end_flow_with_test= diff --git a/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_40nm.xml b/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_40nm.xml new file mode 100644 index 000000000..9d6f7d31d --- /dev/null +++ b/openfpga_flow/vpr_arch/k4_N4_tileable_GlobalTileClk_40nm.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + io.outpad io.inpad + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 1 1 1 1 + 1 1 1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 261e-12 + 261e-12 + 261e-12 + 261e-12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +