From 9074bffa68f8bcb3c142855bc15ecc08bf49c434 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 1 Jul 2021 23:43:19 -0600 Subject: [PATCH 1/3] [Tool] Support customized default value in pin constraint file --- libopenfpga/libpcf/src/pin_constraints.cpp | 51 +++++++++++++++++++ libopenfpga/libpcf/src/pin_constraints.h | 38 ++++++++++++++ .../libpcf/src/read_xml_pin_constraints.cpp | 8 +++ .../libpcf/src/write_xml_pin_constraints.cpp | 1 + .../verilog_formal_random_top_testbench.cpp | 4 ++ .../fpga_verilog/verilog_top_testbench.cpp | 8 ++- 6 files changed, 109 insertions(+), 1 deletion(-) diff --git a/libopenfpga/libpcf/src/pin_constraints.cpp b/libopenfpga/libpcf/src/pin_constraints.cpp index 25cd1048d..bc68b3bd8 100644 --- a/libopenfpga/libpcf/src/pin_constraints.cpp +++ b/libopenfpga/libpcf/src/pin_constraints.cpp @@ -60,6 +60,36 @@ openfpga::BasicPort PinConstraints::net_pin(const std::string& net) const { return constrained_pin; } +PinConstraints::e_logic_level PinConstraints::net_default_value(const std::string& net) const { + PinConstraints::e_logic_level logic_level = PinConstraints::NUM_LOGIC_LEVELS; + for (const PinConstraintId& pin_constraint : pin_constraints()) { + if (net == pin_constraint_nets_[pin_constraint]) { + logic_level = pin_constraint_net_default_values_[pin_constraint]; + break; + } + } + return logic_level; +} + +std::string PinConstraints::net_default_value_to_string(const PinConstraintId& pin_constraint) const { + VTR_ASSERT(valid_pin_constraint_id(pin_constraint)); + if (PinConstraints::LOGIC_HIGH == pin_constraint_net_default_values_[pin_constraint]) { + return std::string("1"); + } else if (PinConstraints::LOGIC_LOW == pin_constraint_net_default_values_[pin_constraint]) { + return std::string("0"); + } + return std::string(); +} + +size_t PinConstraints::net_default_value_to_int(const std::string& net) const { + if (PinConstraints::LOGIC_HIGH == net_default_value(net)) { + return 1; + } else if (PinConstraints::LOGIC_LOW == net_default_value(net)) { + return 0; + } + return -1; +} + bool PinConstraints::empty() const { return 0 == pin_constraint_ids_.size(); } @@ -71,6 +101,7 @@ void PinConstraints::reserve_pin_constraints(const size_t& num_pin_constraints) pin_constraint_ids_.reserve(num_pin_constraints); pin_constraint_pins_.reserve(num_pin_constraints); pin_constraint_nets_.reserve(num_pin_constraints); + pin_constraint_net_default_values_.reserve(num_pin_constraints); } PinConstraintId PinConstraints::create_pin_constraint(const openfpga::BasicPort& pin, @@ -81,10 +112,21 @@ PinConstraintId PinConstraints::create_pin_constraint(const openfpga::BasicPort& pin_constraint_ids_.push_back(pin_constraint_id); pin_constraint_pins_.push_back(pin); pin_constraint_nets_.push_back(net); + pin_constraint_net_default_values_.push_back(PinConstraints::NUM_LOGIC_LEVELS); return pin_constraint_id; } +void PinConstraints::set_net_default_value(const PinConstraintId& pin_constraint, + const std::string& default_value) { + VTR_ASSERT(valid_pin_constraint_id(pin_constraint)); + if (default_value == std::string("1")) { + pin_constraint_net_default_values_[pin_constraint] = PinConstraints::LOGIC_HIGH; + } else if (default_value == std::string("0")) { + pin_constraint_net_default_values_[pin_constraint] = PinConstraints::LOGIC_LOW; + } +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ @@ -100,3 +142,12 @@ bool PinConstraints::unconstrained_net(const std::string& net) const { bool PinConstraints::unmapped_net(const std::string& net) const { return std::string(PIN_CONSTRAINT_OPEN_NET) == net; } + +bool PinConstraints::valid_net_default_value(const PinConstraintId& pin_constraint) const { + VTR_ASSERT(valid_pin_constraint_id(pin_constraint)); + return PinConstraints::NUM_LOGIC_LEVELS != pin_constraint_net_default_values_[pin_constraint]; +} + +bool PinConstraints::valid_net_default_value(const std::string& net) const { + return PinConstraints::NUM_LOGIC_LEVELS != net_default_value(net); +} diff --git a/libopenfpga/libpcf/src/pin_constraints.h b/libopenfpga/libpcf/src/pin_constraints.h index 3ea3aad2f..a60f0aae4 100644 --- a/libopenfpga/libpcf/src/pin_constraints.h +++ b/libopenfpga/libpcf/src/pin_constraints.h @@ -41,6 +41,12 @@ class PinConstraints { typedef vtr::vector::const_iterator pin_constraint_iterator; /* Create range */ typedef vtr::Range pin_constraint_range; + /* Logic value */ + enum e_logic_level { + LOGIC_HIGH, + LOGIC_LOW, + NUM_LOGIC_LEVELS + }; public: /* Constructors */ PinConstraints(); public: /* Accessors: aggregates */ @@ -63,6 +69,21 @@ class PinConstraints { */ openfpga::BasicPort net_pin(const std::string& net) const; + /* Find the default value that a net is constrained to + * If not found, return an invalid value + */ + e_logic_level net_default_value(const std::string& net) const; + + /* Generate the string of the default value + * If not found, return an empty string + */ + std::string net_default_value_to_string(const PinConstraintId& pin_constraint) const; + + /* Generate the integer representation of the default value + * If not found, return -1 + */ + size_t net_default_value_to_int(const std::string& net) const; + /* Check if there are any pin constraints */ bool empty() const; @@ -74,6 +95,10 @@ class PinConstraints { PinConstraintId create_pin_constraint(const openfpga::BasicPort& pin, const std::string& net); + /* Set the default value for the net under a given pin constraint */ + void set_net_default_value(const PinConstraintId& pin_constraint, + const std::string& default_value); + public: /* Public invalidators/validators */ /* Show if the pin constraint id is a valid for data queries */ bool valid_pin_constraint_id(const PinConstraintId& pin_constraint_id) const; @@ -91,6 +116,16 @@ class PinConstraints { * - net() */ bool unmapped_net(const std::string& net) const; + + /* Check if default value is a valid one or not + * This is to check if the default value is constrained or not + */ + bool valid_net_default_value(const PinConstraintId& pin_constraint) const; + + /* Check if default value is a valid one or not + * This is to check if the default value is constrained or not + */ + bool valid_net_default_value(const std::string& net) const; private: /* Internal data */ /* Unique ids for each design constraint */ vtr::vector pin_constraint_ids_; @@ -100,6 +135,9 @@ class PinConstraints { /* Nets to constraint */ vtr::vector pin_constraint_nets_; + + /* Default value of the nets to constraint */ + vtr::vector pin_constraint_net_default_values_; }; #endif diff --git a/libopenfpga/libpcf/src/read_xml_pin_constraints.cpp b/libopenfpga/libpcf/src/read_xml_pin_constraints.cpp index b0c662da5..98527cb32 100644 --- a/libopenfpga/libpcf/src/read_xml_pin_constraints.cpp +++ b/libopenfpga/libpcf/src/read_xml_pin_constraints.cpp @@ -41,6 +41,14 @@ void read_xml_pin_constraint(pugi::xml_node& xml_pin_constraint, archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint), "Fail to create pin constraint!\n"); } + + /* Set default value if defined */ + std::string default_value = get_attribute(xml_pin_constraint, "default_value", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(); + pin_constraints.set_net_default_value(pin_constraint_id, default_value); + if (!default_value.empty() && !pin_constraints.valid_net_default_value(pin_constraint_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin_constraint), + "Invalid default value for pin constraints. Expect [0|1]!\n"); + } } /******************************************************************** diff --git a/libopenfpga/libpcf/src/write_xml_pin_constraints.cpp b/libopenfpga/libpcf/src/write_xml_pin_constraints.cpp index 80a664f3f..ef728be95 100644 --- a/libopenfpga/libpcf/src/write_xml_pin_constraints.cpp +++ b/libopenfpga/libpcf/src/write_xml_pin_constraints.cpp @@ -44,6 +44,7 @@ int write_xml_pin_constraint(std::fstream& fp, write_xml_attribute(fp, "pin", generate_xml_port_name(pin_constraints.pin(pin_constraint)).c_str()); write_xml_attribute(fp, "net", pin_constraints.net(pin_constraint).c_str()); + write_xml_attribute(fp, "default_value", pin_constraints.net_default_value_to_string(pin_constraint).c_str()); fp << "/>" << "\n"; diff --git a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp index 7194f208f..6be38f425 100644 --- a/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_formal_random_top_testbench.cpp @@ -213,6 +213,10 @@ void print_verilog_random_testbench_reset_stimuli(std::fstream& fp, if (1 == global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name)))) { initial_value = 0; } + /* Pin constraints has the final decision on the default value */ + if (pin_constraints.valid_net_default_value(block_name)) { + initial_value = pin_constraints.net_default_value_to_int(block_name); + } fp << "initial" << std::endl; fp << "\tbegin" << std::endl; diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp index 47300ce1e..1e82b7e81 100644 --- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp +++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp @@ -1789,11 +1789,17 @@ void print_verilog_top_testbench_reset_stimuli(std::fstream& fp, continue; } + /* Pin constraints has the final decision on the default value */ + size_t initial_value = global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name))); + if (pin_constraints.valid_net_default_value(block_name)) { + initial_value = pin_constraints.net_default_value_to_int(block_name); + } + /* Connect stimuli to greset with an optional inversion, depending on the default value */ BasicPort reset_port(block_name, 1); print_verilog_wire_connection(fp, reset_port, BasicPort(TOP_TB_RESET_PORT_NAME, 1), - 1 == global_ports.global_port_default_value(find_fabric_global_port(global_ports, module_manager, pin_constraints.net_pin(block_name)))); + 1 == initial_value); } } From 0851075bc96fe9bd4116bf7e65f89aeeb90ff372 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 1 Jul 2021 23:47:36 -0600 Subject: [PATCH 2/3] [Doc] Update documentation about the new feature in pin constraint file --- docs/source/manual/file_formats/pin_constraints_file.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/file_formats/pin_constraints_file.rst b/docs/source/manual/file_formats/pin_constraints_file.rst index c2a71c596..a172396f1 100644 --- a/docs/source/manual/file_formats/pin_constraints_file.rst +++ b/docs/source/manual/file_formats/pin_constraints_file.rst @@ -10,7 +10,7 @@ An example of design constraints is shown as follows. .. code-block:: xml - + @@ -23,3 +23,9 @@ An example of design constraints is shown as follows. .. option:: net="" The net name of the pin to be mapped, which should be consistent with net definition in your ``.blif`` file. The reserved word ``OPEN`` means that no net should be mapped to a given pin. Please ensure that it is not conflicted with any net names in your ``.blif`` file. + +.. option:: default_value="" + + The default value of a net to be constrained. This is mainly used when generating testbenches. Valid value is ``0`` or ``1``. If defined as ``1``, the net is be driven by the inversion of its stimuli. + + .. note:: This feature is mainly used to generate the correct stimuli for some pin whose polarity can be configurable. For example, the ``Reset`` pin of an FPGA fabric may be active-low or active-high depending on its configuration. From 43afaca17c0b406d3b58a347dd37677fd4b90ed0 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 1 Jul 2021 23:51:54 -0600 Subject: [PATCH 3/3] [Doc] Add more details about the new syntax --- docs/source/manual/file_formats/pin_constraints_file.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/manual/file_formats/pin_constraints_file.rst b/docs/source/manual/file_formats/pin_constraints_file.rst index a172396f1..063b27542 100644 --- a/docs/source/manual/file_formats/pin_constraints_file.rst +++ b/docs/source/manual/file_formats/pin_constraints_file.rst @@ -29,3 +29,5 @@ An example of design constraints is shown as follows. The default value of a net to be constrained. This is mainly used when generating testbenches. Valid value is ``0`` or ``1``. If defined as ``1``, the net is be driven by the inversion of its stimuli. .. note:: This feature is mainly used to generate the correct stimuli for some pin whose polarity can be configurable. For example, the ``Reset`` pin of an FPGA fabric may be active-low or active-high depending on its configuration. + + .. note:: The default value in pin constraint file has a higher priority than the ``default_value`` syntax in the :ref:`circuit_library`.