aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/aiger/aigerparse.cc14
-rw-r--r--frontends/aiger/aigerparse.h2
-rw-r--r--frontends/ast/ast.cc6
-rw-r--r--frontends/ast/ast.h3
-rw-r--r--frontends/ast/genrtlil.cc32
-rw-r--r--frontends/ast/simplify.cc85
-rw-r--r--frontends/verilog/verilog_lexer.l4
-rw-r--r--frontends/verilog/verilog_parser.y88
8 files changed, 176 insertions, 58 deletions
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 6fda92d73..d25587e48 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -454,6 +454,14 @@ void AigerReader::parse_xaiger()
for (unsigned i = 0; i < flopNum; i++)
mergeability.emplace_back(parse_xaiger_literal(f));
}
+ else if (c == 's') {
+ uint32_t dataSize YS_ATTRIBUTE(unused) = parse_xaiger_literal(f);
+ flopNum = parse_xaiger_literal(f);
+ log_assert(dataSize == (flopNum+1) * sizeof(uint32_t));
+ initial_state.reserve(flopNum);
+ for (unsigned i = 0; i < flopNum; i++)
+ initial_state.emplace_back(parse_xaiger_literal(f));
+ }
else if (c == 'n') {
parse_xaiger_literal(f);
f >> s;
@@ -767,6 +775,7 @@ void AigerReader::post_process()
}
}
+ dict<int, Wire*> mergeability_to_clock;
for (uint32_t i = 0; i < flopNum; i++) {
RTLIL::Wire *d = outputs[outputs.size() - flopNum + i];
log_assert(d);
@@ -778,10 +787,9 @@ void AigerReader::post_process()
log_assert(q->port_input);
q->port_input = false;
- auto ff = module->addCell(NEW_ID, ID($__ABC9_FF_));
- ff->setPort(ID::D, d);
- ff->setPort(ID::Q, q);
+ Cell* ff = module->addFfGate(NEW_ID, d, q);
ff->attributes[ID::abc9_mergeability] = mergeability[i];
+ q->attributes[ID::init] = initial_state[i];
}
dict<RTLIL::IdString, std::pair<int,int>> wideports_cache;
diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h
index 46ac81212..251a24977 100644
--- a/frontends/aiger/aigerparse.h
+++ b/frontends/aiger/aigerparse.h
@@ -45,7 +45,7 @@ struct AigerReader
std::vector<RTLIL::Wire*> outputs;
std::vector<RTLIL::Wire*> bad_properties;
std::vector<RTLIL::Cell*> boxes;
- std::vector<int> mergeability;
+ std::vector<int> mergeability, initial_state;
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
void parse_aiger();
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 6a9af3f57..689fa9fb4 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -94,6 +94,7 @@ std::string AST::type2str(AstNodeType type)
X(AST_TO_BITS)
X(AST_TO_SIGNED)
X(AST_TO_UNSIGNED)
+ X(AST_SELFSZ)
X(AST_CONCAT)
X(AST_REPLICATE)
X(AST_BIT_NOT)
@@ -110,6 +111,8 @@ std::string AST::type2str(AstNodeType type)
X(AST_SHIFT_RIGHT)
X(AST_SHIFT_SLEFT)
X(AST_SHIFT_SRIGHT)
+ X(AST_SHIFTX)
+ X(AST_SHIFT)
X(AST_LT)
X(AST_LE)
X(AST_EQ)
@@ -615,6 +618,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
if (0) { case AST_POS: txt = "+"; }
if (0) { case AST_NEG: txt = "-"; }
if (0) { case AST_LOGIC_NOT: txt = "!"; }
+ if (0) { case AST_SELFSZ: txt = "@selfsz@"; }
fprintf(f, "%s(", txt.c_str());
children[0]->dumpVlog(f, "");
fprintf(f, ")");
@@ -628,6 +632,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
if (0) { case AST_SHIFT_RIGHT: txt = ">>"; }
if (0) { case AST_SHIFT_SLEFT: txt = "<<<"; }
if (0) { case AST_SHIFT_SRIGHT: txt = ">>>"; }
+ if (0) { case AST_SHIFTX: txt = "@shiftx@"; }
+ if (0) { case AST_SHIFT: txt = "@shift@"; }
if (0) { case AST_LT: txt = "<"; }
if (0) { case AST_LE: txt = "<="; }
if (0) { case AST_EQ: txt = "=="; }
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 3f6329112..8932108e3 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -75,6 +75,7 @@ namespace AST
AST_TO_BITS,
AST_TO_SIGNED,
AST_TO_UNSIGNED,
+ AST_SELFSZ,
AST_CONCAT,
AST_REPLICATE,
AST_BIT_NOT,
@@ -91,6 +92,8 @@ namespace AST
AST_SHIFT_RIGHT,
AST_SHIFT_SLEFT,
AST_SHIFT_SRIGHT,
+ AST_SHIFTX,
+ AST_SHIFT,
AST_LT,
AST_LE,
AST_EQ,
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 996762715..cdc3adc9c 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -809,6 +809,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
sign_hint = false;
break;
+ case AST_SELFSZ:
+ sub_width_hint = 0;
+ children.at(0)->detectSignWidthWorker(sub_width_hint, sign_hint);
+ break;
+
case AST_CONCAT:
for (auto child : children) {
sub_width_hint = 0;
@@ -856,6 +861,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_SHIFT_RIGHT:
case AST_SHIFT_SLEFT:
case AST_SHIFT_SRIGHT:
+ case AST_SHIFTX:
+ case AST_SHIFT:
case AST_POW:
children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real);
break;
@@ -923,7 +930,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
}
break;
}
- /* fall through */
+ YS_FALLTHROUGH
// everything should have been handled above -> print error if not.
default:
@@ -1019,7 +1026,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (GetSize(children) >= 1 && children[0]->type == AST_CONSTANT) {
current_module->parameter_default_values[str] = children[0]->asParaConst();
}
- /* fall through */
+ YS_FALLTHROUGH
case AST_LOCALPARAM:
if (flag_pwires)
{
@@ -1048,7 +1055,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (!range_valid)
log_file_error(filename, location.first_line, "Signal `%s' with non-constant width!\n", str.c_str());
- if (!(range_left >= range_right || (range_left == -1 && range_right == 0)))
+ if (!(range_left + 1 >= range_right))
log_file_error(filename, location.first_line, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
@@ -1205,13 +1212,18 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone());
fake_ast->children[0]->delete_children();
- RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL();
+
+ int fake_ast_width = 0;
+ bool fake_ast_sign = true;
+ fake_ast->children[1]->detectSignWidth(fake_ast_width, fake_ast_sign);
+ RTLIL::SigSpec shift_val = fake_ast->children[1]->genRTLIL(fake_ast_width, fake_ast_sign);
+
if (id2ast->range_right != 0) {
- shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast->children[1]->is_signed);
+ shift_val = current_module->Sub(NEW_ID, shift_val, id2ast->range_right, fake_ast_sign);
fake_ast->children[1]->is_signed = true;
}
if (id2ast->range_swapped) {
- shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed);
+ shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast_sign);
fake_ast->children[1]->is_signed = true;
}
if (GetSize(shift_val) >= 32)
@@ -1265,7 +1277,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// just pass thru the signal. the parent will evaluate the is_signed property and interpret the SigSpec accordingly
case AST_TO_SIGNED:
- case AST_TO_UNSIGNED: {
+ case AST_TO_UNSIGNED:
+ case AST_SELFSZ: {
RTLIL::SigSpec sig = children[0]->genRTLIL();
if (sig.size() < width_hint)
sig.extend_u0(width_hint, sign_hint);
@@ -1356,6 +1369,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (0) { case AST_SHIFT_RIGHT: type_name = ID($shr); }
if (0) { case AST_SHIFT_SLEFT: type_name = ID($sshl); }
if (0) { case AST_SHIFT_SRIGHT: type_name = ID($sshr); }
+ if (0) { case AST_SHIFTX: type_name = ID($shiftx); }
+ if (0) { case AST_SHIFT: type_name = ID($shift); }
{
if (width_hint < 0)
detectSignWidth(width_hint, sign_hint);
@@ -1807,7 +1822,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
is_signed = sign_hint;
return SigSpec(wire);
}
- } /* fall through */
+ }
+ YS_FALLTHROUGH
// everything should have been handled above -> print error if not.
default:
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 252219094..3314819fb 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -91,7 +91,7 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg
case 'D':
if (got_len)
goto unsupported_format;
- /* fall through */
+ YS_FALLTHROUGH
case 'x':
case 'X':
if (next_arg >= GetSize(children))
@@ -608,6 +608,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
case AST_TO_BITS:
case AST_TO_SIGNED:
case AST_TO_UNSIGNED:
+ case AST_SELFSZ:
case AST_CONCAT:
case AST_REPLICATE:
case AST_REDUCE_AND:
@@ -1079,7 +1080,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (old_range_valid != range_valid)
did_something = true;
- if (range_valid && range_left >= 0 && range_right > range_left) {
+ if (range_valid && range_right > range_left) {
int tmp = range_right;
range_right = range_left;
range_left = tmp;
@@ -1097,6 +1098,25 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
range_swapped = children[0]->range_swapped;
range_left = children[0]->range_left;
range_right = children[0]->range_right;
+ bool force_upto = false, force_downto = false;
+ if (attributes.count(ID::force_upto)) {
+ AstNode *val = attributes[ID::force_upto];
+ if (val->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Attribute `force_upto' with non-constant value!\n");
+ force_upto = val->asAttrConst().as_bool();
+ }
+ if (attributes.count(ID::force_downto)) {
+ AstNode *val = attributes[ID::force_downto];
+ if (val->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Attribute `force_downto' with non-constant value!\n");
+ force_downto = val->asAttrConst().as_bool();
+ }
+ if (force_upto && force_downto)
+ log_file_error(filename, location.first_line, "Attributes `force_downto' and `force_upto' cannot be both set!\n");
+ if ((force_upto && !range_swapped) || (force_downto && range_swapped)) {
+ std::swap(range_left, range_right);
+ range_swapped = force_upto;
+ }
}
} else {
if (!range_valid)
@@ -1788,7 +1808,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
}
- if (0)
+ bool use_case_method = false;
+
+ if (children[0]->id2ast->attributes.count(ID::nowrshmsk)) {
+ AstNode *node = children[0]->id2ast->attributes.at(ID::nowrshmsk);
+ while (node->simplify(true, false, false, stage, -1, false, false)) { }
+ if (node->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children[0]->id2ast->str.c_str());
+ if (node->asAttrConst().as_bool())
+ use_case_method = true;
+ }
+
+ if (use_case_method)
{
// big case block
@@ -1796,10 +1827,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
newNode = new AstNode(AST_CASE, shift_expr);
for (int i = 0; i < source_width; i++) {
int start_bit = children[0]->id2ast->range_right + i;
+ int end_bit = std::min(start_bit+result_width,source_width) - 1;
AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true));
AstNode *lvalue = children[0]->clone();
lvalue->delete_children();
- int end_bit = std::min(start_bit+result_width,source_width) - 1;
lvalue->children.push_back(new AstNode(AST_RANGE,
mkconst_int(end_bit, true), mkconst_int(start_bit, true)));
cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
@@ -1846,11 +1877,40 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
AstNode *shamt = shift_expr;
- newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_mask->clone(),
- new AstNode(AST_SHIFT_LEFT, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), shamt->clone())));
- newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_data->clone(),
- new AstNode(AST_SHIFT_LEFT, new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()), shamt)));
- newNode->children.push_back(new AstNode(type, lvalue, new AstNode(AST_BIT_OR, new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)), ref_data)));
+ int shamt_width_hint = 0;
+ bool shamt_sign_hint = true;
+ shamt->detectSignWidth(shamt_width_hint, shamt_sign_hint);
+
+ int start_bit = children[0]->id2ast->range_right;
+ bool use_shift = shamt_sign_hint;
+
+ if (start_bit != 0) {
+ shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true));
+ use_shift = true;
+ }
+
+ AstNode *t;
+
+ t = mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false);
+ if (use_shift)
+ t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt->clone()));
+ else
+ t = new AstNode(AST_SHIFT_LEFT, t, shamt->clone());
+ t = new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), t);
+ newNode->children.push_back(t);
+
+ t = new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone());
+ if (use_shift)
+ t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt));
+ else
+ t = new AstNode(AST_SHIFT_LEFT, t, shamt);
+ t = new AstNode(AST_ASSIGN_EQ, ref_data->clone(), t);
+ newNode->children.push_back(t);
+
+ t = new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask));
+ t = new AstNode(AST_BIT_OR, t, ref_data);
+ t = new AstNode(type, lvalue, t);
+ newNode->children.push_back(t);
}
goto apply_newNode;
@@ -3026,6 +3086,7 @@ replace_fcall_later:;
}
}
break;
+ if (0) { case AST_SELFSZ: const_func = RTLIL::const_pos; }
if (0) { case AST_POS: const_func = RTLIL::const_pos; }
if (0) { case AST_NEG: const_func = RTLIL::const_neg; }
if (children[0]->type == AST_CONSTANT) {
@@ -3034,10 +3095,10 @@ replace_fcall_later:;
} else
if (children[0]->isConst()) {
newNode = new AstNode(AST_REALVALUE);
- if (type == AST_POS)
- newNode->realvalue = +children[0]->asReal(sign_hint);
- else
+ if (type == AST_NEG)
newNode->realvalue = -children[0]->asReal(sign_hint);
+ else
+ newNode->realvalue = +children[0]->asReal(sign_hint);
}
break;
case AST_TERNARY:
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index f6a3ac4db..65a2e9a78 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -128,7 +128,9 @@ static bool isUserType(std::string &s)
%x BASED_CONST
%%
- int comment_caller;
+ // Initialise comment_caller to something to avoid a "maybe undefined"
+ // warning from GCC.
+ int comment_caller = INITIAL;
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* {
fn_stack.push_back(current_filename);
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 5d6e43330..c8223f41d 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -645,13 +645,13 @@ non_opt_range:
} |
'[' expr TOK_POS_INDEXED expr ']' {
$$ = new AstNode(AST_RANGE);
- AstNode *expr = new AstNode(AST_CONCAT, $2);
+ AstNode *expr = new AstNode(AST_SELFSZ, $2);
$$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), $4), AstNode::mkconst_int(1, true)));
$$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true)));
} |
'[' expr TOK_NEG_INDEXED expr ']' {
$$ = new AstNode(AST_RANGE);
- AstNode *expr = new AstNode(AST_CONCAT, $2);
+ AstNode *expr = new AstNode(AST_SELFSZ, $2);
$$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true)));
$$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), AstNode::mkconst_int(1, true)), $4));
} |
@@ -853,7 +853,19 @@ task_func_port:
}
if (astbuf2 && astbuf2->children.size() != 2)
frontend_verilog_yyerror("task/function argument range must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
- } wire_name | wire_name;
+ } wire_name |
+ {
+ if (!astbuf1) {
+ if (!sv_mode)
+ frontend_verilog_yyerror("task/function argument direction missing");
+ albuf = new dict<IdString, AstNode*>;
+ astbuf1 = new AstNode(AST_WIRE);
+ current_wire_rand = false;
+ current_wire_const = false;
+ astbuf1->is_input = true;
+ astbuf2 = NULL;
+ }
+ } wire_name;
task_func_body:
task_func_body behavioral_stmt |
@@ -2191,49 +2203,56 @@ assert_property:
};
simple_behavioral_stmt:
- lvalue '=' delay expr {
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4);
+ attr lvalue '=' delay expr {
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, $5);
ast_stack.back()->children.push_back(node);
- SET_AST_NODE_LOC(node, @1, @4);
+ SET_AST_NODE_LOC(node, @2, @5);
+ append_attr(node, $1);
} |
- lvalue TOK_INCREMENT {
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true)));
+ attr lvalue TOK_INCREMENT {
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true)));
ast_stack.back()->children.push_back(node);
- SET_AST_NODE_LOC(node, @1, @2);
+ SET_AST_NODE_LOC(node, @2, @3);
+ append_attr(node, $1);
} |
- lvalue TOK_DECREMENT {
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true)));
+ attr lvalue TOK_DECREMENT {
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, new AstNode(AST_SUB, $2->clone(), AstNode::mkconst_int(1, true)));
ast_stack.back()->children.push_back(node);
- SET_AST_NODE_LOC(node, @1, @2);
+ SET_AST_NODE_LOC(node, @2, @3);
+ append_attr(node, $1);
} |
- lvalue OP_LE delay expr {
- AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4);
+ attr lvalue OP_LE delay expr {
+ AstNode *node = new AstNode(AST_ASSIGN_LE, $2, $5);
ast_stack.back()->children.push_back(node);
- SET_AST_NODE_LOC(node, @1, @4);
+ SET_AST_NODE_LOC(node, @2, @5);
+ append_attr(node, $1);
};
// this production creates the obligatory if-else shift/reduce conflict
behavioral_stmt:
defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl |
non_opt_delay behavioral_stmt |
- simple_behavioral_stmt ';' | ';' |
- hierarchical_id attr {
+ simple_behavioral_stmt ';' |
+ attr ';' {
+ free_attr($1);
+ } |
+ attr hierarchical_id {
AstNode *node = new AstNode(AST_TCALL);
- node->str = *$1;
- delete $1;
+ node->str = *$2;
+ delete $2;
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
- append_attr(node, $2);
+ append_attr(node, $1);
} opt_arg_list ';'{
ast_stack.pop_back();
} |
- TOK_MSG_TASKS attr {
+ attr TOK_MSG_TASKS {
AstNode *node = new AstNode(AST_TCALL);
- node->str = *$1;
- delete $1;
+ node->str = *$2;
+ delete $2;
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
- append_attr(node, $2);
+ append_attr(node, $1);
} opt_arg_list ';'{
ast_stack.pop_back();
} |
@@ -2330,8 +2349,6 @@ behavioral_stmt:
ast_stack.pop_back();
};
- ;
-
unique_case_attr:
/* empty */ {
$$ = false;
@@ -2426,7 +2443,7 @@ gen_case_item:
} case_select {
case_type_stack.push_back(0);
SET_AST_NODE_LOC(ast_stack.back(), @2, @2);
- } gen_stmt_or_null {
+ } gen_stmt_block {
case_type_stack.pop_back();
ast_stack.pop_back();
};
@@ -2518,7 +2535,10 @@ module_gen_body:
/* empty */;
gen_stmt_or_module_body_stmt:
- gen_stmt | module_body_stmt;
+ gen_stmt | module_body_stmt |
+ attr ';' {
+ free_attr($1);
+ };
// this production creates the obligatory if-else shift/reduce conflict
gen_stmt:
@@ -2537,7 +2557,12 @@ gen_stmt:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
ast_stack.back()->children.push_back($3);
- } gen_stmt_block opt_gen_else {
+ AstNode *block = new AstNode(AST_GENBLOCK);
+ ast_stack.back()->children.push_back(block);
+ ast_stack.push_back(block);
+ } gen_stmt_block {
+ ast_stack.pop_back();
+ } opt_gen_else {
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
ast_stack.pop_back();
} |
@@ -2585,11 +2610,8 @@ gen_stmt_block:
ast_stack.pop_back();
};
-gen_stmt_or_null:
- gen_stmt_block | ';';
-
opt_gen_else:
- TOK_ELSE gen_stmt_or_null | /* empty */ %prec FAKE_THEN;
+ TOK_ELSE gen_stmt_block | /* empty */ %prec FAKE_THEN;
expr:
basic_expr {