@@ -561,6 +561,33 @@ constant_exprt verilog_typecheck_exprt::right(const exprt &expr)
561
561
562
562
/* ******************************************************************\
563
563
564
+ Function: verilog_typecheck_exprt::countones
565
+
566
+ Inputs:
567
+
568
+ Outputs:
569
+
570
+ Purpose:
571
+
572
+ \*******************************************************************/
573
+
574
+ constant_exprt verilog_typecheck_exprt::countones (const constant_exprt &expr)
575
+ {
576
+ // lower to popcount and try simplifier
577
+ auto simplified =
578
+ simplify_expr (popcount_exprt{expr, verilog_int_typet{}.lower ()}, ns);
579
+
580
+ if (!simplified.is_constant ())
581
+ {
582
+ throw errort{}.with_location (expr.source_location ())
583
+ << " failed to simplify constant $countones" ;
584
+ }
585
+ else
586
+ return to_constant_expr (simplified);
587
+ }
588
+
589
+ /* ******************************************************************\
590
+
564
591
Function: verilog_typecheck_exprt::increment
565
592
566
593
Inputs:
@@ -755,6 +782,19 @@ exprt verilog_typecheck_exprt::convert_system_function(
755
782
756
783
return std::move (expr);
757
784
}
785
+ else if (identifier == " $countones" ) // SystemVerilog
786
+ {
787
+ if (arguments.size () != 1 )
788
+ {
789
+ throw errort ().with_location (expr.source_location ())
790
+ << " $countones takes one argument" ;
791
+ }
792
+
793
+ // The return type is 'int'
794
+ expr.type () = verilog_int_typet{}.lower ();
795
+
796
+ return std::move (expr);
797
+ }
758
798
else if (identifier==" $onehot" ) // SystemVerilog
759
799
{
760
800
if (arguments.size ()!=1 )
@@ -1586,6 +1626,17 @@ exprt verilog_typecheck_exprt::elaborate_constant_system_function_call(
1586
1626
DATA_INVARIANT (arguments.size () == 1 , " $increment has one argument" );
1587
1627
return increment (arguments[0 ]);
1588
1628
}
1629
+ else if (identifier == " $countones" )
1630
+ {
1631
+ DATA_INVARIANT (arguments.size () == 1 , " $countones has one argument" );
1632
+
1633
+ auto op = elaborate_constant_expression (arguments[0 ]);
1634
+
1635
+ if (!op.is_constant ())
1636
+ return std::move (expr); // give up
1637
+
1638
+ return countones (to_constant_expr (op));
1639
+ }
1589
1640
else if (identifier == " $clog2" )
1590
1641
{
1591
1642
// the ceiling of the log with base 2 of the argument
0 commit comments