Skip to content

EBLIF cell parameter interpretation #1663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 24, 2022
25 changes: 22 additions & 3 deletions doc/src/vpr/file_formats.rst
Original file line number Diff line number Diff line change
Expand Up @@ -391,17 +391,36 @@ The ``.param`` statement allows parameters (e.g. primitive modes) to be tagged o

.. note:: ``.param`` statements apply to the previous primitive instantiation.

Parameters can have one of the three available types. Type is inferred from the format in which a parameter is provided.

* **string**
Whenever a parameter value is quoted it is considered to be a string. BLIF parser does not allow escaped characters hence those are illegal and will cause syntax errors.

* **binary word**
Binary words are specified using strings of characters ``0`` and ``1``. No other characters are allowed. Number of characters denotes the word length.

* **real number**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is .param x 2? A real number or error?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its an error. For an integer 2 you need 10, for a real 2 you need 2.0.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to make clear that 2 is illegal, because it is not a binary word (has a 2) and is not a string (no quotes) and not a real number (no .).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added clearer explanation of illegal formats

Real numbers are stored as decimals where the dot ``.`` character separates the integer and fractional part. Presence of the dot character implies that the value is to be treated as a real number.

For example:

.. code-block:: none

.subckt dsp a=a_in b=b_in cin=c_in cout=c_out s=sum_out
.param mode adder
.subckt pll clk_in=gclk clk_out=pclk
.param feedback "internal"
.param multiplier 0.50
.param power 001101

Would set the parameter ``mode`` of the above ``dsp`` ``.subckt`` to ``adder``.
Would set the parameters ``feedback``, ``multiplier`` and ``power`` of the above ``pll`` ``.subckt`` to ``"internal"``, ``0.50`` and ``001101`` respectively.

.. warning:: Integers in notation other than binary (e.g. decimal, hexadecimal) are not supported. Occurrence of params with digits other than 1 and 0 for binary words, not quoted (strings) or not separated with dot ``.`` (real numbers) are considered to be illegal.

Interpretation of parameter values is out of scope of the BLIF format extension.

``.param`` statements propagate to ``<parameter>`` elements in the packed netlist.

Paramerer values propagate also to the post-route Verilog netlist, if it is generated. Strings and real numbers are passed directly while binary words are prepended with the ``<N>'b`` prefix where ``N`` denotes a binary word length.

.attr
~~~~~
The ``.attr`` statement allows attributes (e.g. source file/line) to be tagged on BLIF primitives.
Expand Down
10 changes: 9 additions & 1 deletion vpr/src/base/netlist_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "vpr_error.h"
#include "vpr_types.h"

#include "read_blif.h"

#include "netlist_walker.h"
#include "netlist_writer.h"

