Skip to content

Commit 591ddea

Browse files
authored
Merge pull request #1275 from diffblue/module-type-ports
Verilog: strengthen typing when using module type
2 parents 18f0827 + 1d097f0 commit 591ddea

File tree

6 files changed

+143
-58
lines changed

6 files changed

+143
-58
lines changed

src/verilog/verilog_interfaces.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ Function: verilog_typecheckt::check_module_ports
5050
void verilog_typecheckt::check_module_ports(
5151
const verilog_module_sourcet::port_listt &module_ports)
5252
{
53-
auto &ports = module_symbol.type.add(ID_ports).get_sub();
54-
ports.resize(module_ports.size());
53+
auto &ports = to_module_type(module_symbol.type).ports();
54+
ports.clear();
55+
ports.reserve(module_ports.size());
5556
std::map<irep_idt, unsigned> port_names;
5657

5758
unsigned nr=0;
@@ -97,19 +98,22 @@ void verilog_typecheckt::check_module_ports(
9798
<< "port `" << base_name << "' not declared as input or output";
9899
}
99100

100-
ports[nr].set("#name", base_name);
101-
ports[nr].id(ID_symbol);
102-
ports[nr].set(ID_identifier, identifier);
103-
ports[nr].set(ID_C_source_location, declarator.source_location());
104-
ports[nr].set(ID_type, port_symbol->type);
105-
ports[nr].set(ID_input, port_symbol->is_input);
106-
ports[nr].set(ID_output, port_symbol->is_output);
101+
ports.emplace_back(
102+
identifier,
103+
port_symbol->type,
104+
port_symbol->is_input,
105+
port_symbol->is_output);
106+
107+
ports.back().set("#name", base_name);
108+
ports.back().set(ID_C_source_location, declarator.source_location());
107109

108110
port_names[base_name] = nr;
109111

110112
nr++;
111113
}
112114

115+
DATA_INVARIANT(ports.size() == module_ports.size(), "number of ports");
116+
113117
// check that all declared ports are also in the port list
114118

