diff --git a/Changes b/Changes index 30a6b5a14..e19b51400 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 3.911 devel +*** Support or/and/xor array intrinsic methods, bug1210. [Mike Popoloski] + *** Fix ordering of arrayed cell wide connections, bug1202 partial. [Mike Popoloski] **** Fix LITENDIAN warning on arrayed cells, bug1202. [Mike Popoloski] diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6c63e972a..ed5facdda 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1536,6 +1536,45 @@ private: nodep->v3error("Unknown built-in enum method '"<fromp()->prettyTypeName()<<"'"); } } + else if (AstUnpackArrayDType* arrayType = fromDtp->castUnpackArrayDType()) { + enum { + UNKNOWN = 0, + ARRAY_OR, + ARRAY_AND, + ARRAY_XOR + } methodId; + + methodId = UNKNOWN; + if (nodep->name() == "or") methodId = ARRAY_OR; + else if (nodep->name() == "and") methodId = ARRAY_AND; + else if (nodep->name() == "xor") methodId = ARRAY_XOR; + + if (methodId) { + if (nodep->pinsp()) nodep->v3error("Arguments passed to array method, but it does not take arguments"); + + FileLine* fl = nodep->fileline(); + AstNode* newp = NULL; + for (int i = 0; i < arrayType->elementsConst(); ++i) { + AstNode* arrayRef = nodep->fromp()->cloneTree(false); + AstNode* selector = new AstArraySel(fl, arrayRef, i); + if (!newp) + newp = selector; + else { + switch (methodId) { + case ARRAY_OR: newp = new AstOr(fl, newp, selector); break; + case ARRAY_AND: newp = new AstAnd(fl, newp, selector); break; + case ARRAY_XOR: newp = new AstXor(fl, newp, selector); break; + default: nodep->v3fatalSrc("bad case"); + } + } + } + nodep->replaceWith(newp); + nodep->deleteTree(); VL_DANGLING(nodep); + } + else { + nodep->v3error("Unknown built-in array method '"<fromp()->prettyTypeName()<<"'"); + } + } else { nodep->v3error("Unsupported: Member call on non-enum object '" <fromp()->prettyTypeName()<<"' which is a '"<fromp()->dtypep()->prettyTypeName()<<"'"); diff --git a/src/verilog.y b/src/verilog.y index 2a97499b7..093083f09 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2894,6 +2894,11 @@ parenE: // // IEEE: built_in_method_call // // method_call_root not needed, part of expr resolution // // What's left is below array_methodNoRoot +array_methodNoRoot: + yOR { $$ = new AstFuncRef($1, "or", NULL); } + | yAND { $$ = new AstFuncRef($1, "and", NULL); } + | yXOR { $$ = new AstFuncRef($1, "xor", NULL); } + ; dpi_import_export: // ==IEEE: dpi_import_export yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE function_prototype ';' @@ -3040,7 +3045,7 @@ expr: // IEEE: part of expression/constant_expression/primary // // method_call | ~l~expr '.' function_subroutine_callNoMethod { $$ = new AstDot($2,$1,$3); } // // method_call:array_method requires a '.' - //UNSUP ~l~expr '.' array_methodNoRoot { UNSUP } + | ~l~expr '.' array_methodNoRoot { $$ = new AstDot($2,$1,$3); } // // // IEEE: let_expression // // see funcRef diff --git a/test_regress/t/t_array_type_methods.pl b/test_regress/t/t_array_type_methods.pl new file mode 100644 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_array_type_methods.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_array_type_methods.v b/test_regress/t/t_array_type_methods.v new file mode 100644 index 000000000..0af06c8ee --- /dev/null +++ b/test_regress/t/t_array_type_methods.v @@ -0,0 +1,28 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2014 by Wilson Snyder. + +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); +`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + logic [2:0] foo [1:0]; + initial begin + foo[0] = 3'b101; + foo[1] = 3'b011; + + `checkh(foo.or, 3'b111); + `checkh(foo.and, 3'b001); + `checkh(foo.xor, 3'b110); + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule