2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * The Verilog frontend.
22 * This frontend is using the AST frontend library (see frontends/ast/).
23 * Thus this frontend does not generate RTLIL code directly but creates an
24 * AST directly from the Verilog parse tree and then passes this AST to
25 * the AST frontend library.
29 * This file contains an ad-hoc parser for Verilog constants. The Verilog
30 * lexer does only recognize a constant but does not actually split it to its
31 * components. I.e. it just passes the Verilog code for the constant to the
32 * bison parser. The parser then uses the function const2ast() from this file
33 * to create an AST node for the constant.
37 #include "verilog_frontend.h"
38 #include "kernel/log.h"
46 // divide an arbitrary length decimal number by two and return the rest
47 static int my_decimal_div_by_two(std::vector
<uint8_t> &digits
)
50 for (size_t i
= 0; i
< digits
.size(); i
++) {
52 log_file_error(current_filename
, get_line_num(), "Invalid use of [a-fxz?] in decimal constant.\n");
53 digits
[i
] += carry
* 10;
54 carry
= digits
[i
] % 2;
57 while (!digits
.empty() && !digits
.front())
58 digits
.erase(digits
.begin());
62 // find the number of significant bits in a binary number (not including the sign bit)
63 static int my_ilog2(int x
)
66 while (x
!= 0 && x
!= -1) {
73 // parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
74 static void my_strtobin(std::vector
<RTLIL::State
> &data
, const char *str
, int len_in_bits
, int base
, char case_type
, bool is_unsized
)
76 // all digits in string (MSB at index 0)
77 std::vector
<uint8_t> digits
;
80 if ('0' <= *str
&& *str
<= '9')
81 digits
.push_back(*str
- '0');
82 else if ('a' <= *str
&& *str
<= 'f')
83 digits
.push_back(10 + *str
- 'a');
84 else if ('A' <= *str
&& *str
<= 'F')
85 digits
.push_back(10 + *str
- 'A');
86 else if (*str
== 'x' || *str
== 'X')
87 digits
.push_back(0xf0);
88 else if (*str
== 'z' || *str
== 'Z')
89 digits
.push_back(0xf1);
91 digits
.push_back(0xf2);
95 if (base
== 10 && GetSize(digits
) == 1 && digits
.front() >= 0xf0)
101 while (!digits
.empty())
102 data
.push_back(my_decimal_div_by_two(digits
) ? RTLIL::S1
: RTLIL::S0
);
104 int bits_per_digit
= my_ilog2(base
-1);
105 for (auto it
= digits
.rbegin(), e
= digits
.rend(); it
!= e
; it
++) {
106 if (*it
> (base
-1) && *it
< 0xf0)
107 log_file_error(current_filename
, get_line_num(), "Digit larger than %d used in in base-%d constant.\n",
109 for (int i
= 0; i
< bits_per_digit
; i
++) {
110 int bitmask
= 1 << i
;
112 data
.push_back(case_type
== 'x' ? RTLIL::Sa
: RTLIL::Sx
);
113 else if (*it
== 0xf1)
114 data
.push_back(case_type
== 'x' || case_type
== 'z' ? RTLIL::Sa
: RTLIL::Sz
);
115 else if (*it
== 0xf2)
116 data
.push_back(RTLIL::Sa
);
118 data
.push_back((*it
& bitmask
) ? RTLIL::S1
: RTLIL::S0
);
123 int len
= GetSize(data
);
124 RTLIL::State msb
= data
.empty() ? RTLIL::S0
: data
.back();
126 if (len_in_bits
< 0) {
128 data
.resize(32, msb
== RTLIL::S0
|| msb
== RTLIL::S1
? RTLIL::S0
: msb
);
132 if (is_unsized
&& (len
> len_in_bits
))
133 log_file_error(current_filename
, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len
);
135 for (len
= len
- 1; len
>= 0; len
--)
136 if (data
[len
] == RTLIL::S1
)
138 if (msb
== RTLIL::S0
|| msb
== RTLIL::S1
) {
140 data
.resize(len_in_bits
, RTLIL::S0
);
143 data
.resize(len_in_bits
, msb
);
146 if (len
> len_in_bits
)
147 log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n",
148 len_in_bits
, len
, current_filename
.c_str(), get_line_num());
151 // convert the Verilog code for a constant to an AST node
152 AstNode
*VERILOG_FRONTEND::const2ast(std::string code
, char case_type
, bool warn_z
)
155 AstNode
*ret
= const2ast(code
, case_type
);
156 if (std::find(ret
->bits
.begin(), ret
->bits
.end(), RTLIL::State::Sz
) != ret
->bits
.end())
157 log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n",
158 current_filename
.c_str(), get_line_num());
162 const char *str
= code
.c_str();
166 int len
= strlen(str
) - 2;
167 std::vector
<RTLIL::State
> data
;
168 data
.reserve(len
* 8);
169 for (int i
= 0; i
< len
; i
++) {
170 unsigned char ch
= str
[len
- i
];
171 for (int j
= 0; j
< 8; j
++) {
172 data
.push_back((ch
& 1) ? RTLIL::S1
: RTLIL::S0
);
176 AstNode
*ast
= AstNode::mkconst_bits(data
, false);
181 for (size_t i
= 0; i
< code
.size(); i
++)
182 if (code
[i
] == '_' || code
[i
] == ' ' || code
[i
] == '\t' || code
[i
] == '\r' || code
[i
] == '\n')
183 code
.erase(code
.begin()+(i
--));
187 long len_in_bits
= strtol(str
, &endptr
, 10);
189 // Simple base-10 integer
191 std::vector
<RTLIL::State
> data
;
192 my_strtobin(data
, str
, -1, 10, case_type
, false);
193 if (data
.back() == RTLIL::S1
)
194 data
.push_back(RTLIL::S0
);
195 return AstNode::mkconst_bits(data
, true);
202 // The "<bits>'s?[bodhBODH]<digits>" syntax
205 std::vector
<RTLIL::State
> data
;
206 bool is_signed
= false;
207 bool is_unsized
= false;
208 if (*(endptr
+1) == 's') {
216 my_strtobin(data
, endptr
+2, len_in_bits
, 2, case_type
, false);
220 my_strtobin(data
, endptr
+2, len_in_bits
, 8, case_type
, false);
224 my_strtobin(data
, endptr
+2, len_in_bits
, 10, case_type
, false);
228 my_strtobin(data
, endptr
+2, len_in_bits
, 16, case_type
, false);
231 char next_char
= char(tolower(*(endptr
+1)));
232 if (next_char
== '0' || next_char
== '1' || next_char
== 'x' || next_char
== 'z') {
233 my_strtobin(data
, endptr
+1, 1, 2, case_type
, true);
239 if (len_in_bits
< 0) {
240 if (is_signed
&& data
.back() == RTLIL::S1
)
241 data
.push_back(RTLIL::S0
);
243 return AstNode::mkconst_bits(data
, is_signed
, is_unsized
);