Expand Down Expand Up @@ -625,7 +627,13 @@ class BlackBoxInst : public Instance {

//Verilog parameters
for (auto iter = params_.begin(); iter != params_.end(); ++iter) {
os << indent(depth + 1) << "." << iter->first << "(" << iter->second << ")";
/* Prepend a prefix if needed */
std::stringstream prefix;
if (is_binary_param(iter->second)) {
prefix << iter->second.length() << "'b";
}

os << indent(depth + 1) << "." << iter->first << "(" << prefix.str() << iter->second << ")";
if (iter != --params_.end()) {
os << ",";
}
Expand Down
71 changes: 71 additions & 0 deletions vpr/src/base/read_blif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <sstream>
#include <unordered_set>
#include <cctype> //std::isdigit
#include <algorithm>
#include <regex>

#include "blifparse.hpp"
#include "atom_netlist.h"
Expand Down Expand Up @@ -386,6 +388,14 @@ struct BlifAllocCallback : public blifparse::Callback {
parse_error(lineno_, ".param", "Supported only in extended BLIF format");
}

// Validate the parameter value
bool is_valid = is_string_param(value) || is_binary_param(value) || is_real_param(value);

if (!is_valid) {
std::string msg = "Incorrect parameter '" + name + "' value specification. Value '" + value + "' is not recognized as string, binary word or real number. Possible causes:\n\t* lack or inconsistency in quotes (string)\n\t* no dot '.' to separate integer and fractional part (real number)\n\t* use of characters other than '1' and '0' (binary word)";
parse_error(lineno_, ".param", msg);
}

curr_model().set_block_param(curr_block(), name, value);
}

Expand Down Expand Up @@ -666,6 +676,67 @@ vtr::LogicValue to_vtr_logic_value(blifparse::LogicValue val) {
return new_val;
}

bool is_string_param(const std::string& param) {
/* Empty param is considered a string */
if (param.empty()) {
return true;
}

/* There have to be at least 2 characters (the quotes) */
if (param.length() < 2) {
return false;
}

/* The first and the last characters must be quotes */
size_t len = param.length();
if (param[0] != '"' || param[len - 1] != '"') {
return false;
}

/* There mustn't be any other quotes except for escaped ones */
for (size_t i = 1; i < (len - 1); ++i) {
if (param[i] == '"' && param[i - 1] != '\\') {
return false;
}
}

/* This is a string param */
return true;
}

bool is_binary_param(const std::string& param) {
/* Must be non-empty */
if (param.empty()) {
return false;
}

/* The string must contain only '0' and '1' */
for (size_t i = 0; i < param.length(); ++i) {
if (param[i] != '0' && param[i] != '1') {
return false;
}
}

/* This is a binary word param */
return true;
}

bool is_real_param(const std::string& param) {
/* Must be non-empty */
if (param.empty()) {
return false;
}

/* The string must match the regular expression */
static const std::regex real_number_expr("[+-]?([0-9]*\\.[0-9]+)|([0-9]+\\.[0-9]*)");
if (!std::regex_match(param, real_number_expr)) {
return false;
}

/* This is a real number param */
return true;
}

AtomNetlist read_blif(e_circuit_format circuit_format,
const char* blif_file,
const t_model* user_models,
Expand Down
4 changes: 4 additions & 0 deletions vpr/src/base/read_blif.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#include "atom_netlist_fwd.h"
#include "read_circuit.h"

bool is_string_param(const std::string& param);
bool is_binary_param(const std::string& param);
bool is_real_param(const std::string& param);

AtomNetlist read_blif(e_circuit_format circuit_format,
const char* blif_file,
const t_model* user_models,
Expand Down
8 changes: 6 additions & 2 deletions vtr_flow/benchmarks/tests/test_eblif.eblif
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
.names a b a_and_b
11 1
.cname lut_a_and_b
.param test_names_param "test_names_param_value"
.param test_names_param_str "test_names_param_str_value"
.param test_names_param_bin 00110101
.param test_names_param_num 2.0
.attr test_names_attrib "test_names_param_attrib"

.latch a_and_b dff_q re clk 0
.cname my_dff
.param test_latch_param "test_latch_param_value"
.param test_latch_param "test_latch_param_str_value"
.param test_latch_param_bin 00110101
.param test_latch_param_num 2.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need negative tests here!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I recommend reviewing the failure output to make sure it is possible to understand the problem from the error message. Concrete things I'd look for:

  • Is the location of the error made clear (e.g. file and line number)
  • Is there an explanation of why the input was wrong?
  • For example, missing quotes
  • A bare integer with no period

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that VPR at this point doesn't support test cases that are meant to fail (however https://github.com/verilog-to-routing/vtr-verilog-to-routing/blob/master/vtr_flow/scripts/python_libs/vtr/util.py#L73-L75 allows that but this parameter is not used anywhere in the test framework).
Anyway, I tested the error output and modified it to provide more useful information.

.attr test_latch_attrib "test_latch_param_attrib"

.conn dff_q o_dff
Expand Down