Skip to content

Commit 06c409a

Browse files
committed
Verilog: multiple top-level modules
This extends the Verilog language to support multiple top-level modules, following SystemVerilog 1800-2017 23.3.1.
1 parent 06b5375 commit 06c409a

2 files changed

Lines changed: 79 additions & 45 deletions

File tree

src/verilog/verilog_ebmc_language.cpp

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ void verilog_ebmc_languaget::typecheck_module(
180180

181181
transition_systemt verilog_ebmc_languaget::typecheck(
182182
const parse_treest &parse_trees,
183-
irep_idt top_level_module,
183+
const std::vector<irep_idt> top_level_modules,
184184
symbol_tablet &&symbol_table)
185185
{
186186
std::map<irep_idt, modulet> module_map;
@@ -198,13 +198,17 @@ transition_systemt verilog_ebmc_languaget::typecheck(
198198
}
199199
}
200200

201-
// now type check the top-level module
202-
auto m_it = module_map.find(verilog_module_symbol(top_level_module));
203-
CHECK_RETURN(m_it != module_map.end());
204-
201+
// now type check the given top-level modules
205202
transition_systemt transition_system;
206203
transition_system.symbol_table = std::move(symbol_table);
207-
typecheck_module(m_it->second, transition_system.symbol_table);
204+
205+
for(auto top_level_module : top_level_modules)
206+
{
207+
auto m_it = module_map.find(verilog_module_symbol(top_level_module));
208+
CHECK_RETURN(m_it != module_map.end());
209+
210+
typecheck_module(m_it->second, transition_system.symbol_table);
211+
}
208212

209213
return transition_system;
210214
}
@@ -244,8 +248,10 @@ static void module_dependencies(
244248
module_dependencies_rec(item, action);
245249
}
246250

247-
irep_idt
248-
verilog_ebmc_languaget::top_level_module(const parse_treest &parse_trees) const
251+
/// Determine the set of top-level modules following 1800 2017 23.3.1,
252+
/// given via their base names. Sorted alphabetically.
253+
std::vector<irep_idt>
254+
verilog_ebmc_languaget::top_level_modules(const parse_treest &parse_trees) const
249255
{
250256
// start with a set of all modules, from all the files
251257
std::set<irep_idt> all_modules;
@@ -260,29 +266,47 @@ verilog_ebmc_languaget::top_level_module(const parse_treest &parse_trees) const
260266
}
261267
}
262268

263-
// Did the user specify one?
264-
irep_idt given_module;
269+
// Did the user specify a set of top level modules?
270+
std::vector<irep_idt> given_modules;
265271

266272
if(cmdline.isset("module"))
267-
given_module = cmdline.get_value("module");
273+
{
274+
for(auto &value : cmdline.get_values("module"))
275+
given_modules.push_back(value);
276+
}
268277
else if(cmdline.isset("top"))
269-
given_module = cmdline.get_value("top");
278+
{
279+
for(auto &value : cmdline.get_values("top"))
280+
given_modules.push_back(value);
281+
}
270282

271-
if(given_module != irep_idt{})
283+
if(!given_modules.empty())
272284
{
273-
if(all_modules.find(given_module) == all_modules.end())
285+
// first check that all the given modules exist
286+
for(const auto &given_module : given_modules)
274287
{
275-
messaget log{message_handler};
276-
log.error() << "module '" << given_module << "' not found"
277-
<< messaget::eom;
278-
throw ebmc_errort{}.with_exit_code(2);
288+
if(all_modules.find(given_module) == all_modules.end())
289+
{
290+
messaget log{message_handler};
291+
log.error() << "module '" << given_module << "' not found"
292+
<< messaget::eom;
293+
throw ebmc_errort{}.with_exit_code(2);
294+
}
279295
}
280-
else
281-
return given_module; // done
296+
297+
// now sort alphabetically
298+
std::sort(
299+
given_modules.begin(),
300+
given_modules.end(),
301+
[](const irep_idt &a, const irep_idt &b)
302+
{ return id2string(a) < id2string(b); });
303+
304+
return given_modules; // done
282305
}
283306

284-
// start with all modules, and then erase the ones that are
285-
// used as a dependency
307+
// No modules given. Find all modules that are not used
308+
// as a submodule. Start with all modules, and then erase
309+
// the ones that are used as a submodule.
286310
std::set<irep_idt> top_level_modules = all_modules;
287311

