diff --git a/include/verilated_types.h b/include/verilated_types.h index 39e487bb7..494af9be8 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -1066,6 +1066,9 @@ struct VlUnpacked final { // Similar to 'neq' above, *this = that used for change detection void assign(const VlUnpacked& that) { *this = that; } + bool operator==(const VlUnpacked& that) const { return !neq(that); } + bool operator!=(const VlUnpacked& that) { return neq(that); } + // Dumping. Verilog: str = $sformatf("%p", assoc) std::string to_string() const { std::string out = "'{"; diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index abda6f4f1..04e38e172 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -17,6 +17,7 @@ #include "config_build.h" #include "verilatedos.h" +#include "V3Ast.h" #include "V3EmitC.h" #include "V3EmitCConstInit.h" #include "V3Global.h" @@ -239,25 +240,18 @@ class EmitCHeader final : public EmitCConstInit { puts(";\n"); } - puts("\nbool operator==(const " + EmitCBase::prefixNameProtect(sdtypep) + "& rhs){\n"); + puts("\nbool operator==(const " + EmitCBase::prefixNameProtect(sdtypep) + + "& rhs) const {\n"); puts("return "); for (const AstMemberDType* itemp = sdtypep->membersp(); itemp; itemp = VN_AS(itemp->nextp(), MemberDType)) { if (itemp != sdtypep->membersp()) puts("\n && "); - if (AstUnpackArrayDType* const adtypep - = VN_CAST(itemp->subDTypep(), UnpackArrayDType)) { - for (uint32_t i = 0; i < adtypep->arrayUnpackedElements(); i++) { - if (i != 0) puts("\n && "); - puts(itemp->nameProtect() + "[" + std::to_string(i) + "U] == " + "rhs." - + itemp->nameProtect() + "[" + std::to_string(i) + "U]"); - } - } else { - puts(itemp->nameProtect() + " == " + "rhs." + itemp->nameProtect()); - } + puts(itemp->nameProtect() + " == " + "rhs." + itemp->nameProtect()); } puts(";\n"); puts("}\n"); - puts("bool operator!=(const " + EmitCBase::prefixNameProtect(sdtypep) + "& rhs){\n"); + puts("bool operator!=(const " + EmitCBase::prefixNameProtect(sdtypep) + + "& rhs) const {\n"); puts("return !(*this == rhs);\n}\n"); puts("};\n"); } diff --git a/test_regress/t/t_unpacked_struct_eq.v b/test_regress/t/t_unpacked_struct_eq.v index 5757cae2e..384f10801 100644 --- a/test_regress/t/t_unpacked_struct_eq.v +++ b/test_regress/t/t_unpacked_struct_eq.v @@ -17,30 +17,47 @@ // SPDX-License-Identifier: CC0-1.0 module t; + typedef struct{ + logic [31:0] subarr[4]; + } arr_str_t; typedef struct { string txt; struct { logic m0; logic [3:0] m1; + logic [7:0] arr[2][3]; + arr_str_t str[5]; } sub; - logic [7:0] arr[2]; } struct_t; struct_t s1; struct_t s2; + struct_t s3; assign {s1.sub.m0, s1.sub.m1} = {1'b0, 4'h5}; assign {s2.sub.m0, s2.sub.m1} = {1'b0, 4'h5}; assign s1.txt = "text"; assign s2.txt = "text"; - assign s1.arr[0] = 8'h77; - assign s2.arr[0] = 8'h77; - assign s1.arr[1] = 8'h33; - assign s2.arr[1] = 8'h33; + + assign {s1.sub.arr[0][0], s2.sub.arr[0][0]} = {8'h01, 8'h01}; + assign {s1.sub.arr[0][1], s2.sub.arr[0][1]} = {8'h02, 8'h02}; + assign {s1.sub.arr[0][2], s2.sub.arr[0][2]} = {8'h03, 8'h03}; + assign {s1.sub.arr[1][0], s2.sub.arr[1][0]} = {8'h04, 8'h04}; + assign {s1.sub.arr[1][1], s2.sub.arr[1][1]} = {8'h05, 8'h05}; + assign {s1.sub.arr[1][2], s2.sub.arr[1][2]} = {8'h06, 8'h06}; + + assign {s3.sub.m0, s3.sub.m1} = {1'b0, 4'h5}; + assign s3.txt = "text"; + + assign s3.sub.arr[0][0] = 8'h01; + assign s3.sub.arr[0][1] = 8'h02; + assign s3.sub.arr[0][2] = 8'h03; + assign s3.sub.arr[1][0] = 8'h24; // One mismatch + assign s3.sub.arr[1][1] = 8'h05; + assign s3.sub.arr[1][2] = 8'h06; initial begin - if(s1 != s2) $stop; - if(s1.sub != s2.sub) $stop; - if(s1 == s2) begin + if(s3 == s1) $stop; + if(s1 == s2 && s3 != s1) begin $write("*-* All Finished *-*\n"); $finish; end else begin