Skip to content

Commit d560cae

Browse files
authored
Merge pull request #506 from diffblue/verilog_non_indexed_part_select_exprt
introduce verilog_non_indexed_part_select_exprt
2 parents f75c8e0 + 74225fd commit d560cae

File tree

2 files changed

+190
-54
lines changed

2 files changed

+190
-54
lines changed

src/verilog/verilog_expr.h

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,4 +1989,138 @@ inline verilog_past_exprt &to_verilog_past_expr(exprt &expr)
19891989
return static_cast<verilog_past_exprt &>(expr);
19901990
}
19911991

1992+
class verilog_non_indexed_part_select_exprt : public ternary_exprt
1993+
{
1994+
public:
1995+
verilog_non_indexed_part_select_exprt(
1996+
exprt src,
1997+
exprt msb,
1998+
exprt lsb,
1999+
typet type)
2000+
: ternary_exprt(
2001+
ID_verilog_non_indexed_part_select,
2002+
std::move(src),
2003+
std::move(msb),
2004+
std::move(lsb),
2005+
std::move(type))
2006+
{
2007+
}
2008+
2009+
const exprt &src() const
2010+
{
2011+
return op0();
2012+
}
2013+
2014+
exprt &src()
2015+
{
2016+
return op0();
2017+
}
2018+
2019+
const exprt &msb() const
2020+
{
2021+
return op1();
2022+
}
2023+
2024+
exprt &msb()
2025+
{
2026+
return op1();
2027+
}
2028+
2029+
const exprt &lsb() const
2030+
{
2031+
return op2();
2032+
}
2033+
2034+
exprt &lsb()
2035+
{
2036+
return op2();
2037+
}
2038+
};
2039+
2040+
inline const verilog_non_indexed_part_select_exprt &
2041+
to_verilog_non_indexed_part_select_expr(const exprt &expr)
2042+
{
2043+
PRECONDITION(expr.id() == ID_verilog_non_indexed_part_select);
2044+
verilog_non_indexed_part_select_exprt::check(expr);
2045+
return static_cast<const verilog_non_indexed_part_select_exprt &>(expr);
2046+
}
2047+
2048+
inline verilog_non_indexed_part_select_exprt &
2049+
to_verilog_non_indexed_part_select_expr(exprt &expr)
2050+
{
2051+
PRECONDITION(expr.id() == ID_verilog_non_indexed_part_select);
2052+
verilog_non_indexed_part_select_exprt::check(expr);
2053+
return static_cast<verilog_non_indexed_part_select_exprt &>(expr);
2054+
}
2055+
2056+
class verilog_indexed_part_select_plus_or_minus_exprt : public ternary_exprt
2057+
{
2058+
public:
2059+
verilog_indexed_part_select_plus_or_minus_exprt(
2060+
irep_idt id,
2061+
exprt src,
2062+
exprt index,
2063+
exprt width,
2064+
typet type)
2065+
: ternary_exprt(
2066+
id,
2067+
std::move(src),
2068+
std::move(index),
2069+
std::move(width),
2070+
std::move(type))
2071+
{
2072+
}
2073+
2074+
const exprt &src() const
2075+
{
2076+
return op0();
2077+
}
2078+
2079+
exprt &src()
2080+
{
2081+
return op0();
2082+
}
2083+
2084+
const exprt &index() const
2085+
{
2086+
return op1();
2087+
}
2088+
2089+
exprt &index()
2090+
{
2091+
return op1();
2092+
}
2093+
2094+
const exprt &width() const
2095+
{
2096+
return op2();
2097+
}
2098+
2099+
exprt &width()
2100+
{
2101+
return op2();
2102+
}
2103+
};
2104+
2105+
inline const verilog_indexed_part_select_plus_or_minus_exprt &
2106+
to_verilog_indexed_part_select_plus_or_minus_expr(const exprt &expr)
2107+
{
2108+
PRECONDITION(
2109+
expr.id() == ID_verilog_indexed_part_select_plus ||
2110+
expr.id() == ID_verilog_indexed_part_select_minus);
2111+
verilog_indexed_part_select_plus_or_minus_exprt::check(expr);
2112+
return static_cast<const verilog_indexed_part_select_plus_or_minus_exprt &>(
2113+
expr);
2114+
}
2115+
2116+
inline verilog_indexed_part_select_plus_or_minus_exprt &
2117+
to_verilog_indexed_part_select_plus_or_minus_expr(exprt &expr)
2118+
{
2119+
PRECONDITION(
2120+
expr.id() == ID_verilog_indexed_part_select_plus ||
2121+
expr.id() == ID_verilog_indexed_part_select_minus);
2122+
verilog_indexed_part_select_plus_or_minus_exprt::check(expr);
2123+
return static_cast<verilog_indexed_part_select_plus_or_minus_exprt &>(expr);
2124+
}
2125+
19922126
#endif

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,70 +2317,71 @@ exprt verilog_typecheck_exprt::convert_trinary_expr(ternary_exprt expr)
23172317
{
23182318
if(expr.id() == ID_verilog_non_indexed_part_select)
23192319
{
2320-
exprt &op0 = expr.op0();
2321-
convert_expr(op0);
2320+
auto &part_select = to_verilog_non_indexed_part_select_expr(expr);
2321+
exprt &src = part_select.src();
2322+
convert_expr(src);
23222323

2323-
if(op0.type().id()==ID_array)
2324+
if(src.type().id() == ID_array)
23242325
{
2325-
throw errort().with_location(op0.source_location())
2326+
throw errort().with_location(src.source_location())
23262327
<< "array type not allowed in part select";
23272328
}
23282329

2329-
if(op0.type().id() == ID_verilog_real)
2330+
if(src.type().id() == ID_verilog_real)
23302331
{
2331-
throw errort().with_location(op0.source_location())
2332+
throw errort().with_location(src.source_location())
23322333
<< "real not allowed in part select";
23332334
}
23342335

2335-
mp_integer op0_width = get_width(op0.type());
2336-
mp_integer op0_offset = string2integer(op0.type().get_string(ID_C_offset));
2336+
mp_integer src_width = get_width(src.type());
2337+
mp_integer src_offset = string2integer(src.type().get_string(ID_C_offset));
23372338

23382339
// In non-indexed part-select expressions, both
23392340
// indices must be constants (1800-2017 11.5.1).
2340-
mp_integer op1 = convert_integer_constant_expression(expr.op1());
2341-
mp_integer op2 = convert_integer_constant_expression(expr.op2());
2341+
mp_integer msb = convert_integer_constant_expression(part_select.msb());
2342+
mp_integer lsb = convert_integer_constant_expression(part_select.lsb());
23422343

2343-
if(op1<op2)
2344-
std::swap(op1, op2); // now op1>=op2
2344+
if(msb < lsb)
2345+
std::swap(msb, lsb); // now msb>=lsb
23452346

23462347
// 1800-2017 sec 11.5.1: out-of-bounds bit-select is
23472348
// x for 4-state and 0 for 2-state values. We
23482349
// achieve that by padding the operand from either end,
23492350
// or both.
2350-
if(op2 < op0_offset)
2351+
if(lsb < src_offset)
23512352
{
2352-
auto padding_width = op0_offset - op2;
2353+
auto padding_width = src_offset - lsb;
23532354
auto padding = from_integer(
23542355
0, unsignedbv_typet{numeric_cast_v<std::size_t>(padding_width)});
23552356
auto new_type = unsignedbv_typet{
2356-
numeric_cast_v<std::size_t>(get_width(op0.type()) + padding_width)};
2357-
expr.op0() = concatenation_exprt(expr.op0(), padding, new_type);
2358-
op2 += padding_width;
2359-
op1 += padding_width;
2357+
numeric_cast_v<std::size_t>(get_width(src.type()) + padding_width)};
2358+
src = concatenation_exprt(src, padding, new_type);
2359+
lsb += padding_width;
2360+
msb += padding_width;
23602361
}
23612362

2362-
if(op1 >= op0_width + op0_offset)
2363+
if(msb >= src_width + src_offset)
23632364
{
2364-
auto padding_width = op1 - (op0_width + op0_offset) + 1;
2365+
auto padding_width = msb - (src_width + src_offset) + 1;
23652366
auto padding = from_integer(
23662367
0, unsignedbv_typet{numeric_cast_v<std::size_t>(padding_width)});
23672368
auto new_type = unsignedbv_typet{
2368-
numeric_cast_v<std::size_t>(get_width(op0.type()) + padding_width)};
2369-
expr.op0() = concatenation_exprt(padding, expr.op0(), new_type);
2369+
numeric_cast_v<std::size_t>(get_width(src.type()) + padding_width)};
2370+
src = concatenation_exprt(padding, src, new_type);
23702371
}
23712372

