Skip to content

Commit 7ed5b30

Browse files
committed
Verilog: aval/bval lowering of 4-valued logic
This introduces the standard aval/bval lowering of Verilog's 4-valued logic into bit vectors.
1 parent 73ecda7 commit 7ed5b30

File tree

7 files changed

+174
-39
lines changed

7 files changed

+174
-39
lines changed

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ IREP_ID_ONE(uwire)
148148
IREP_ID_ONE(wand)
149149
IREP_ID_ONE(automatic)
150150
IREP_ID_TWO(C_verilog_type, #verilog_type)
151+
IREP_ID_TWO(C_verilog_aval_bval, #verilog_aval_bval)
151152
IREP_ID_ONE(verilog_enum)
152153
IREP_ID_ONE(verilog_packed_array)
153154
IREP_ID_ONE(verilog_type_reference)

src/verilog/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
SRC = expr2verilog.cpp \
1+
SRC = aval_bval_encoding.cpp \
2+
expr2verilog.cpp \
23
sva_expr.cpp \
34
verilog_elaborate.cpp \
45
verilog_expr.cpp \

src/verilog/aval_bval_encoding.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*******************************************************************\
2+
3+
Module: aval/bval encoding
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "aval_bval_encoding.h"
10+
11+
#include <util/arith_tools.h>
12+
#include <util/bitvector_types.h>
13+
#include <util/std_expr.h>
14+
15+
bv_typet aval_bval_type(std::size_t width)
16+
{
17+
auto result = bv_typet{width * 2};
18+
result.set(ID_C_verilog_aval_bval, true);
19+
return result;
20+
}
21+
22+
bv_typet lower_to_aval_bval(const typet &src)
23+
{
24+
PRECONDITION(
25+
src.id() == ID_verilog_unsignedbv || src.id() == ID_verilog_signedbv);
26+
return aval_bval_type(to_bitvector_type(src).get_width());
27+
}
28+
29+
bool is_aval_bval(const typet &type)
30+
{
31+
return type.id() == ID_bv && type.get_bool(ID_C_verilog_aval_bval);
32+
}
33+
34+
std::size_t aval_bval_width(const typet &type)
35+
{
36+
PRECONDITION(is_aval_bval(type));
37+
return to_bv_type(type).get_width() / 2;
38+
}
39+
40+
constant_exprt lower_to_aval_bval(const constant_exprt &src)
41+
{
42+
PRECONDITION(
43+
src.type().id() == ID_verilog_signedbv ||
44+
src.type().id() == ID_verilog_unsignedbv);
45+
46+
auto new_type = lower_to_aval_bval(src.type());
47+
auto width = aval_bval_width(new_type);
48+
auto &value = id2string(src.get_value());
49+
50+
auto bv_f = [width, value](const std::size_t dest_index) {
51+
bool bval = dest_index >= width;
52+
std::size_t src_index = bval ? dest_index - width : dest_index;
53+
54+
// bval aval | 4-state Verilog value
55+
// ----------|----------------------
56+
// 0 0 | 0
57+
// 0 1 | 1
58+
// 1 0 | X
59+
// 1 1 | Z
60+
61+
switch(value[src_index])
62+
{
63+
case '0':
64+
return bval ? 0 : 0;
65+
case '1':
66+
return bval ? 0 : 1;
67+
case 'z':
68+
return bval ? 1 : 1;
69+
case 'x':
70+
return bval ? 1 : 0;
71+
default:
72+
INVARIANT(false, "unexpected Verilog vector bit");
73+
}
74+
};
75+
76+
return constant_exprt{make_bvrep(width * 2, bv_f), new_type};
77+
}

src/verilog/aval_bval_encoding.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*******************************************************************\
2+
3+
Module: aval/bval encoding
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_VERILOG_AVAL_BVAL_H
10+
#define CPROVER_VERILOG_AVAL_BVAL_H
11+
12+
#include <util/expr.h>
13+
14+
class bv_typet;
15+
class constant_exprt;
16+
17+
// bit-concoding for four-valued types
18+
//
19+
// bval aval | 4-state Verilog value
20+
// ----------|----------------------
21+
// 0 0 | 0
22+
// 0 1 | 1
23+
// 1 0 | X
24+
// 1 1 | Z
25+
26+
bool is_aval_bval(const typet &);
27+
std::size_t aval_bval_width(const typet &);
28+
29+
bv_typet lower_to_aval_bval(const typet &);
30+
constant_exprt lower_to_aval_bval(const constant_exprt &);
31+
32+
// extract a/b vectors
33+
exprt aval_bval_a(const exprt &);
34+
exprt aval_bval_b(const exprt &);
35+
36+
#endif

src/verilog/verilog_synthesis.cpp

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Author: Daniel Kroening, [email protected]
1818
#include <util/simplify_expr.h>
1919
#include <util/std_expr.h>
2020

21+
#include "aval_bval_encoding.h"
2122
#include "expr2verilog.h"
2223
#include "sva_expr.h"
2324
#include "verilog_expr.h"
@@ -74,6 +75,18 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
7475
UNREACHABLE;
7576
}
7677
}
78+
else if(expr.id() == ID_constant)
79+
{
80+
// encode into aval/bval
81+
if(
82+
expr.type().id() == ID_verilog_unsignedbv ||
83+
expr.type().id() == ID_verilog_signedbv)
84+
{
85+
return lower_to_aval_bval(to_constant_expr(expr));
86+
}
87+
88+
return expr;
89+
}
7790
else if(expr.id()==ID_function_call)
7891
{
7992
return expand_function_call(to_function_call_expr(expr));
@@ -2262,15 +2275,14 @@ exprt verilog_synthesist::case_comparison(
22622275
{
22632276
// we need to take case of ?, x, z in the pattern
22642277
const typet &pattern_type=pattern.type();
2265-
2266-
if(pattern_type.id()==ID_verilog_signedbv ||
2267-
pattern_type.id()==ID_verilog_unsignedbv)
2278+
2279+
if(is_aval_bval(pattern_type))
22682280
{
22692281
// try to simplify the pattern
22702282
exprt tmp=pattern;
22712283

22722284
simplify(tmp, ns);
2273-
2285+
22742286
if(tmp.id()!=ID_constant)
22752287
{
22762288
warning().source_location=pattern.source_location();
@@ -2279,43 +2291,39 @@ exprt verilog_synthesist::case_comparison(
22792291
else
22802292
{
22812293
exprt new_case_operand=case_operand;
2294+
auto width = aval_bval_width(pattern_type);
22822295

22832296
// the pattern has the max type
2284-
unsignedbv_typet new_type(pattern.type().get_int(ID_width));
2285-
new_case_operand = typecast_exprt{new_case_operand, new_type};
2286-
2287-
// we are using masking!
2288-
2289-
std::string new_pattern_value=
2290-
id2string(to_constant_expr(tmp).get_value());
2291-
2292-
// ?zx -> 0
2293-
for(unsigned i=0; i<new_pattern_value.size(); i++)
2294-
if(new_pattern_value[i]=='?' ||
2295-
new_pattern_value[i]=='z' ||
2296-
new_pattern_value[i]=='x')
2297-
new_pattern_value[i]='0';
2297+
bv_typet comparison_type{width};
2298+
new_case_operand = typecast_exprt{new_case_operand, comparison_type};
22982299

2299-
auto new_pattern =
2300-
from_integer(string2integer(new_pattern_value, 2), new_type);
2300+
auto &pattern_value = id2string(to_constant_expr(tmp).get_value());
23012301

2302-
std::string new_mask_value=
2303-
id2string(to_constant_expr(tmp).get_value());
2304-
2305-
// ?zx -> 0, 0 -> 1
2306-
for(unsigned i=0; i<new_mask_value.size(); i++)
2307-
if(new_mask_value[i]=='?' ||
2308-
new_mask_value[i]=='z' ||
2309-
new_mask_value[i]=='x')
2310-
new_mask_value[i]='0';
2311-
else
2312-
new_mask_value[i]='1';
2313-
2314-
auto new_mask = from_integer(string2integer(new_mask_value, 2), new_type);
2315-
2316-
exprt bitand_expr = bitand_exprt{new_case_operand, new_mask};
2317-
2318-
return equal_exprt{bitand_expr, new_pattern};
2302+
// we are using masking!
2303+
auto value_bvrep =
2304+
make_bvrep(width, [pattern_value](const std::size_t index) {
2305+
// 0?zx -> 0
2306+
// 1 -> 1
2307+
DATA_INVARIANT(
2308+
index < pattern_value.size(), "index within pattern_value");
2309+
return pattern_value[index] == '1';
2310+
});
2311+
2312+
auto mask_bvrep =
2313+
make_bvrep(width, [pattern_value](const std::size_t index) {
2314+
// ?zx -> 0
2315+
// 01 -> 1
2316+
DATA_INVARIANT(
2317+
index < pattern_value.size(), "index within pattern_value");
2318+
return pattern_value[index] == '0' || pattern_value[index] == '1';
2319+
});
2320+
2321+
auto value_expr = constant_exprt{value_bvrep, comparison_type};
2322+
auto mask_expr = constant_exprt{mask_bvrep, comparison_type};
2323+
2324+
exprt bitand_expr = bitand_exprt{new_case_operand, mask_expr};
2325+
2326+
return equal_exprt{bitand_expr, value_expr};
23192327
}
23202328
}
23212329

src/verilog/verilog_synthesis_class.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, [email protected]
99
#ifndef CPROVER_VERILOG_SYNTHESIS_CLASS_H
1010
#define CPROVER_VERILOG_SYNTHESIS_CLASS_H
1111

12+
#include <util/bitvector_types.h>
1213
#include <util/mathematical_expr.h>
1314
#include <util/mp_arith.h>
1415
#include <util/options.h>
@@ -326,6 +327,17 @@ class verilog_synthesist:
326327
void function_locality(const symbolt &);
327328

328329
unsigned temporary_counter;
330+
331+
static bool is_aval_bval(const typet &type)
332+
{
333+
return type.id() == ID_bv && type.get_bool(ID_C_verilog_aval_bval);
334+
}
335+
336+
static std::size_t aval_bval_width(const typet &type)
337+
{
338+
PRECONDITION(is_aval_bval(type));
339+
return to_bv_type(type).get_width() / 2;
340+
}
329341
};
330342

331343
#endif

0 commit comments

Comments
 (0)