diff options
author | Ahmed Irfan <ahmedirfan1983@gmail.com> | 2014-01-03 10:54:54 +0100 |
---|---|---|
committer | Ahmed Irfan <ahmedirfan1983@gmail.com> | 2014-01-03 10:54:54 +0100 |
commit | 06482c046bcab4e2b9603f8954ce0f2fd501a73b (patch) | |
tree | d160ad05402768e4f468ff0685593b81658e6a5a /frontends | |
parent | 5da334fc2efd66c8a5efde925bb18212c34d0cef (diff) | |
parent | fb2bf934dc6d2c969906b350c9a1b09a972bfdd7 (diff) | |
download | yosys-06482c046bcab4e2b9603f8954ce0f2fd501a73b.tar.gz yosys-06482c046bcab4e2b9603f8954ce0f2fd501a73b.tar.bz2 yosys-06482c046bcab4e2b9603f8954ce0f2fd501a73b.zip |
Merge branch 'master' of https://github.com/cliffordwolf/yosys into btor
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.cc | 4 | ||||
-rw-r--r-- | frontends/ast/ast.h | 2 | ||||
-rw-r--r-- | frontends/ast/genrtlil.cc | 18 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 19 | ||||
-rw-r--r-- | frontends/verilog/lexer.l | 4 | ||||
-rw-r--r-- | frontends/verilog/parser.y | 10 | ||||
-rw-r--r-- | frontends/verilog/preproc.cc | 122 |
7 files changed, 138 insertions, 41 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 0e65f1cb7..201584885 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -103,6 +103,8 @@ std::string AST::type2str(AstNodeType type) X(AST_LE) X(AST_EQ) X(AST_NE) + X(AST_EQX) + X(AST_NEX) X(AST_GE) X(AST_GT) X(AST_ADD) @@ -539,6 +541,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) if (0) { case AST_LE: txt = "<="; } if (0) { case AST_EQ: txt = "=="; } if (0) { case AST_NE: txt = "!="; } + if (0) { case AST_EQX: txt = "==="; } + if (0) { case AST_NEX: txt = "!=="; } if (0) { case AST_GE: txt = ">="; } if (0) { case AST_GT: txt = ">"; } if (0) { case AST_ADD: txt = "+"; } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index f8e279274..22853d0f9 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -82,6 +82,8 @@ namespace AST AST_LE, AST_EQ, AST_NE, + AST_EQX, + AST_NEX, AST_GE, AST_GT, AST_ADD, diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 269752df5..e44b2d361 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -728,6 +728,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint) case AST_LE: case AST_EQ: case AST_NE: + case AST_EQX: + case AST_NEX: case AST_GE: case AST_GT: width_hint = std::max(width_hint, 1); @@ -1113,12 +1115,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) } // generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt - if (0) { case AST_LT: type_name = "$lt"; } - if (0) { case AST_LE: type_name = "$le"; } - if (0) { case AST_EQ: type_name = "$eq"; } - if (0) { case AST_NE: type_name = "$ne"; } - if (0) { case AST_GE: type_name = "$ge"; } - if (0) { case AST_GT: type_name = "$gt"; } + if (0) { case AST_LT: type_name = "$lt"; } + if (0) { case AST_LE: type_name = "$le"; } + if (0) { case AST_EQ: type_name = "$eq"; } + if (0) { case AST_NE: type_name = "$ne"; } + if (0) { case AST_EQX: type_name = "$eqx"; } + if (0) { case AST_NEX: type_name = "$nex"; } + if (0) { case AST_GE: type_name = "$ge"; } + if (0) { case AST_GT: type_name = "$gt"; } { int width = std::max(width_hint, 1); width_hint = -1, sign_hint = true; @@ -1267,6 +1271,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(0); cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0); + + cell->parameters["\\PRIORITY"] = RTLIL::Const(RTLIL::autoidx-1); } break; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index f6df0c170..9b8ed7603 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -299,6 +299,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_LE: case AST_EQ: case AST_NE: + case AST_EQX: + case AST_NEX: case AST_GE: case AST_GT: width_hint = -1; @@ -495,8 +497,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, if (width != int(children[0]->bits.size())) { RTLIL::SigSpec sig(children[0]->bits); sig.extend_u0(width, children[0]->is_signed); - delete children[0]; + AstNode *old_child_0 = children[0]; children[0] = mkconst_bits(sig.as_const().bits, children[0]->is_signed); + delete old_child_0; } children[0]->is_signed = is_signed; } @@ -1258,12 +1261,14 @@ skip_dynamic_range_lvalue_expansion:; newNode = mkconst_bits(y.bits, sign_hint); } break; - if (0) { case AST_LT: const_func = RTLIL::const_lt; } - if (0) { case AST_LE: const_func = RTLIL::const_le; } - if (0) { case AST_EQ: const_func = RTLIL::const_eq; } - if (0) { case AST_NE: const_func = RTLIL::const_ne; } - if (0) { case AST_GE: const_func = RTLIL::const_ge; } - if (0) { case AST_GT: const_func = RTLIL::const_gt; } + if (0) { case AST_LT: const_func = RTLIL::const_lt; } + if (0) { case AST_LE: const_func = RTLIL::const_le; } + if (0) { case AST_EQ: const_func = RTLIL::const_eq; } + if (0) { case AST_NE: const_func = RTLIL::const_ne; } + if (0) { case AST_EQX: const_func = RTLIL::const_eqx; } + if (0) { case AST_NEX: const_func = RTLIL::const_nex; } + if (0) { case AST_GE: const_func = RTLIL::const_ge; } + if (0) { case AST_GT: const_func = RTLIL::const_gt; } if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) { int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size()); bool cmp_signed = children[0]->is_signed && children[1]->is_signed; diff --git a/frontends/verilog/lexer.l b/frontends/verilog/lexer.l index a0deb755b..9e606d90f 100644 --- a/frontends/verilog/lexer.l +++ b/frontends/verilog/lexer.l @@ -232,8 +232,8 @@ supply1 { return TOK_SUPPLY1; } "<=" { return OP_LE; } ">=" { return OP_GE; } -"===" { return OP_EQ; } -"!==" { return OP_NE; } +"===" { return OP_EQX; } +"!==" { return OP_NEX; } "~&" { return OP_NAND; } "~|" { return OP_NOR; } diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y index f47d1785c..874482d6e 100644 --- a/frontends/verilog/parser.y +++ b/frontends/verilog/parser.y @@ -117,7 +117,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) %left '|' OP_NOR %left '^' OP_XNOR %left '&' OP_NAND -%left OP_EQ OP_NE +%left OP_EQ OP_NE OP_EQX OP_NEX %left '<' OP_LE OP_GE '>' %left OP_SHL OP_SHR OP_SSHL OP_SSHR %left '+' '-' @@ -1161,6 +1161,14 @@ basic_expr: $$ = new AstNode(AST_NE, $1, $4); append_attr($$, $3); } | + basic_expr OP_EQX attr basic_expr { + $$ = new AstNode(AST_EQX, $1, $4); + append_attr($$, $3); + } | + basic_expr OP_NEX attr basic_expr { + $$ = new AstNode(AST_NEX, $1, $4); + append_attr($$, $3); + } | basic_expr OP_GE attr basic_expr { $$ = new AstNode(AST_GE, $1, $4); append_attr($$, $3); diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 8d435d940..5cfa0f24b 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -76,8 +76,9 @@ static char next_char() return ch == '\r' ? next_char() : ch; } -static void skip_spaces() +static std::string skip_spaces() { + std::string spaces; while (1) { char ch = next_char(); if (ch == 0) @@ -86,7 +87,9 @@ static void skip_spaces() return_char(ch); break; } + spaces += ch; } + return spaces; } static std::string next_token(bool pass_newline = false) @@ -170,13 +173,14 @@ static std::string next_token(bool pass_newline = false) else { const char *ok = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789"; - while ((ch = next_char()) != 0) { - if (strchr(ok, ch) == NULL) { - return_char(ch); - break; + if (ch == '`' || strchr(ok, ch) != NULL) + while ((ch = next_char()) != 0) { + if (strchr(ok, ch) == NULL) { + return_char(ch); + break; + } + token += ch; } - token += ch; - } } return token; @@ -200,8 +204,10 @@ static void input_file(FILE *f, std::string filename) std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::map<std::string, std::string> pre_defines_map, const std::list<std::string> include_dirs) { + std::set<std::string> defines_with_args; std::map<std::string, std::string> defines_map(pre_defines_map); int ifdef_fail_level = 0; + bool in_elseif = false; output_code.clear(); input_buffer.clear(); @@ -218,17 +224,29 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m if (tok == "`endif") { if (ifdef_fail_level > 0) ifdef_fail_level--; + if (ifdef_fail_level == 0) + in_elseif = false; continue; } if (tok == "`else") { if (ifdef_fail_level == 0) ifdef_fail_level = 1; - else if (ifdef_fail_level == 1) + else if (ifdef_fail_level == 1 && !in_elseif) ifdef_fail_level = 0; continue; } + if (tok == "`elsif") { + skip_spaces(); + std::string name = next_token(true); + if (ifdef_fail_level == 0) + ifdef_fail_level = 1, in_elseif = true; + else if (ifdef_fail_level == 1 && defines_map.count(name) != 0) + ifdef_fail_level = 0, in_elseif = true; + continue; + } + if (tok == "`ifdef") { skip_spaces(); std::string name = next_token(true); @@ -289,32 +307,58 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m if (tok == "`define") { std::string name, value; + std::map<std::string, int> args; skip_spaces(); name = next_token(true); - skip_spaces(); int newline_count = 0; + int state = 0; + if (skip_spaces() != "") + state = 3; while (!tok.empty()) { tok = next_token(); - if (tok == "\n") { - return_char('\n'); - break; - } - if (tok == "\\") { - char ch = next_char(); - if (ch == '\n') { - value += " "; - newline_count++; - } else { - value += std::string("\\"); - return_char(ch); - } + if (state == 0 && tok == "(") { + state = 1; + skip_spaces(); } else - value += tok; + if (state == 1) { + if (tok == ")") + state = 2; + else if (tok != ",") { + int arg_idx = args.size()+1; + args[tok] = arg_idx; + } + skip_spaces(); + } else { + if (state != 2) + state = 3; + if (tok == "\n") { + return_char('\n'); + break; + } + if (tok == "\\") { + char ch = next_char(); + if (ch == '\n') { + value += " "; + newline_count++; + } else { + value += std::string("\\"); + return_char(ch); + } + } else + if (args.count(tok) > 0) + value += stringf("`macro_%s_arg%d", name.c_str(), args.at(tok)); + else + value += tok; + } } while (newline_count-- > 0) return_char('\n'); // printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str()); defines_map[name] = value; + if (state == 2) + defines_with_args.insert(name); + else + defines_with_args.erase(name); continue; } @@ -324,6 +368,7 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m name = next_token(true); // printf("undef: >>%s<<\n", name.c_str()); defines_map.erase(name); + defines_with_args.erase(name); continue; } @@ -338,8 +383,35 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m } if (tok.size() > 1 && tok[0] == '`' && defines_map.count(tok.substr(1)) > 0) { - // printf("expand: >>%s<< -> >>%s<<\n", tok.c_str(), defines_map[tok.substr(1)].c_str()); - insert_input(defines_map[tok.substr(1)]); + std::string name = tok.substr(1); + // printf("expand: >>%s<< -> >>%s<<\n", name.c_str(), defines_map[name].c_str()); + std::string skipped_spaces = skip_spaces(); + tok = next_token(true); + if (tok == "(" && defines_with_args.count(name) > 0) { + int level = 1; + std::vector<std::string> args; + args.push_back(std::string()); + while (1) + { + tok = next_token(true); + if (tok == ")" || tok == "}" || tok == "]") + level--; + if (level == 0) + break; + if (level == 1 && tok == ",") + args.push_back(std::string()); + else + args.back() += tok; + if (tok == "(" || tok == "{" || tok == "[") + level++; + } + for (size_t i = 0; i < args.size(); i++) + defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i]; + } else { + insert_input(tok); + insert_input(skipped_spaces); + } + insert_input(defines_map[name]); continue; } |