aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/ast/simplify.cc
diff options
context:
space:
mode:
authorClaire Wolf <claire@symbioticeda.com>2020-04-27 17:04:47 +0200
committerClaire Wolf <claire@symbioticeda.com>2020-05-02 11:21:01 +0200
commitbbbce0d1c58f8bfb0a615f1ed53fa046552b5adf (patch)
tree6a8df40ad6343d3af573020f4e39e5a55f4da55a /frontends/ast/simplify.cc
parentca3fc3c882b9a454c48bee7d701fa5cb254ae671 (diff)
downloadyosys-bbbce0d1c58f8bfb0a615f1ed53fa046552b5adf.tar.gz
yosys-bbbce0d1c58f8bfb0a615f1ed53fa046552b5adf.tar.bz2
yosys-bbbce0d1c58f8bfb0a615f1ed53fa046552b5adf.zip
Add "nowrshmsk" attribute, fix shift-and-mask bit slice write for signed offset, fixes #1990
Signed-off-by: Claire Wolf <claire@symbioticeda.com>
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r--frontends/ast/simplify.cc50
1 files changed, 43 insertions, 7 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 837c14ad7..af347b8f1 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1786,7 +1786,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
@@ -1794,10 +1805,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())));
@@ -1844,11 +1855,36 @@ 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 start_bit = children[0]->id2ast->range_right;
+ bool use_shift = shamt->is_signed;
+
+ 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;