Skip to content

Commit 21146f9

Browse files
authored
Merge pull request #581 from diffblue/array_functions1
Verilog: `$low`, `$high`, `$increment`, `$left`, `$right`
2 parents dbed35e + d70f5f2 commit 21146f9

File tree

4 files changed

+257
-2
lines changed

4 files changed

+257
-2
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
CORE
2+
array_functions1.sv
3+
--module main --bound 0
4+
^\[main\.pP0\] always 32 == 32 && 1 == 1: PROVED up to bound 0$
5+
^\[main\.pP1\] always 0 == 0 && 31 == 31: PROVED up to bound 0$
6+
^\[main\.pP2\] always 1 == 1 && 32 == 32: PROVED up to bound 0$
7+
^\[main\.pP3\] always 0 == 0 && 31 == 31: PROVED up to bound 0$
8+
^\[main\.pP4\] always 1 == 1: PROVED up to bound 0$
9+
^\[main\.pP5\] always -1 == -1: PROVED up to bound 0$
10+
^\[main\.pU0\] always 32 == 32 && 1 == 1: PROVED up to bound 0$
11+
^\[main\.pU1\] always 0 == 0 && 31 == 31: PROVED up to bound 0$
12+
^\[main\.pU2\] always 31 == 31 && 0 == 0: PROVED up to bound 0$
13+
^\[main\.pU3\] always 1 == 1 && 32 == 32: PROVED up to bound 0$
14+
^\[main\.pU4\] always 0 == 0 && 31 == 31: PROVED up to bound 0$
15+
^\[main\.pU5\] always 0 == 0 && 31 == 31: PROVED up to bound 0$
16+
^\[main\.pU6\] always 1 == 1: PROVED up to bound 0$
17+
^\[main\.pU7\] always -1 == -1: PROVED up to bound 0$
18+
^\[main\.pU8\] always 1 == 1: PROVED up to bound 0$
19+
^EXIT=0$
20+
^SIGNAL=0$
21+
--
22+
^warning: ignoring
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module main;
2+
3+
wire [32:1] packed1;
4+
wire [0:31] packed2;
5+
6+
wire unpacked1 [32:1];
7+
wire unpacked2 [0:31];
8+
wire unpacked3 [32];
9+
10+
pP0: assert property ($left(packed1) == 32 and $right(packed1) == 1);
11+
pP1: assert property ($left(packed2) == 0 and $right(packed2) == 31);
12+
pP2: assert property ($low(packed1) == 1 and $high(packed1) == 32);
13+
pP3: assert property ($low(packed2) == 0 and $high(packed2) == 31);
14+
pP4: assert property ($increment(packed1) == 1);
15+
pP5: assert property ($increment(packed2) == -1);
16+
17+
pU0: assert property ($left(unpacked1) == 32 and $right(unpacked1) == 1);
18+
pU1: assert property ($left(unpacked2) == 0 and $right(unpacked2) == 31);
19+
pU2: assert property ($left(unpacked3) == 31 and $right(unpacked3) == 0);
20+
pU3: assert property ($low(unpacked1) == 1 and $high(unpacked1) == 32);
21+
pU4: assert property ($low(unpacked2) == 0 and $high(unpacked2) == 31);
22+
pU5: assert property ($low(unpacked3) == 0 and $high(unpacked3) == 31);
23+
pU6: assert property ($increment(unpacked1) == 1);
24+
pU7: assert property ($increment(unpacked2) == -1);
25+
pU8: assert property ($increment(unpacked3) == 1);
26+
27+
endmodule

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 202 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,179 @@ exprt verilog_typecheck_exprt::bits(const exprt &expr)
447447

