Added support for unsized constants, fixes #1022
authorMiodrag Milanovic <mmicko@gmail.com>
Mon, 27 May 2019 09:42:10 +0000 (11:42 +0200)
committerMiodrag Milanovic <mmicko@gmail.com>
Mon, 27 May 2019 09:42:10 +0000 (11:42 +0200)
Includes work from @sumit0190 and @AaronKel

frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/verilog/const2ast.cc
frontends/verilog/verilog_lexer.l

index 5623541b2a68f9a6917912818c9cd2bd5f194d8a..29e175c1580b9760938c2a7e0b67c6e5cefc6ef4 100644 (file)
@@ -194,6 +194,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
        is_logic = false;
        is_signed = false;
        is_string = false;
+       is_unsized = false;
        was_checked = false;
        range_valid = false;
        range_swapped = false;
@@ -722,7 +723,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
 }
 
 // create an AST node for a constant (using a bit vector as value)
-AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
+AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
 {
        AstNode *node = new AstNode(AST_CONSTANT);
        node->is_signed = is_signed;
@@ -736,9 +737,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
        node->range_valid = true;
        node->range_left = node->bits.size()-1;
        node->range_right = 0;
+       node->is_unsized = is_unsized;
        return node;
 }
 
+AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
+{
+       return mkconst_bits(v, is_signed, false);
+}
+
 // create an AST node for a constant (using a string in bit vector form as value)
 AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
 {
@@ -775,6 +782,14 @@ bool AstNode::bits_only_01() const
        return true;
 }
 
+RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
+{
+       RTLIL::State extbit = bits.back();
+       while (width > int(bits.size()))
+               bits.push_back(extbit);
+       return RTLIL::Const(bits);
+}
+
 RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
 {
        std::vector<RTLIL::State> bits = this->bits;
index 281cbe0865ba8987fed475e9c7d71944c3ab9d14..f90e683ad8c4b1b57b3e079047dca877b865961c 100644 (file)
@@ -173,7 +173,7 @@ namespace AST
                // node content - most of it is unused in most node types
                std::string str;
                std::vector<RTLIL::State> bits;
-               bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked;
+               bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked, is_unsized;
                int port_id, range_left, range_right;
                uint32_t integer;
                double realvalue;
@@ -262,6 +262,7 @@ namespace AST
 
                // helper functions for creating AST nodes for constants
                static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32);
+               static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
                static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
                static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
                static AstNode *mkconst_str(const std::string &str);
@@ -269,6 +270,7 @@ namespace AST
                // helper function for creating sign-extended const objects
                RTLIL::Const bitsAsConst(int width, bool is_signed);
                RTLIL::Const bitsAsConst(int width = -1);
+               RTLIL::Const bitsAsUnsizedConst(int width);
                RTLIL::Const asAttrConst();
                RTLIL::Const asParaConst();
                uint64_t asInt(bool is_signed);
index 379fed641a73c1657ccd233704f931c2692729d7..d9dfc17cc3056bd4a0ff1cd821e0bd5a3e74efd2 100644 (file)
@@ -963,8 +963,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                detectSignWidth(width_hint, sign_hint);
                        is_signed = sign_hint;
 
-                       if (type == AST_CONSTANT)
-                               return RTLIL::SigSpec(bitsAsConst());
+                       if (type == AST_CONSTANT) {
+                               if (is_unsized) {
+                                       return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint));
+                               } else {
+                                       return RTLIL::SigSpec(bitsAsConst());
+                               }
+                       }
 
                        RTLIL::SigSpec sig = realAsConst(width_hint);
                        log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
index 7848c626d58cdbfcb23a8084ae4b24c8dfd05189..57d366dbfed3e8e812dfeb838d8f2628c86d824d 100644 (file)
@@ -71,7 +71,7 @@ static int my_ilog2(int x)
 }
 
 // parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
-static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type)
+static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized)
 {
        // all digits in string (MSB at index 0)
        std::vector<uint8_t> digits;
@@ -129,6 +129,9 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
                return;
        }
 
+       if (is_unsized && (len > len_in_bits))
+               log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
+
        for (len = len - 1; len >= 0; len--)
                if (data[len] == RTLIL::S1)
                        break;
@@ -186,7 +189,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
        // Simple base-10 integer
        if (*endptr == 0) {
                std::vector<RTLIL::State> data;
-               my_strtobin(data, str, -1, 10, case_type);
+               my_strtobin(data, str, -1, 10, case_type, false);
                if (data.back() == RTLIL::S1)
                        data.push_back(RTLIL::S0);
                return AstNode::mkconst_bits(data, true);
@@ -201,6 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
        {
                std::vector<RTLIL::State> data;
                bool is_signed = false;
+               bool is_unsized = false;
                if (*(endptr+1) == 's') {
                        is_signed = true;
                        endptr++;
@@ -209,28 +213,34 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
                {
                case 'b':
                case 'B':
-                       my_strtobin(data, endptr+2, len_in_bits, 2, case_type);
+                       my_strtobin(data, endptr+2, len_in_bits, 2, case_type, false);
                        break;
                case 'o':
                case 'O':
-                       my_strtobin(data, endptr+2, len_in_bits, 8, case_type);
+                       my_strtobin(data, endptr+2, len_in_bits, 8, case_type, false);
                        break;
                case 'd':
                case 'D':
-                       my_strtobin(data, endptr+2, len_in_bits, 10, case_type);
+                       my_strtobin(data, endptr+2, len_in_bits, 10, case_type, false);
                        break;
                case 'h':
                case 'H':
-                       my_strtobin(data, endptr+2, len_in_bits, 16, case_type);
+                       my_strtobin(data, endptr+2, len_in_bits, 16, case_type, false);
                        break;
                default:
-                       return NULL;
+                       char next_char = char(tolower(*(endptr+1)));
+                       if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') {
+                               my_strtobin(data, endptr+1, 1, 2, case_type, true);
+                               is_unsized = true;
+                       } else {
+                               return NULL;
+                       }
                }
                if (len_in_bits < 0) {
                        if (is_signed && data.back() == RTLIL::S1)
                                data.push_back(RTLIL::S0);
                }
-               return AstNode::mkconst_bits(data, is_signed);
+               return AstNode::mkconst_bits(data, is_signed, is_unsized);
        }
 
        return NULL;
index 142d05d45be2c73966779644414f688822001b9b..d89e144a9af9ff5de009e2370376d32f6f627d0c 100644 (file)
@@ -232,7 +232,7 @@ YOSYS_NAMESPACE_END
        return TOK_CONSTVAL;
 }
 
-[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
+[0-9]*[ \t]*\'s?[bodhBODH]*[ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
        frontend_verilog_yylval.string = new std::string(yytext);
        return TOK_CONSTVAL;
 }