288312
for(auto &parse_tree : parse_trees)
@@ -304,33 +328,41 @@ verilog_ebmc_languaget::top_level_module(const parse_treest &parse_trees) const
304328
log.error() << "no module found" << messaget::eom;
305329
throw ebmc_errort{}.with_exit_code(1);
306330
}
307-
else if(top_level_modules.size() >= 2)
308-
{
309-
// sorted alphabetically
310-
std::set<std::string> modules;
311331

312-
for(const auto &base_name : top_level_modules)
313-
modules.insert(id2string(base_name));
332+
// sort alphabetically into a vector
333+
std::vector<irep_idt> result;
314334

335+
for(auto &module : top_level_modules)
336+
result.push_back(module);
337+
338+
std::sort(
339+
result.begin(),
340+
result.end(),
341+
[](const irep_idt &a, const irep_idt &b)
342+
{ return id2string(a) < id2string(b); });
343+
344+
return result; // done
345+
}
346+
347+
static bool get_main(
348+
const std::vector<irep_idt> top_level_modules,
349+
message_handlert &message_handler,
350+
transition_systemt &transition_system)
351+
{
352+
if(top_level_modules.size() >= 2)
353+
{
315354
messaget log{message_handler};
316355
log.error() << "multiple modules found, please select one:\n";
317356

318-
for(const auto &module : modules)
357+
for(const auto &module : top_level_modules)
319358
log.error() << " " << module << '\n';
320359

321360
log.error() << messaget::eom;
322361
throw ebmc_errort{}.with_exit_code(1);
323362
}
324363

325-
// we have exactly one top-level module
326-
return *top_level_modules.begin();
327-
}
364+
auto top_level_module = top_level_modules.front();
328365

329-
static bool get_main(
330-
irep_idt top_level_module,
331-
message_handlert &message_handler,
332-
transition_systemt &transition_system)
333-
{
334366
try
335367
{
336368
auto identifier = verilog_module_symbol(top_level_module);
@@ -448,9 +480,9 @@ std::optional<transition_systemt> verilog_ebmc_languaget::transition_system()
448480
symbol_tablet symbol_table = elaborate_compilation_units(parse_trees);
449481

450482
//
451-
// determine the top-level module
483+
// determine the top-level modules
452484
//
453-
auto top_level_module = this->top_level_module(parse_trees);
485+
auto top_level_modules = this->top_level_modules(parse_trees);
454486

455487
//
456488
// type checking
@@ -459,15 +491,15 @@ std::optional<transition_systemt> verilog_ebmc_languaget::transition_system()
459491
message.status() << "Converting" << messaget::eom;
460492

461493
auto transition_system =
462-
typecheck(parse_trees, top_level_module, std::move(symbol_table));
494+
typecheck(parse_trees, top_level_modules, std::move(symbol_table));
463495

464496
if(cmdline.isset("show-symbol-table"))
465497
{
466498
std::cout << transition_system.symbol_table;
467499
return {};
468500
}
469501

470-
if(get_main(top_level_module, message_handler, transition_system))
502+
if(get_main(top_level_modules, message_handler, transition_system))
471503
throw ebmc_errort{}.with_exit_code(1);
472504

473505
if(cmdline.isset("show-module-hierarchy"))

src/verilog/verilog_ebmc_language.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ class verilog_ebmc_languaget : public ebmc_languaget
5151

5252
void copy_parse_tree(const parse_treet &, symbol_tablet &);
5353

54-
// base_name of the top-level module
55-
irep_idt top_level_module(const parse_treest &) const;
54+
// base_names of the top-level modules, alphabetical order
55+
std::vector<irep_idt> top_level_modules(const parse_treest &) const;
5656

5757
class modulet
5858
{
@@ -66,8 +66,10 @@ class verilog_ebmc_languaget : public ebmc_languaget
6666
};
6767

6868
symbol_tablet elaborate_compilation_units(const parse_treest &);
69-
transition_systemt
70-
typecheck(const parse_treest &, irep_idt top_level_module, symbol_tablet &&);
69+
transition_systemt typecheck(
70+
const parse_treest &,
71+
const std::vector<irep_idt> top_level_modules,
72+
symbol_tablet &&);
7173
void typecheck_module(modulet &, symbol_tablet &);
7274
};
7375

0 commit comments

Comments
 (0)