Added $anyconst and $aconst
authorClifford Wolf <clifford@clifford.at>
Wed, 27 Jul 2016 13:41:22 +0000 (15:41 +0200)
committerClifford Wolf <clifford@clifford.at>
Wed, 27 Jul 2016 13:41:22 +0000 (15:41 +0200)
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
frontends/verilog/verilog_parser.y
kernel/celltypes.h
kernel/rtlil.cc
manual/CHAPTER_CellLib.tex
techlibs/common/simlib.v

index 2fb95ff5a17d266a9f8d03cf07377930ad35b594..04cdb9416cc3e5e3708e6459f4dd2c78cfffd37f 100644 (file)
@@ -750,6 +750,19 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
                width_hint = max(width_hint, this_width);
                break;
 
+       case AST_FCALL:
+               if (str == "\\$anyconst" || str == "\\$aconst") {
+                       if (GetSize(children) == 1) {
+                               while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
+                               if (children[0]->type != AST_CONSTANT)
+                                       log_error("System function %s called with non-const argument at %s:%d!\n",
+                                                       RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                               width_hint = max(width_hint, int(children[0]->asInt(true)));
+                       }
+                       break;
+               }
+               /* fall through */
+
        // everything should have been handled above -> print error if not.
        default:
                for (auto f : log_files)
@@ -1427,6 +1440,38 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        delete always;
                } break;
 
+       case AST_FCALL: {
+                       if (str == "\\$anyconst" || str == "\\$aconst")
+                       {
+                               string myid = stringf("%s$%d", RTLIL::unescape_id(str).c_str(), autoidx++);
+                               int width = width_hint;
+
+                               if (GetSize(children) > 1)
+                                       log_error("System function %s got %d arguments, expected 1 or 0 at %s:%d.\n",
+                                                       RTLIL::unescape_id(str).c_str(), GetSize(children), filename.c_str(), linenum);
+
+                               if (GetSize(children) == 1) {
+                                       if (children[0]->type != AST_CONSTANT)
+                                               log_error("System function %s called with non-const argument at %s:%d!\n",
+                                                               RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                       width = children[0]->asInt(true);
+                               }
+
+                               if (width <= 0)
+                                       log_error("Failed to detect width of %s at %s:%d!\n",
+                                                       RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+
+                               Cell *cell = current_module->addCell(myid, str.substr(1));
+                               cell->parameters["\\WIDTH"] = width;
+
+                               Wire *wire = current_module->addWire(myid + "_wire", width);
+                               cell->setPort("\\Y", wire);
+
+                               is_signed = sign_hint;
+                               return SigSpec(wire);
+                       }
+               } /* fall through */
+
        // everything should have been handled above -> print error if not.
        default:
                for (auto f : log_files)
index 9f88cddc2349ff414b968d579c39784f0c7b7a94..79dc3b7c86f422ee0522972e280783cc233170f6 100644 (file)
@@ -1655,6 +1655,10 @@ skip_dynamic_range_lvalue_expansion:;
                                goto apply_newNode;
                        }
 
+                       // $anyconst and $aconst are mapped in AstNode::genRTLIL()
+                       if (str == "\\$anyconst" || str == "\\$aconst")
+                               return false;
+
                        if (str == "\\$clog2")
                        {
                                if (children.size() != 1)
index 4cb65a088386729672cd76a20d5567693f9c8d49..c2327011f23825c9f20733a7aebdad0ec27a48ba 100644 (file)
@@ -1219,7 +1219,7 @@ rvalue:
                $$ = new AstNode(AST_IDENTIFIER, $2);
                $$->str = *$1;
                delete $1;
-               if ($2 == nullptr && $$->str == "\\$initstate")
+               if ($2 == nullptr && formal_mode && ($$->str == "\\$initstate" || $$->str == "\\$anyconst" || $$->str == "\\$aconst"))
                        $$->type = AST_FCALL;
        } |
        hierarchical_id non_opt_multirange {
index 1eea0530c57c63b43703cee58ccef52e96ed52da..9eb1523e922b036eed3f54532ffa19d17850f653 100644 (file)
@@ -118,6 +118,8 @@ struct CellTypes
                setup_type("$assume", {A, EN}, pool<RTLIL::IdString>(), true);
                setup_type("$predict", {A, EN}, pool<RTLIL::IdString>(), true);
                setup_type("$initstate", pool<RTLIL::IdString>(), {Y}, true);
+               setup_type("$anyconst", pool<RTLIL::IdString>(), {Y}, true);
+               setup_type("$aconst", pool<RTLIL::IdString>(), {Y}, true);
                setup_type("$equiv", {A, B}, {Y}, true);
        }
 
index 2e5157e857fd32777db8849bcf38c81d0e13223e..ad90965fb583ba21b13ebadc8d6961c186e7120c 100644 (file)
@@ -1030,6 +1030,12 @@ namespace {
                                return;
                        }
 
+                       if (cell->type.in("$aconst", "$anyconst")) {
+                               port("\\Y", param("\\WIDTH"));
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == "$equiv") {
                                port("\\A", 1);
                                port("\\B", 1);
index 0f1136346cf39389fb0a867a66e64ea5e01799e5..bff01d06c09040a3ddd0c353a48f5c96333de8fc 100644 (file)
@@ -421,7 +421,7 @@ pass. The combinatorial logic cells can be mapped to physical cells from a Liber
 using the {\tt abc} pass.
 
 \begin{fixme}
-Add information about {\tt \$assert}, {\tt \$assume}, {\tt \$predict}, {\tt \$equiv}, and {\tt \$initstate} cells.
+Add information about {\tt \$assert}, {\tt \$assume}, {\tt \$predict}, {\tt \$equiv}, {\tt \$initstate}, {\tt \$aconst}, and {\tt \$anyconst} cells.
 \end{fixme}
 
 \begin{fixme}
index 8ab1240344868c93afdfe7c499154b5f83ba5de8..ac4269c9072bc732eaae7619f446af4c66c078e2 100644 (file)
@@ -1330,6 +1330,30 @@ endmodule
 
 // --------------------------------------------------------
 
+module \$aconst (Y);
+
+parameter WIDTH = 0;
+
+output [WIDTH-1:0] Y;
+
+assign Y = 'bx;
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$anyconst (Y);
+
+parameter WIDTH = 0;
+
+output [WIDTH-1:0] Y;
+
+assign Y = 'bx;
+
+endmodule
+
+// --------------------------------------------------------
+
 module \$equiv (A, B, Y);
 
 input A, B;