23722373
// Part-select expressions are unsigned, even if the
23732374
// entire expression is selected!
23742375
auto expr_type =
2375-
unsignedbv_typet{numeric_cast_v<std::size_t>(op1 - op2 + 1)};
2376+
unsignedbv_typet{numeric_cast_v<std::size_t>(msb - lsb + 1)};
23762377

2377-
op2 -= op0_offset;
2378-
op1 -= op0_offset;
2378+
lsb -= src_offset;
2379+
msb -= src_offset;
23792380

23802381
// Construct the extractbits expression
23812382
expr.id(ID_extractbits);
2382-
expr.op1() = from_integer(op1, integer_typet());
2383-
expr.op2() = from_integer(op2, integer_typet());
2383+
expr.op1() = from_integer(msb, integer_typet());
2384+
expr.op2() = from_integer(lsb, integer_typet());
23842385
expr.type() = expr_type;
23852386

23862387
return std::move(expr);
@@ -2389,62 +2390,63 @@ exprt verilog_typecheck_exprt::convert_trinary_expr(ternary_exprt expr)
23892390
expr.id() == ID_verilog_indexed_part_select_plus ||
23902391
expr.id() == ID_verilog_indexed_part_select_minus)
23912392
{
2392-
exprt &op0 = expr.op0();
2393-
convert_expr(op0);
2393+
auto &part_select = to_verilog_indexed_part_select_plus_or_minus_expr(expr);
2394+
exprt &src = part_select.src();
2395+
convert_expr(src);
23942396

2395-
if(op0.type().id() == ID_array)
2397+
if(src.type().id() == ID_array)
23962398
{
2397-
throw errort().with_location(op0.source_location())
2399+
throw errort().with_location(src.source_location())
23982400
<< "array type not allowed in part select";
23992401
}
24002402

2401-
if(op0.type().id() == ID_verilog_real)
2403+
if(src.type().id() == ID_verilog_real)
24022404
{
2403-
throw errort().with_location(op0.source_location())
2405+
throw errort().with_location(src.source_location())
24042406
<< "real not allowed in part select";
24052407
}
24062408

2407-
mp_integer op0_width = get_width(op0.type());
2408-
mp_integer op0_offset = string2integer(op0.type().get_string(ID_C_offset));
2409+
mp_integer src_width = get_width(src.type());
2410+
mp_integer src_offset = string2integer(src.type().get_string(ID_C_offset));
24092411

24102412
// The index need not be a constant.
2411-
exprt &op1 = expr.op1();
2412-
convert_expr(op1);
2413+
exprt &index = part_select.index();
2414+
convert_expr(index);
24132415

24142416
// The width of the indexed part select must be an
24152417
// elaboration-time constant.
2416-
mp_integer op2 = convert_integer_constant_expression(expr.op2());
2418+
mp_integer width = convert_integer_constant_expression(part_select.width());
24172419

24182420
// The width must be positive. 1800-2017 11.5.1
2419-
if(op2 < 0)
2421+
if(width < 0)
24202422
{
2421-
throw errort().with_location(expr.op2().source_location())
2423+
throw errort().with_location(part_select.width().source_location())
24222424
<< "width of indexed part select must be positive";
24232425
}
24242426

24252427
// Part-select expressions are unsigned, even if the
24262428
// entire expression is selected!
2427-
auto expr_type = unsignedbv_typet{numeric_cast_v<std::size_t>(op2)};
2429+
auto expr_type = unsignedbv_typet{numeric_cast_v<std::size_t>(width)};
24282430

2429-
mp_integer op1_int;
2430-
if(is_constant_expression(op1, op1_int))
2431+
mp_integer index_int;
2432+
if(is_constant_expression(index, index_int))
24312433
{
24322434
// Construct the extractbits expression
24332435
mp_integer bottom, top;
24342436

2435-
if(expr.id() == ID_verilog_indexed_part_select_plus)
2437+
if(part_select.id() == ID_verilog_indexed_part_select_plus)
24362438
{
2437-
bottom = op1_int - op0_offset;
2438-
top = bottom + op2;
2439+
bottom = index_int - src_offset;
2440+
top = bottom + width;
24392441
}
24402442
else // ID_verilog_indexed_part_select_minus
24412443
{
2442-
top = op1_int - op0_offset;
2443-
bottom = bottom - op2;
2444+
top = index_int - src_offset;
2445+
bottom = bottom - width;
24442446
}
24452447

24462448
return extractbits_exprt{
2447-
std::move(op0),
2449+
std::move(src),
24482450
from_integer(top, integer_typet{}),
24492451
from_integer(bottom, integer_typet{}),
24502452
std::move(expr_type)}
@@ -2454,14 +2456,14 @@ exprt verilog_typecheck_exprt::convert_trinary_expr(ternary_exprt expr)
24542456
{
24552457
// Index not constant.
24562458
// Use logical right-shift followed by (constant) extractbits.
2457-
auto op1_adjusted =
2458-
minus_exprt{op1, from_integer(op0_offset, op1.type())};
2459+
auto index_adjusted =
2460+
minus_exprt{index, from_integer(src_offset, index.type())};
24592461

2460-
auto op0_shifted = lshr_exprt(op0, op1_adjusted);
2462+
auto src_shifted = lshr_exprt(src, index_adjusted);
24612463

24622464
return extractbits_exprt{
2463-
std::move(op0_shifted),
2464-
from_integer(op2 - 1, integer_typet{}),
2465+
std::move(src_shifted),
2466+
from_integer(width - 1, integer_typet{}),
24652467
from_integer(0, integer_typet{}),
24662468
std::move(expr_type)}
24672469
.with_source_location(expr);

0 commit comments

Comments
 (0)