aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
authorAhmed Irfan <ahmedirfan1983@gmail.com>2014-01-03 10:54:54 +0100
committerAhmed Irfan <ahmedirfan1983@gmail.com>2014-01-03 10:54:54 +0100
commit06482c046bcab4e2b9603f8954ce0f2fd501a73b (patch)
treed160ad05402768e4f468ff0685593b81658e6a5a /frontends
parent5da334fc2efd66c8a5efde925bb18212c34d0cef (diff)
parentfb2bf934dc6d2c969906b350c9a1b09a972bfdd7 (diff)
downloadyosys-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.cc4
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/genrtlil.cc18
-rw-r--r--frontends/ast/simplify.cc19
-rw-r--r--frontends/verilog/lexer.l4
-rw-r--r--frontends/verilog/parser.y10
-rw-r--r--frontends/verilog/preproc.cc122
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;
}