448448
/*******************************************************************\
449449
450+
Function: verilog_typecheck_exprt::left
451+
452+
Inputs:
453+
454+
Outputs:
455+
456+
Purpose:
457+
458+
\*******************************************************************/
459+
460+
constant_exprt verilog_typecheck_exprt::left(const exprt &expr)
461+
{
462+
// unpacked array: left bound
463+
// packed array: index of most significant element
464+
// 0 otherwise
465+
auto left = [](const typet &type) -> mp_integer {
466+
if(
467+
type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
468+
type.id() == ID_verilog_unsignedbv || type.id() == ID_verilog_signedbv ||
469+
type.id() == ID_bool)
470+
{
471+
auto offset = type.get_int(ID_C_offset);
472+
if(type.get_bool(ID_C_little_endian))
473+
return offset + get_width(type) - 1;
474+
else
475+
return offset;
476+
}
477+
else if(type.id() == ID_array)
478+
{
479+
auto offset = numeric_cast_v<mp_integer>(
480+
to_constant_expr(static_cast<const exprt &>(type.find(ID_offset))));
481+
if(type.get_bool(ID_C_little_endian))
482+
return offset +
483+
numeric_cast_v<mp_integer>(
484+
to_constant_expr(to_array_type(type).size())) -
485+
1;
486+
else
487+
return offset;
488+
}
489+
else
490+
return 0;
491+
};
492+
493+
return from_integer(left(expr.type()), integer_typet{});
494+
}
495+
496+
/*******************************************************************\
497+
498+
Function: verilog_typecheck_exprt::right
499+
500+
Inputs:
501+
502+
Outputs:
503+
504+
Purpose:
505+
506+
\*******************************************************************/
507+
508+
constant_exprt verilog_typecheck_exprt::right(const exprt &expr)
509+
{
510+
// unpacked array: right bound
511+
// packed array: index of least significant element
512+
// 0 otherwise
513+
auto right = [](const typet &type) -> mp_integer {
514+
if(
515+
type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
516+
type.id() == ID_verilog_unsignedbv || type.id() == ID_verilog_signedbv ||
517+
type.id() == ID_bool)
518+
{
519+
auto offset = type.get_int(ID_C_offset);
520+
if(type.get_bool(ID_C_little_endian))
521+
return offset;
522+
else
523+
return offset + get_width(type) - 1;
524+
}
525+
else if(type.id() == ID_array)
526+
{
527+
auto offset = numeric_cast_v<mp_integer>(
528+
to_constant_expr(static_cast<const exprt &>(type.find(ID_offset))));
529+
if(type.get_bool(ID_C_little_endian))
530+
return offset;
531+
else
532+
return offset +
533+
numeric_cast_v<mp_integer>(
534+
to_constant_expr(to_array_type(type).size())) -
535+
1;
536+
}
537+
else
538+
return 0;
539+
};
540+
541+
return from_integer(right(expr.type()), integer_typet{});
542+
}
543+
544+
/*******************************************************************\
545+
546+
Function: verilog_typecheck_exprt::increment
547+
548+
Inputs:
549+
550+
Outputs:
551+
552+
Purpose:
553+
554+
\*******************************************************************/
555+
556+
constant_exprt verilog_typecheck_exprt::increment(const exprt &expr)
557+
{
558+
// fixed-size dimension: 1 if $left >= $right, -1 otherwise
559+
auto increment = [](const typet &type) -> mp_integer {
560+
if(
561+
type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
562+
type.id() == ID_verilog_unsignedbv || type.id() == ID_verilog_signedbv ||
563+
type.id() == ID_array)
564+
{
565+
if(type.get_bool(ID_C_little_endian))
566+
return 1;
567+
else
568+
return -1;
569+
}
570+
else
571+
return -1;
572+
};
573+
574+
return from_integer(increment(expr.type()), integer_typet{});
575+
}
576+
577+
/*******************************************************************\
578+
579+
Function: verilog_typecheck_exprt::low
580+
581+
Inputs:
582+
583+
Outputs:
584+
585+
Purpose:
586+
587+
\*******************************************************************/
588+
589+
constant_exprt verilog_typecheck_exprt::low(const exprt &expr)
590+
{
591+
// $left if $increment returns –1
592+
// $right otherwise
593+
if(numeric_cast_v<mp_integer>(increment(expr)) == -1)
594+
return left(expr);
595+
else
596+
return right(expr);
597+
}
598+
599+
/*******************************************************************\
600+
601+
Function: verilog_typecheck_exprt::high
602+
603+
Inputs:
604+
605+
Outputs:
606+
607+
Purpose:
608+
609+
\*******************************************************************/
610+
611+
constant_exprt verilog_typecheck_exprt::high(const exprt &expr)
612+
{
613+
// $right if $increment returns –1
614+
// $left otherwise
615+
if(numeric_cast_v<mp_integer>(increment(expr)) == -1)
616+
return right(expr);
617+
else
618+
return left(expr);
619+
}
620+
621+
/*******************************************************************\
622+
450623
Function: verilog_typecheck_exprt::convert_system_function
451624
452625
Inputs:
@@ -549,12 +722,14 @@ exprt verilog_typecheck_exprt::convert_system_function(
549722
expr.type() = arguments.front().type();
550723
return std::move(expr);
551724
}
552-
else if(identifier == "$bits")
725+
else if(
726+
identifier == "$bits" || identifier == "$left" || identifier == "$right" ||
727+
identifier == "$increment" || identifier == "$low" || identifier == "$high")
553728
{
554729
if(arguments.size() != 1)
555730
{
556731
throw errort().with_location(expr.source_location())
557-
<< "$bits takes one argument";
732+
<< identifier << " takes one argument";
558733
}
559734

560735
// The return type is integer.
@@ -1370,6 +1545,31 @@ exprt verilog_typecheck_exprt::elaborate_constant_system_function_call(
13701545
DATA_INVARIANT(arguments.size() == 1, "$bits has one argument");
13711546
return bits(arguments[0]);
13721547
}
1548+
else if(identifier == "$low")
1549+
{
1550+
DATA_INVARIANT(arguments.size() == 1, "$low has one argument");
1551+
return low(arguments[0]);
1552+
}
1553+
else if(identifier == "$high")
1554+
{
1555+
DATA_INVARIANT(arguments.size() == 1, "$high has one argument");
1556+
return high(arguments[0]);
1557+
}
1558+
else if(identifier == "$left")
1559+
{
1560+
DATA_INVARIANT(arguments.size() == 1, "$left has one argument");
1561+
return left(arguments[0]);
1562+
}
1563+
else if(identifier == "$right")
1564+
{
1565+
DATA_INVARIANT(arguments.size() == 1, "$right has one argument");
1566+
return right(arguments[0]);
1567+
}
1568+
else if(identifier == "$increment")
1569+
{
1570+
DATA_INVARIANT(arguments.size() == 1, "$increment has one argument");
1571+
return increment(arguments[0]);
1572+
}
13731573
else if(identifier == "$clog2")
13741574
{
13751575
// the ceiling of the log with base 2 of the argument

src/verilog/verilog_typecheck_expr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,14 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
133133
void tc_binary_expr(const exprt &expr, exprt &op0, exprt &op1);
134134
void no_bool_ops(exprt &);
135135

136+
// system functions
136137
exprt bits(const exprt &);
137138
std::optional<mp_integer> bits_rec(const typet &) const;
139+
constant_exprt left(const exprt &);
140+
constant_exprt right(const exprt &);
141+
constant_exprt low(const exprt &);
142+
constant_exprt high(const exprt &);
143+
constant_exprt increment(const exprt &);
138144
};
139145

140146
bool verilog_typecheck(

0 commit comments

Comments
 (0)