Added support for "upto" wires to Verilog front- and back-end
authorClifford Wolf <clifford@clifford.at>
Mon, 28 Jul 2014 12:25:03 +0000 (14:25 +0200)
committerClifford Wolf <clifford@clifford.at>
Mon, 28 Jul 2014 12:25:03 +0000 (14:25 +0200)
backends/verilog/verilog_backend.cc
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
tests/simple/partsel.v

index fe2c2b247e60026b9e46ba6c05e4d4381e101327..5826aea878ef0bbb360c9d5e1731ad6ca67ab79b 100644 (file)
@@ -211,14 +211,23 @@ void dump_sigchunk(FILE *f, const RTLIL::SigChunk &chunk, bool no_decimal = fals
        if (chunk.wire == NULL) {
                dump_const(f, chunk.data, chunk.width, chunk.offset, no_decimal);
        } else {
-               if (chunk.width == chunk.wire->width && chunk.offset == 0)
+               if (chunk.width == chunk.wire->width && chunk.offset == 0) {
                        fprintf(f, "%s", id(chunk.wire->name).c_str());
-               else if (chunk.width == 1)
-                       fprintf(f, "%s[%d]", id(chunk.wire->name).c_str(), chunk.offset + chunk.wire->start_offset);
-               else
-                       fprintf(f, "%s[%d:%d]", id(chunk.wire->name).c_str(),
-                                       chunk.offset + chunk.wire->start_offset + chunk.width - 1,
-                                       chunk.offset + chunk.wire->start_offset);
+               } else if (chunk.width == 1) {
+                       if (chunk.wire->upto)
+                               fprintf(f, "%s[%d]", id(chunk.wire->name).c_str(), (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset);
+                       else
+                               fprintf(f, "%s[%d]", id(chunk.wire->name).c_str(), chunk.offset + chunk.wire->start_offset);
+               } else {
+                       if (chunk.wire->upto)
+                               fprintf(f, "%s[%d:%d]", id(chunk.wire->name).c_str(),
+                                               (chunk.wire->width - (chunk.offset + chunk.width - 1) - 1) + chunk.wire->start_offset,
+                                               (chunk.wire->width - chunk.offset - 1) + chunk.wire->start_offset);
+                       else
+                               fprintf(f, "%s[%d:%d]", id(chunk.wire->name).c_str(),
+                                               (chunk.offset + chunk.width - 1) + chunk.wire->start_offset,
+                                               chunk.offset + chunk.wire->start_offset);
+               }
        }
 }
 
@@ -267,8 +276,12 @@ void dump_wire(FILE *f, std::string indent, RTLIL::Wire *wire)
 #else
        // do not use Verilog-2k "outut reg" syntax in verilog export
        std::string range = "";
-       if (wire->width != 1)
-               range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
+       if (wire->width != 1) {
+               if (wire->upto)
+                       range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset);
+               else
+                       range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
+       }
        if (wire->port_input && !wire->port_output)
                fprintf(f, "%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
        if (!wire->port_input && wire->port_output)
index cec199b638a0e631a27c31af70bbfd4291fd71d6..5b3214f5c055442079b220223b6a09f04a35cbc2 100644 (file)
@@ -181,6 +181,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2)
        is_signed = false;
        is_string = false;
        range_valid = false;
+       range_swapped = false;
        port_id = 0;
        range_left = -1;
        range_right = 0;
@@ -276,7 +277,7 @@ void AstNode::dumpAst(FILE *f, std::string indent)
        if (port_id > 0)
                fprintf(f, " port=%d", port_id);
        if (range_valid || range_left != -1 || range_right != 0)
-               fprintf(f, " range=[%d:%d]%s", range_left, range_right, range_valid ? "" : "!");
+               fprintf(f, " %srange=[%d:%d]%s", range_swapped ? "swapped_" : "", range_left, range_right, range_valid ? "" : "!");
        if (integer != 0)
                fprintf(f, " int=%u", (int)integer);
        if (realvalue != 0)
@@ -620,6 +621,8 @@ bool AstNode::operator==(const AstNode &other) const
                return false;
        if (range_valid != other.range_valid)
                return false;
+       if (range_swapped != other.range_swapped)
+               return false;
        if (port_id != other.port_id)
                return false;
        if (range_left != other.range_left)
index 8253a2052bf9d3e913c6874e368dd0be856f795b..6c15c03ab736b41269c8aad76acd82fe02f227fb 100644 (file)
@@ -151,7 +151,7 @@ namespace AST
                // node content - most of it is unused in most node types
                std::string str;
                std::vector<RTLIL::State> bits;
-               bool is_input, is_output, is_reg, is_signed, is_string, range_valid;
+               bool is_input, is_output, is_reg, is_signed, is_string, range_valid, range_swapped;
                int port_id, range_left, range_right;
                uint32_t integer;
                double realvalue;
index 8ee46eb85b895aa4a7bae25a056c1963d165090f..5545fc16964407f114d195afeb04dcf6cf459e9f 100644 (file)
@@ -786,13 +786,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                log_error("Signal `%s' with non-constant width at %s:%d!\n",
                                                str.c_str(), filename.c_str(), linenum);
 
-                       bool wire_upto = false;
-                       if (range_left < range_right && (range_left != -1 || range_right != 0)) {
-                               int tmp = range_left;
-                               range_left = range_right;
-                               range_right = tmp;
-                               wire_upto = true;
-                       }
+                       log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
 
                        RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
                        wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -800,7 +794,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        wire->port_id = port_id;
                        wire->port_input = is_input;
                        wire->port_output = is_output;