115119
for(auto it=symbol_table.symbol_module_map.lower_bound(module_identifier);

src/verilog/verilog_synthesis.cpp

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,14 +1349,13 @@ Function: verilog_synthesist::instantiate_port
13491349
\*******************************************************************/
13501350

13511351
void verilog_synthesist::instantiate_port(
1352-
bool is_output,
1353-
const symbol_exprt &port,
1352+
const module_typet::portt &port,
13541353
const exprt &value,
13551354
const replace_mapt &replace_map,
13561355
const source_locationt &source_location,
13571356
transt &trans)
13581357
{
1359-
irep_idt port_identifier = port.get_identifier();
1358+
irep_idt port_identifier = port.identifier();
13601359

13611360
replace_mapt::const_iterator it = replace_map.find(port_identifier);
13621361

@@ -1372,7 +1371,7 @@ void verilog_synthesist::instantiate_port(
13721371
// Note that the types need not match.
13731372
exprt lhs, rhs;
13741373

1375-
if(is_output)
1374+
if(port.output())
13761375
{
13771376
lhs = value;
13781377
rhs = typecast_exprt::conditional_cast(it->second, value.type());
@@ -1417,31 +1416,29 @@ void verilog_synthesist::instantiate_ports(
14171416
if(inst.connections().empty())
14181417
return;
14191418

1419+
auto &module_type = to_module_type(symbol.type);
1420+
14201421
// named port connection?
14211422

14221423
if(inst.named_port_connections())
14231424
{
1424-
const irept::subt &ports = symbol.type.find(ID_ports).get_sub();
1425-
1426-
std::set<irep_idt> output_identifiers;
1427-
for(auto &port : ports)
1428-
if(port.get_bool(ID_output))
1429-
output_identifiers.insert(
1430-
to_symbol_expr((const exprt &)(port)).get_identifier());
1425+
const auto &ports = module_type.ports();
1426+
auto port_map = module_type.port_map();
14311427

14321428
// no requirement that all ports are connected
14331429
for(const auto &connection : inst.connections())
14341430
{
14351431
auto &named_connection = to_verilog_named_port_connection(connection);
1436-
const auto &port = to_symbol_expr(named_connection.port());
1432+
auto port_it =
1433+
port_map.find(to_symbol_expr(named_connection.port()).get_identifier());
1434+
CHECK_RETURN(port_it != port_map.end());
1435+
auto &port = port_it->second;
14371436
const exprt &value = named_connection.value();
14381437

14391438
if(value.is_not_nil())
14401439
{
1441-
bool is_output = output_identifiers.find(port.get_identifier()) !=
1442-
output_identifiers.end();
14431440
instantiate_port(
1444-
is_output, port, value, replace_map, inst.source_location(), trans);
1441+
port, value, replace_map, inst.source_location(), trans);
14451442
}
14461443
}
14471444

@@ -1456,17 +1453,15 @@ void verilog_synthesist::instantiate_ports(
14561453

14571454
// unconnected inputs may be given a default value
14581455
for(auto &port : ports)
1459-
if(port.get_bool(ID_input))
1456+
if(port.input())
14601457
{
1461-
auto &port_symbol_expr = to_symbol_expr((const exprt &)(port));
1462-
auto identifier = port_symbol_expr.get_identifier();
1458+
auto identifier = port.identifier();
14631459
if(connected_ports.find(identifier) == connected_ports.end())
14641460
{
1465-
auto &port_symbol = ns.lookup(port_symbol_expr);
1461+
auto &port_symbol = ns.lookup(identifier);
14661462
if(port_symbol.value.is_not_nil())
14671463
instantiate_port(
1468-
false,
1469-
port_symbol_expr,
1464+
port,
14701465
port_symbol.value,
14711466
replace_map,
14721467
inst.source_location(),
@@ -1476,7 +1471,7 @@ void verilog_synthesist::instantiate_ports(
14761471
}
14771472
else // just a list without names
14781473
{
1479-
const irept::subt &ports = symbol.type.find(ID_ports).get_sub();
1474+
const auto &ports = module_type.ports();
14801475

14811476
if(inst.connections().size() != ports.size())
14821477
{
@@ -1485,24 +1480,15 @@ void verilog_synthesist::instantiate_ports(
14851480
<< inst.connections().size();
14861481
}
14871482

1488-
irept::subt::const_iterator p_it=
1489-
ports.begin();
1483+
auto p_it = ports.begin();
14901484

14911485
for(const auto &connection : inst.connections())
14921486
{
14931487
DATA_INVARIANT(connection.is_not_nil(), "all ports must be connected");
14941488

1495-
auto &port = to_symbol_expr((const exprt &)(*p_it));
1496-
1497-
bool is_output = port.get_bool(ID_output);
1498-
14991489
instantiate_port(
1500-
is_output,
1501-
port,
1502-
connection,
1503-
replace_map,
1504-
inst.source_location(),
1505-
trans);
1490+
*p_it, connection, replace_map, inst.source_location(), trans);
1491+
15061492
p_it++;
15071493
}
15081494
}

src/verilog/verilog_synthesis_class.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,7 @@ class verilog_synthesist:
326326
void replace_symbols(const irep_idt &target, exprt &dest);
327327

328328
void instantiate_port(
329-
bool is_output,
330-
const symbol_exprt &port,
329+
const module_typet::portt &,
331330
const exprt &value,
332331
const replace_mapt &,
333332
const source_locationt &,

src/verilog/verilog_typecheck.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@ Function: verilog_typecheckt::typecheck_port_connection
3939

4040
void verilog_typecheckt::typecheck_port_connection(
4141
exprt &op,
42-
const exprt &port)
42+
const module_typet::portt &port)
4343
{
44-
const symbolt &symbol=
45-
ns.lookup(port.get(ID_identifier));
44+
const symbolt &symbol = ns.lookup(port.identifier());
4645

4746
if(!symbol.is_input && !symbol.is_output)
4847
{
@@ -101,7 +100,7 @@ void verilog_typecheckt::typecheck_port_connections(
101100
else
102101
range = convert_range(range_expr);
103102

104-
const irept::subt &ports=symbol.type.find(ID_ports).get_sub();
103+
const auto &ports = to_module_type(symbol.type).ports();
105104

106105
// no connection is one connection that is nil
107106
if(inst.connections().size() == 1 && inst.connections().front().is_nil())
@@ -148,10 +147,9 @@ void verilog_typecheckt::typecheck_port_connections(
148147
{
149148
if(port.get(ID_identifier) == identifier)
150149
{
151-
auto &p_expr = static_cast<const exprt &>(port);
152150
found=true;
153-
typecheck_port_connection(value, p_expr);
154-
named_port_connection.port().type() = p_expr.type();
151+
typecheck_port_connection(value, port);
152+
named_port_connection.port().type() = port.type();
155153
break;
156154
}
157155
}
@@ -174,12 +172,11 @@ void verilog_typecheckt::typecheck_port_connections(
174172
<< " but got " << inst.connections().size();
175173
}
176174

177-
irept::subt::const_iterator p_it=
178-
ports.begin();
175+
auto p_it = ports.begin();
179176

180177
for(auto &connection : inst.connections())
181178
{
182-
typecheck_port_connection(connection, (exprt &)*p_it);
179+
typecheck_port_connection(connection, *p_it);
183180
p_it++;
184181
}
185182
}

src/verilog/verilog_typecheck.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,7 @@ class verilog_typecheckt:
202202

203203
void typecheck_builtin_port_connections(verilog_inst_baset::instancet &);
204204

205-
void typecheck_port_connection(
206-
exprt &op,
207-
const exprt &port);
205+
void typecheck_port_connection(exprt &op, const module_typet::portt &);
208206

209207
bool replace_symbols(const replace_mapt &what, exprt &dest);
210208
void replace_symbols(const std::string &target, exprt &dest);

src/verilog/verilog_types.h

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,109 @@ class module_typet:public typet
141141
inline module_typet():typet(ID_module)
142142
{
143143
}
144+
145+
class portt : public irept
146+
{
147+
public:
148+
portt(irep_idt _identifier, typet _type, bool _input, bool _output)
149+
: irept(ID_symbol)
150+
{
151+
type() = std::move(_type);
152+
identifier(_identifier);
153+
input(_input);
154+
output(_output);
155+
}
156+
157+
typet &type()
158+
{
159+
return static_cast<typet &>(add(ID_type));
160+
}
161+
162+
const typet &type() const
163+
{
164+
return static_cast<const typet &>(find(ID_type));
165+
}
166+
167+
irep_idt identifier() const
168+
{
169+
return get(ID_identifier);
170+
}
171+
172+
void identifier(irep_idt _identifier)
173+
{
174+
set(ID_identifier, _identifier);
175+
}
176+
177+
bool output() const
178+
{
179+
return get_bool(ID_output);
180+
}
181+
182+
void output(bool _output)
183+
{
184+
set(ID_output, _output);
185+
}
186+
187+
bool input() const
188+
{
189+
return get_bool(ID_input);
190+
}
191+
192+
void input(bool _input)
193+
{
194+
set(ID_input, _input);
195+
}
196+
};
197+
198+
using portst = std::vector<portt>;
199+
200+
portst &ports()
201+
{
202+
return (portst &)(add(ID_ports).get_sub());
203+
}
204+
205+
const portst &ports() const
206+
{
207+
return (const portst &)(find(ID_ports).get_sub());
208+
}
209+
210+
using port_mapt = std::unordered_map<irep_idt, portt, irep_id_hash>;
211+
212+
port_mapt port_map() const
213+
{
214+
port_mapt result;
215+
auto &ports = this->ports();
216+
for(auto &port : ports)
217+
result.emplace(port.identifier(), port);
218+
return result;
219+
}
144220
};
145221

222+
/*! \brief Cast a generic typet to a \ref module_typet
223+
*
224+
* This is an unchecked conversion. \a type must be known to be \ref
225+
* module_typet.
226+
*
227+
* \param type Source type
228+
* \return Object of type \ref module_typet
229+
*
230+
* \ingroup gr_std_types
231+
*/
232+
inline const module_typet &to_module_type(const typet &type)
233+
{
234+
PRECONDITION(type.id() == ID_module);
235+
return static_cast<const module_typet &>(type);
236+
}
237+
238+
/*! \copydoc to_module_type(const typet &)
239+
* \ingroup gr_std_types
240+
*/
241+
inline module_typet &to_module_type(typet &type)
242+
{
243+
PRECONDITION(type.id() == ID_module);
244+
return static_cast<module_typet &>(type);
245+
}
246+
146247
class verilog_genvar_typet : public typet
147248
{
148249
public:

0 commit comments

Comments
 (0)