yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
const2ast.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
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.
9  *
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.
17  *
18  * ---
19  *
20  * The Verilog frontend.
21  *
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.
26  *
27  * ---
28  *
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.
34  *
35  */
36 
37 #include "verilog_frontend.h"
38 #include "kernel/log.h"
39 #include <string.h>
40 #include <math.h>
41 
43 
44 using namespace AST;
45 
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)
48 {
49  int carry = 0;
50  for (size_t i = 0; i < digits.size(); i++) {
51  log_assert(digits[i] < 10);
52  digits[i] += carry * 10;
53  carry = digits[i] % 2;
54  digits[i] /= 2;
55  }
56  while (!digits.empty() && !digits.front())
57  digits.erase(digits.begin());
58  return carry;
59 }
60 
61 // find the number of significant bits in a binary number (not including the sign bit)
62 static int my_ilog2(int x)
63 {
64  int ret = 0;
65  while (x != 0 && x != -1) {
66  x = x >> 1;
67  ret++;
68  }
69  return ret;
70 }
71 
72 // parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
73 static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type)
74 {
75  // all digits in string (MSB at index 0)
76  std::vector<uint8_t> digits;
77 
78  while (*str) {
79  if ('0' <= *str && *str <= '9')
80  digits.push_back(*str - '0');
81  else if ('a' <= *str && *str <= 'f')
82  digits.push_back(10 + *str - 'a');
83  else if ('A' <= *str && *str <= 'F')
84  digits.push_back(10 + *str - 'A');
85  else if (*str == 'x' || *str == 'X')
86  digits.push_back(0xf0);
87  else if (*str == 'z' || *str == 'Z')
88  digits.push_back(0xf1);
89  else if (*str == '?')
90  digits.push_back(0xf2);
91  str++;
92  }
93 
94  if (base == 10) {
95  data.clear();
96  if (len_in_bits < 0) {
97  while (!digits.empty())
98  data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
99  while (data.size() < 32)
100  data.push_back(RTLIL::S0);
101  } else {
102  for (int i = 0; i < len_in_bits; i++)
103  data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
104  }
105  return;
106  }
107 
108  int bits_per_digit = my_ilog2(base-1);
109  if (len_in_bits < 0)
110  len_in_bits = std::max<int>(digits.size() * bits_per_digit, 32);
111 
112  data.clear();
113  data.resize(len_in_bits);
114 
115  for (int i = 0; i < len_in_bits; i++) {
116  int bitmask = 1 << (i % bits_per_digit);
117  int digitidx = digits.size() - (i / bits_per_digit) - 1;
118  if (digitidx < 0) {
119  if (i > 0 && (data[i-1] == RTLIL::Sz || data[i-1] == RTLIL::Sx || data[i-1] == RTLIL::Sa))
120  data[i] = data[i-1];
121  else
122  data[i] = RTLIL::S0;
123  } else if (digits[digitidx] == 0xf0)
124  data[i] = case_type == 'x' ? RTLIL::Sa : RTLIL::Sx;
125  else if (digits[digitidx] == 0xf1)
126  data[i] = case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz;
127  else if (digits[digitidx] == 0xf2)
128  data[i] = RTLIL::Sa;
129  else
130  data[i] = (digits[digitidx] & bitmask) ? RTLIL::S1 : RTLIL::S0;
131  }
132 }
133 
134 // convert the verilog code for a constant to an AST node
135 AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z)
136 {
137  if (warn_z) {
138  AstNode *ret = const2ast(code, case_type);
139  if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
140  log_warning("Yosys does not support tri-state logic at the moment. (%s:%d)\n",
142  return ret;
143  }
144 
145  const char *str = code.c_str();
146 
147  // Strings
148  if (*str == '"') {
149  int len = strlen(str) - 2;
150  std::vector<RTLIL::State> data;
151  data.reserve(len * 8);
152  for (int i = 0; i < len; i++) {
153  unsigned char ch = str[len - i];
154  for (int j = 0; j < 8; j++) {
155  data.push_back((ch & 1) ? RTLIL::S1 : RTLIL::S0);
156  ch = ch >> 1;
157  }
158  }
159  AstNode *ast = AstNode::mkconst_bits(data, false);
160  ast->str = code;
161  return ast;
162  }
163 
164  for (size_t i = 0; i < code.size(); i++)
165  if (code[i] == '_' || code[i] == ' ' || code[i] == '\t' || code[i] == '\r' || code[i] == '\n')
166  code.erase(code.begin()+(i--));
167  str = code.c_str();
168 
169  char *endptr;
170  long len_in_bits = strtol(str, &endptr, 10);
171 
172  // Simple base-10 integer
173  if (*endptr == 0) {
174  std::vector<RTLIL::State> data;
175  my_strtobin(data, str, -1, 10, case_type);
176  if (data.back() == RTLIL::S1)
177  data.push_back(RTLIL::S0);
178  return AstNode::mkconst_bits(data, true);
179  }
180 
181  // unsized constant
182  if (str == endptr)
183  len_in_bits = -1;
184 
185  // The "<bits>'s?[bodhBODH]<digits>" syntax
186  if (*endptr == '\'')
187  {
188  std::vector<RTLIL::State> data;
189  bool is_signed = false;
190  if (*(endptr+1) == 's') {
191  is_signed = true;
192  endptr++;
193  }
194  switch (*(endptr+1))
195  {
196  case 'b':
197  case 'B':
198  my_strtobin(data, endptr+2, len_in_bits, 2, case_type);
199  break;
200  case 'o':
201  case 'O':
202  my_strtobin(data, endptr+2, len_in_bits, 8, case_type);
203  break;
204  case 'd':
205  case 'D':
206  my_strtobin(data, endptr+2, len_in_bits, 10, case_type);
207  break;
208  case 'h':
209  case 'H':
210  my_strtobin(data, endptr+2, len_in_bits, 16, case_type);
211  break;
212  default:
213  return NULL;
214  }
215  if (len_in_bits < 0) {
216  if (is_signed && data.back() == RTLIL::S1)
217  data.push_back(RTLIL::S0);
218  while (data.size() < 32)
219  data.push_back(RTLIL::S0);
220  }
221  return AstNode::mkconst_bits(data, is_signed);
222  }
223 
224  return NULL;
225 }
226 
228 
void log_warning(const char *format,...)
Definition: log.cc:196
static AstNode * mkconst_bits(const std::vector< RTLIL::State > &v, bool is_signed)
Definition: ast.cc:688
#define YOSYS_NAMESPACE_END
Definition: yosys.h:100
static int my_decimal_div_by_two(std::vector< uint8_t > &digits)
Definition: const2ast.cc:47
int frontend_verilog_yyget_lineno(void)
#define log_assert(_assert_expr_)
Definition: log.h:85
std::string current_filename
Definition: ast.cc:49
#define NULL
#define YOSYS_NAMESPACE_BEGIN
Definition: yosys.h:99
std::string str
Definition: ast.h:156
AST::AstNode * const2ast(std::string code, char case_type=0, bool warn_z=false)
Definition: const2ast.cc:135
static bool find(V &ts, const T &t)
Definition: Alg.h:47
std::vector< RTLIL::State > bits
Definition: ast.h:157
static void my_strtobin(std::vector< RTLIL::State > &data, const char *str, int len_in_bits, int base, char case_type)
Definition: const2ast.cc:73
static int my_ilog2(int x)
Definition: const2ast.cc:62