Skip to content

Commit cfea2ef

Browse files
committed
SystemVerilog: $countones
This adds the SystemVerilog system function $countones (IEEE 1800-2017 20.9).
1 parent 4b8a2d3 commit cfea2ef

File tree

7 files changed

+99
-0
lines changed

7 files changed

+99
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
countones1.sv
3+
--module main --bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module main;
2+
3+
always assert ($countones('b10101)==3);
4+
5+
// $countones yields an elaboration-time constant
6+
parameter P = 123;
7+
parameter Q = $countones(P);
8+
9+
endmodule
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
KNOWNBUG
2+
countones2.sv
3+
--bound 10
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module gray_counter#(N = 4) (input clk, resetn, output reg [N-1:0] out);
2+
3+
reg [N-1:0] state;
4+
5+
always_ff @(posedge clk) begin
6+
if (!resetn) begin
7+
state <= 0;
8+
out <= 0;
9+
end else begin
10+
state <= state + 1;
11+
out <= {state[N-1], state[N-1:1] ^ state[N-2:0]};
12+
end
13+
end
14+
15+
// two successive values differ in one bit exactly
16+
p0: assert property (@(posedge clk)
17+
$countones($past(out) ^ out) == 1);
18+
19+
endmodule

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,33 @@ constant_exprt verilog_typecheck_exprt::right(const exprt &expr)
561561

562562
/*******************************************************************\
563563
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+
564591
Function: verilog_typecheck_exprt::increment
565592
566593
Inputs:
@@ -755,6 +782,19 @@ exprt verilog_typecheck_exprt::convert_system_function(
755782

756783
return std::move(expr);
757784
}
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+
}
758798
else if(identifier=="$onehot") // SystemVerilog
759799
{
760800
if(arguments.size()!=1)
@@ -1586,6 +1626,17 @@ exprt verilog_typecheck_exprt::elaborate_constant_system_function_call(
15861626
DATA_INVARIANT(arguments.size() == 1, "$increment has one argument");
15871627
return increment(arguments[0]);
15881628
}
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+
}
15891640
else if(identifier == "$clog2")
15901641
{
15911642
// the ceiling of the log with base 2 of the argument

src/verilog/verilog_typecheck_expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
137137
// system functions
138138
exprt bits(const exprt &);
139139
std::optional<mp_integer> bits_rec(const typet &) const;
140+
constant_exprt countones(const constant_exprt &);
140141
constant_exprt left(const exprt &);
141142
constant_exprt right(const exprt &);
142143
constant_exprt low(const exprt &);

src/verilog/verilog_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ class verilog_int_typet : public typet
218218
{
219219
return 32;
220220
}
221+
222+
typet lower() const
223+
{
224+
return signedbv_typet{width()};
225+
}
221226
};
222227

223228
/// 2-state data type, 64-bit signed integer

0 commit comments

Comments
 (0)