Skip to content

Commit b9dc4f3

Browse files
committed
SystemVerilog: structs
This adds support for SystemVerilog struct types.
1 parent 3fc2299 commit b9dc4f3

File tree

7 files changed

+165
-57
lines changed

7 files changed

+165
-57
lines changed
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
structs1.sv
3+
--bound 0
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module main;
2+
3+
// The first field is the most-significant bit.
4+
struct packed {
5+
bit field1, field2;
6+
bit [6:0] field3;
7+
} s = 'b1011111;
8+
9+
// Expected to pass.
10+
p1: assert property (s.field1 == 1);
11+
p2: assert property (s.field2 == 0);
12+
p3: assert property (s.field3 == 'b111111);
13+
14+
endmodule

src/verilog/expr2verilog.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,14 @@ std::string expr2verilogt::convert(const typet &type)
12511251
{
12521252
return "enum";
12531253
}
1254+
else if(type.id() == ID_struct)
1255+
{
1256+
return "struct";
1257+
}
1258+
else if(type.id() == ID_union)
1259+
{
1260+
return "union";
1261+
}
12541262
else if(type.id() == ID_verilog_type_reference)
12551263
{
12561264
auto &type_reference = to_verilog_type_reference(type);

src/verilog/parser.y

+22-3
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,11 @@ property_qualifier:
978978
| class_item_qualifier
979979
;
980980

981+
random_qualifier_opt:
982+
/* Optional */
983+
| random_qualifier
984+
;
985+
981986
random_qualifier:
982987
TOK_RAND
983988
| TOK_RANDC
@@ -1250,8 +1255,9 @@ data_type:
12501255
}
12511256
| non_integer_type
12521257
| struct_union packed_opt signing_opt
1253-
'{' struct_union_member_list '}' packed_dimension_brace
1254-
{ /* todo */ }
1258+
'{' struct_union_member_brace '}' packed_dimension_brace
1259+
{ $$=$1;
1260+
addswap($$, ID_declaration_list, $5); }
12551261
| TOK_ENUM enum_base_type_opt '{' enum_name_declaration_list '}'
12561262
{ // Like in C, these do _not_ create a scope.
12571263
// The enum names go into the current scope.
@@ -1330,7 +1336,20 @@ integer_atom_type:
13301336
class_type: class_identifier
13311337
;
13321338

1333-
struct_union_member_list:
1339+
struct_union_member_brace:
1340+
/* Not optional! No empty structs. */
1341+
struct_union_member
1342+
{ init($$); mts($$, $1); }
1343+
| struct_union_member_brace struct_union_member
1344+
{ $$=$1; mts($$, $2); }
1345+
;
1346+
1347+
struct_union_member:
1348+
attribute_instance_brace
1349+
random_qualifier_opt
1350+
data_type_or_void
1351+
list_of_variable_decl_assignments ';'
1352+
{ $$=$4; stack_expr($$).id(ID_decl); addswap($$, ID_type, $3); }
13341353
;
13351354

13361355
enum_base_type_opt:

src/verilog/verilog_expr.h

+45-41
Original file line numberDiff line numberDiff line change
@@ -402,55 +402,59 @@ inline verilog_set_genvarst &to_verilog_set_genvars(exprt &expr)
402402
return static_cast<verilog_set_genvarst &>(expr);
403403
}
404404

405-
class verilog_parameter_declt : public verilog_module_itemt
405+
// This class is used for all declarators in the parse tree
406+
class verilog_declaratort : public exprt
406407
{
407408
public:
408-
inline verilog_parameter_declt() : verilog_module_itemt(ID_parameter_decl)
409+
const irep_idt &identifier() const
409410
{
411+
return get(ID_identifier);
410412
}
411413

412-
class declaratort : public exprt
414+
void identifier(irep_idt _identifier)
413415
{
414-
public:
415-
const irep_idt &identifier() const
416-
{
417-
return get(ID_identifier);
418-
}
416+
set(ID_identifier, _identifier);
417+
}
419418

420-
void identifier(irep_idt _identifier)
421-
{
422-
set(ID_identifier, _identifier);
423-
}
419+
const irep_idt &base_name() const
420+
{
421+
return get(ID_base_name);
422+
}
424423

425-
const irep_idt &base_name() const
426-
{
427-
return get(ID_base_name);
428-
}
424+
const exprt &value() const
425+
{
426+
return static_cast<const exprt &>(find(ID_value));
427+
}
429428

430-
const exprt &value() const
431-
{
432-
return static_cast<const exprt &>(find(ID_value));
433-
}
429+
exprt &value()
430+
{
431+
return static_cast<exprt &>(add(ID_value));
432+
}
434433

435-
exprt &value()
436-
{
437-
return static_cast<exprt &>(add(ID_value));
438-
}
434+
bool has_value() const
435+
{
436+
return find(ID_value).is_not_nil();
437+
}
439438

440-
bool has_value() const
441-
{
442-
return find(ID_value).is_not_nil();
443-
}
439+
// helper to generate a symbol expression
440+
symbol_exprt symbol_expr() const
441+
{
442+
return symbol_exprt(identifier(), type())
443+
.with_source_location<symbol_exprt>(*this);
444+
}
445+
};
444446

445-
// helper to generate a symbol expression
446-
symbol_exprt symbol_expr() const
447-
{
448-
return symbol_exprt(identifier(), type())
449-
.with_source_location<symbol_exprt>(*this);
450-
}
451-
};
447+
using verilog_declaratorst = std::vector<verilog_declaratort>;
448+
449+
class verilog_parameter_declt : public verilog_module_itemt
450+
{
451+
public:
452+
inline verilog_parameter_declt() : verilog_module_itemt(ID_parameter_decl)
453+
{
454+
}
452455

453-
using declaratorst = std::vector<declaratort>;
456+
using declaratort = verilog_declaratort;
457+
using declaratorst = verilog_declaratorst;
454458

455459
const declaratorst &declarations() const
456460
{
@@ -484,8 +488,8 @@ class verilog_local_parameter_declt : public verilog_module_itemt
484488
{
485489
}
486490

487-
using declaratort = verilog_parameter_declt::declaratort;
488-
using declaratorst = std::vector<declaratort>;
491+
using declaratort = verilog_declaratort;
492+
using declaratorst = verilog_declaratorst;
489493

490494
const declaratorst &declarations() const
491495
{
@@ -516,7 +520,7 @@ class verilog_lett : public verilog_module_itemt
516520
{
517521
public:
518522
// These have a single declarator.
519-
using declaratort = verilog_parameter_declt::declaratort;
523+
using declaratort = verilog_declaratort;
520524

521525
const declaratort &declarator() const
522526
{
@@ -700,8 +704,8 @@ class verilog_declt:public verilog_statementt
700704
}
701705

702706
// When it's not a function or task, there are declarators.
703-
using declaratort = verilog_parameter_declt::declaratort;
704-
using declaratorst = verilog_parameter_declt::declaratorst;
707+
using declaratort = verilog_declaratort;
708+
using declaratorst = verilog_declaratorst;
705709

706710
declaratorst &declarators()
707711
{

src/verilog/verilog_typecheck_expr.cpp

+40-13
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,11 @@ exprt verilog_typecheck_exprt::convert_hierarchical_identifier(
954954
<< "identifier `" << rhs_identifier << "' not found in named block";
955955
}
956956
}
957+
else if(
958+
expr.lhs().type().id() == ID_struct || expr.lhs().type().id() == ID_union)
959+
{
960+
throw errort().with_location(expr.source_location()) << "TBD";
961+
}
957962
else
958963
{
959964
throw errort().with_location(expr.source_location())
@@ -1490,23 +1495,25 @@ void verilog_typecheck_exprt::implicit_typecast(
14901495
if(dest_type.id()==irep_idt())
14911496
return;
14921497

1498+
const typet &src_type = expr.type();
1499+
14931500
auto &verilog_dest_type = dest_type.get(ID_C_verilog_type);
14941501
if(verilog_dest_type == ID_verilog_enum)
14951502
{
14961503
// IEEE 1800-2017 6.19.3: "a variable of type enum cannot be directly
14971504
// assigned a value that lies outside the enumeration set unless an
14981505
// explicit cast is used"
14991506
if(
1500-
expr.type().get(ID_C_verilog_type) != ID_verilog_enum ||
1501-
expr.type().get(ID_C_identifier) != dest_type.get(ID_C_identifier))
1507+
src_type.get(ID_C_verilog_type) != ID_verilog_enum ||
1508+
src_type.get(ID_C_identifier) != dest_type.get(ID_C_identifier))
15021509
{
15031510
throw errort().with_location(expr.source_location())
15041511
<< "assignment to enum requires enum of the same type, but got "
15051512
<< to_string(expr.type());
15061513
}
15071514
}
15081515

1509-
if(expr.type()==dest_type)
1516+
if(src_type==dest_type)
15101517
return;
15111518

15121519
if(dest_type.id() == ID_integer)
@@ -1527,15 +1534,15 @@ void verilog_typecheck_exprt::implicit_typecast(
15271534
}
15281535

15291536
if(
1530-
expr.type().id() == ID_bool || expr.type().id() == ID_unsignedbv ||
1531-
expr.type().id() == ID_signedbv || expr.type().id() == ID_integer)
1537+
src_type.id() == ID_bool || src_type.id() == ID_unsignedbv ||
1538+
src_type.id() == ID_signedbv || src_type.id() == ID_integer)
15321539
{
15331540
expr = typecast_exprt{expr, dest_type};
15341541
return;
15351542
}
15361543
}
15371544

1538-
if(expr.type().id() == ID_integer)
1545+
if(src_type.id() == ID_integer)
15391546
{
15401547
// from integer to s.th. else
15411548
if(dest_type.id()==ID_bool)
@@ -1558,19 +1565,20 @@ void verilog_typecheck_exprt::implicit_typecast(
15581565
return;
15591566
}
15601567
}
1561-
else if(expr.type().id()==ID_bool ||
1562-
expr.type().id()==ID_unsignedbv ||
1563-
expr.type().id()==ID_signedbv ||
1564-
expr.type().id()==ID_verilog_unsignedbv ||
1565-
expr.type().id()==ID_verilog_signedbv)
1568+
else if(src_type.id()==ID_bool ||
1569+
src_type.id()==ID_unsignedbv ||
1570+
src_type.id()==ID_signedbv ||
1571+
src_type.id()==ID_verilog_unsignedbv ||
1572+
src_type.id()==ID_verilog_signedbv)
15661573
{
1574+
// from bits to s.th. else
15671575
if(dest_type.id()==ID_bool)
15681576
{
15691577
// do not use typecast here
15701578
// we actually only want the lowest bit
15711579

15721580
if(expr.is_constant() &&
1573-
expr.type().id()==ID_unsignedbv)
1581+
src_type.id()==ID_unsignedbv)
15741582
{
15751583
const std::string &value=expr.get_string(ID_value);
15761584
// least significant bit is last
@@ -1614,10 +1622,29 @@ void verilog_typecheck_exprt::implicit_typecast(
16141622
expr = typecast_exprt{expr, dest_type};
16151623
return;
16161624
}
1625+
else if(dest_type.id() == ID_struct)
1626+
{
1627+
// bit-vectors can be converted to packed structs
1628+
expr = typecast_exprt{expr, dest_type};
1629+
return;
1630+
}
1631+
}
1632+
else if(src_type.id() == ID_struct)
1633+
{
1634+
// packed structs can be converted to bits
1635+
if(
1636+
dest_type.id() == ID_bool || dest_type.id() == ID_unsignedbv ||
1637+
dest_type.id() == ID_signedbv ||
1638+
dest_type.id() == ID_verilog_unsignedbv ||
1639+
dest_type.id() == ID_verilog_signedbv)
1640+
{
1641+
expr = typecast_exprt{expr, dest_type};
1642+
return;
1643+
}
16171644
}
16181645

16191646
throw errort().with_location(expr.source_location())
1620-
<< "failed to convert `" << to_string(expr.type()) << "' to `"
1647+
<< "failed to convert `" << to_string(src_type) << "' to `"
16211648
<< to_string(dest_type) << "'";
16221649
}
16231650

src/verilog/verilog_typecheck_type.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include "verilog_typecheck_expr.h"
1414

15+
#include "verilog_expr.h"
1516
#include "verilog_types.h"
1617

1718
/*******************************************************************\
@@ -180,6 +181,35 @@ typet verilog_typecheck_exprt::convert_type(const typet &src)
180181
// recursive call
181182
return convert_type(to_to_be_elaborated_type(src).subtype());
182183
}
184+
else if(src.id() == ID_struct || src.id() == ID_union)
185+
{
186+
// the declarations of the components
187+
auto &declaration_list = src.find(ID_declaration_list).get_sub();
188+
struct_union_typet::componentst components;
189+
190+
for(auto &declaration : declaration_list)
191+
{
192+
auto &declaration_expr = static_cast<const exprt &>(declaration);
193+
DATA_INVARIANT(
194+
declaration.id() == ID_decl, "struct type must have declarations");
195+
// Convert the type
196+
auto type = convert_type(declaration_expr.type());
197+
// Convert the declarators
198+
for(auto &declarator_expr : declaration_expr.operands())
199+
{
200+
auto &declarator = static_cast<const verilog_declaratort &>(declarator_expr);
201+
struct_union_typet::componentt component;
202+
component.add_source_location() = declarator.source_location();
203+
component.type() = type;
204+
component.set_base_name(declarator.base_name());
205+
component.set_name(declarator.base_name());
206+
components.push_back(std::move(component));
207+
}
208+
}
209+
210+
return struct_union_typet{src.id(), std::move(components)}
211+
.with_source_location(src.source_location());
212+
}
183213
else
184214
{
185215
throw errort().with_location(source_location)

0 commit comments

Comments
 (0)