Add "nowrshmsk" attribute, fix shift-and-mask bit slice write for signed offset,...
authorClaire Wolf <claire@symbioticeda.com>
Mon, 27 Apr 2020 15:04:47 +0000 (17:04 +0200)
committerClaire Wolf <claire@symbioticeda.com>
Sat, 2 May 2020 09:21:01 +0000 (11:21 +0200)
Signed-off-by: Claire Wolf <claire@symbioticeda.com>
README.md
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
kernel/constids.inc

index 1e486c3ac7a1918556b6339fa9f33332f1e254f6..c17c0c3b1b1fab07b7b8bb2570ce4fcd7c44bf15 100644 (file)
--- a/README.md
+++ b/README.md
@@ -281,6 +281,9 @@ Verilog Attributes and non-standard features
   temporary variable within an always block. This is mostly used internally
   by Yosys to synthesize Verilog functions and access arrays.
 
+- The ``nowrshmsk`` attribute on a register prohibits the generation of
+  shift-and-mask type circuits for writing to bit slices of that register.
+
 - The ``onehot`` attribute on wires mark them as one-hot state register. This
   is used for example for memory port sharing and set by the fsm_map pass.
 
index 6a9af3f57683a47b8c6e060aa5a4cb80cc5f0661..8daae7dcbac04cf3f5d51d94d9da3db233a388df 100644 (file)
@@ -110,6 +110,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)
@@ -628,6 +630,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 = "==";  }
index 3f632911230db9813abd3feb917ce10aafb951b9..0baea7b63d4abdd1022b6da8f3343227d48a7860 100644 (file)
@@ -91,6 +91,8 @@ namespace AST
                AST_SHIFT_RIGHT,
                AST_SHIFT_SLEFT,
                AST_SHIFT_SRIGHT,
+               AST_SHIFTX,
+               AST_SHIFT,
                AST_LT,
                AST_LE,
                AST_EQ,
index d35335747e4c5e7fb02380849ae7eb261d7153b0..6a39bbc049df405623d429310d050c882643516b 100644 (file)
@@ -856,6 +856,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;
@@ -1356,6 +1358,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);
index 837c14ad773e3e700e5bc10e4523c2c5505f109e..af347b8f1fb7b34031cfd94832834128a014f45a 100644 (file)
@@ -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;
index 27b652e247dbbbb5bcd30c64d8b9ae9ace9bf5fa..4f8e86969f04f0f93a5672a67594de800177aeae 100644 (file)
@@ -123,6 +123,7 @@ X(nomem2init)
 X(nomem2reg)
 X(nomeminit)
 X(nosync)
+X(nowrshmsk)
 X(O)
 X(OFFSET)
 X(onehot)