-                       wire->upto = wire_upto;
+                       wire->upto = range_swapped;
 
                        for (auto &attr : attributes) {
                                if (attr.second->type != AST_CONSTANT)
@@ -918,17 +912,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                                        children[0]->children[1]->clone() : children[0]->children[0]->clone());
                                        fake_ast->children[0]->delete_children();
                                        RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shr", width,
-                                                       fake_ast->children[0]->genRTLIL(), fake_ast->children[1]->genRTLIL());
+                                                       fake_ast->children[0]->genRTLIL(), !wire->upto ? fake_ast->children[1]->genRTLIL() :
+                                                       current_module->Sub(NEW_ID, RTLIL::SigSpec(wire->width - width), fake_ast->children[1]->genRTLIL()));
                                        delete left_at_zero_ast;
                                        delete right_at_zero_ast;
                                        delete fake_ast;
                                        return sig;
                                } else {
-                                       chunk.offset = children[0]->range_right - id2ast->range_right;
-                                       chunk.width = children[0]->range_left - children[0]->range_right + 1;
                                        if (children[0]->range_left > id2ast->range_left || id2ast->range_right > children[0]->range_right)
                                                log_error("Range select out of bounds on signal `%s' at %s:%d!\n",
                                                                str.c_str(), filename.c_str(), linenum);
+                                       chunk.width = children[0]->range_left - children[0]->range_right + 1;
+                                       chunk.offset = children[0]->range_right - id2ast->range_right;
+                                       if (wire->upto)
+                                               chunk.offset = wire->width - (chunk.offset + chunk.width);
                                }
                        }
 
index 2a55adeff45d092511070c776bb899eb59f61ee3..7aa6d24c3fead499b2104204c2af4029d348b9e4 100644 (file)
@@ -504,6 +504,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        if (type == AST_RANGE) {
                bool old_range_valid = range_valid;
                range_valid = false;
+               range_swapped = false;
                range_left = -1;
                range_right = 0;
                log_assert(children.size() >= 1);
@@ -525,6 +526,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        int tmp = range_right;
                        range_right = range_left;
                        range_left = tmp;
+                       range_swapped = true;
                }
        }
 
@@ -535,6 +537,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                if (!range_valid)
                                        did_something = true;
                                range_valid = true;
+                               range_swapped = children[0]->range_swapped;
                                range_left = children[0]->range_left;
                                range_right = children[0]->range_right;
                        }
@@ -542,6 +545,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        if (!range_valid)
                                did_something = true;
                        range_valid = true;
+                       range_swapped = false;
                        range_left = 0;
                        range_right = 0;
                }
index 9b1a99859f7445d89d8707c5d26ca36b367ce57c..7461358ad50b4000a36d0f1085930e6287a9c821 100644 (file)
@@ -3,3 +3,60 @@ wire [5:0] offset = idx << 2;
 assign slice_up = data[offset +: 4];
 assign slice_down = data[offset + 3 -: 4];
 endmodule
+
+module partsel_test002 (
+       input clk, rst,
+       input [7:0] a,
+       input [0:7] b,
+       input [1:0] s,
+       output [7:0] x1, x2, x3,
+       output [0:7] x4, x5, x6,
+       output [7:0] y1, y2, y3,
+       output [0:7] y4, y5, y6,
+       output [7:0] z1, z2, z3,
+       output [0:7] z4, z5, z6,
+       output [7:0] w1, w2, w3,
+       output [0:7] w4, w5, w6,
+       output [7:0] p1, p2, p3, p4, p5, p6,
+       output [0:7] q1, q2, q3, q4, q5, q6,
+       output reg [7:0] r1,
+       output reg [0:7] r2
+);
+
+assign x1 = a, x2 = a + b, x3 = b;
+assign x4 = a, x5 = a + b, x6 = b;
+assign y1 = a[4 +: 3], y2 = a[4 +: 3] + b[4 +: 3], y3 = b[4 +: 3];
+assign y4 = a[4 +: 3], y5 = a[4 +: 3] + b[4 +: 3], y6 = b[4 +: 3];
+assign z1 = a[4 -: 3], z2 = a[4 -: 3] + b[4 -: 3], z3 = b[4 -: 3];
+assign z4 = a[4 -: 3], z5 = a[4 -: 3] + b[4 -: 3], z6 = b[4 -: 3];
+assign w1 = a[6:3], w2 = a[6:3] + b[3:6], w3 = b[3:6];
+assign w4 = a[6:3], w5 = a[6:3] + b[3:6], w6 = b[3:6];
+assign p1 = a[s], p2 = b[s], p3 = a[s+2 +: 2], p4 = b[s+2 +: 2], p5 = a[s+2 -: 2], p6 = b[s+2 -: 2];
+assign q1 = a[s], q2 = b[s], q3 = a[s+2 +: 2], q4 = b[s+2 +: 2], q5 = a[s+2 -: 2], q6 = b[s+2 -: 2];
+
+always @(posedge clk) begin
+       if (rst) begin
+               { r1, r2 } = 16'h1337 ^ {a, b};
+       end else begin
+               case (s)
+                       0: begin
+                               r1[3:0] <= r2[0:3] ^ x1;
+                               r2[4:7] <= r1[7:4] ^ x4;
+                       end
+                       1: begin
+                               r1[2 +: 3] <= r2[5 -: 3] + x1;
+                               r2[3 +: 3] <= r1[6 -: 3] + x4;
+                       end
+                       2: begin
+                               r1[6 -: 3] <= r2[3 +: 3] - x1;
+                               r2[7 -: 3] <= r1[4 +: 3] - x4;
+                       end
+                       3: begin
+                               r1 <= r2;
+                               r2 <= r1;
+                       end
+               endcase
+       end
+end
+
+endmodule