Skip to content

Commit d25aa62

Browse files
committed
Verilog: introduce the Verilog indexer
1 parent f77b914 commit d25aa62

File tree

5 files changed

+231
-0
lines changed

5 files changed

+231
-0
lines changed

src/ebmc/ebmc_parse_options.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Author: Daniel Kroening, [email protected]
1313
#include <util/help_formatter.h>
1414
#include <util/string2int.h>
1515

16+
#include <verilog/verilog_indexer.h>
17+
1618
#include "bdd_engine.h"
1719
#include "diatest.h"
1820
#include "ebmc_base.h"
@@ -232,6 +234,9 @@ int ebmc_parse_optionst::doit()
232234
if(cmdline.isset("verilog-netlist"))
233235
return show_trans_verilog_netlist(cmdline, ui_message_handler);
234236

237+
if(cmdline.isset("verilog-index"))
238+
return verilog_index();
239+
235240
// get the transition system
236241
auto transition_system = get_transition_system(cmdline, ui_message_handler);
237242

src/ebmc/ebmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class ebmc_parse_optionst:public parse_options_baset
3636
"(neural-liveness)(neural-engine):"
3737
"(reset):"
3838
"(version)(verilog-rtl)(verilog-netlist)"
39+
"(verilog-index)"
3940
"(compute-interpolant)(interpolation)(interpolation-vmcai)"
4041
"(ic3)(property):(constr)(h)(new-mode)(aiger)"
4142
"(interpolation-word)(interpolator):(bdd)"

src/verilog/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ SRC = expr2verilog.cpp \
33
verilog_elaborate.cpp \
44
verilog_expr.cpp \
55
verilog_generate.cpp \
6+
verilog_indexer.cpp \
67
verilog_interfaces.cpp \
78
verilog_interpreter.cpp \
89
verilog_language.cpp \

src/verilog/verilog_indexer.cpp

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*******************************************************************\
2+
3+
Module: Verilog Indexer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "verilog_indexer.h"
10+
11+
#include <util/suffix.h>
12+
#include <util/unicode.h>
13+
14+
#include "verilog_parser.h"
15+
#include "verilog_preprocessor.h"
16+
#include "verilog_y.tab.h"
17+
18+
#include <algorithm>
19+
#include <fstream>
20+
#include <iosfwd>
21+
#include <iostream>
22+
#include <unordered_map>
23+
24+
class verilog_indexert
25+
{
26+
public:
27+
struct idt
28+
{
29+
using kindt = enum { MODULE, PACKAGE, CLASS, TYPEDEF, INSTANCE };
30+
kindt kind;
31+
irep_idt file_name;
32+
bool is_module() const
33+
{
34+
return kind == MODULE;
35+
}
36+
};
37+
38+
// The keys are Verilog hierarchical identifiers
39+
// without Verilog:: prefix, as this is Verilog only.
40+
using id_mapt = std::unordered_map<irep_idt, idt>;
41+
id_mapt id_map;
42+
43+
// a lookup helper
44+
std::optional<const idt &> operator[](const irep_idt &) const;
45+
46+
/// index the given file
47+
void operator()(const irep_idt &file_name);
48+
49+
protected:
50+
struct parsert
51+
{
52+
// grammar rules
53+
void rDescription();
54+
void rModule();
55+
56+
struct tokent
57+
{
58+
int kind;
59+
std::string text;
60+
bool is_eof() const
61+
{
62+
return kind == YYEOF;
63+
}
64+
bool is_identifier() const
65+
{
66+
return kind == TOK_NON_TYPE_IDENTIFIER;
67+
}
68+
};
69+
70+
const tokent &next_token()
71+
{
72+
peek();
73+
peeked = false;
74+
return peeked_token;
75+
}
76+
77+
const tokent &peek();
78+
79+
bool peeked = false;
80+
tokent peeked_token;
81+
};
82+
83+
std::string preprocess(const std::string &file_name);
84+
};
85+
86+
void verilog_indexert::operator()(const irep_idt &file_name)
87+
{
88+
// run the preprocessor
89+
const auto preprocessed_string = preprocess(id2string(file_name));
90+
std::istringstream preprocessed(preprocessed_string);
91+
92+
// set up the tokenizer
93+
verilog_parser.in=&preprocessed;
94+
verilog_scanner_init();
95+
96+
// now parse
97+
parsert parser;
98+
parser.rDescription();
99+
}
100+
101+
std::string verilog_indexert::preprocess(const std::string &file_name)
102+
{
103+
std::stringstream preprocessed;
104+
105+
auto in_stream = std::ifstream(widen_if_needed(file_name));
106+
107+
if(!in_stream)
108+
{
109+
// We deliberately fail silently.
110+
// Errors on invalid file names are expected to be raised
111+
// later.
112+
return std::string();
113+
}
114+
115+
null_message_handlert message_handler;
116+
verilog_preprocessort preprocessor(
117+
in_stream, preprocessed, message_handler, file_name);
118+
119+
preprocessor.preprocessor();
120+
121+
return preprocessed.str();
122+
}
123+
124+
// scanner interface
125+
int yyveriloglex();
126+
extern char *yyverilogtext;
127+
extern int yyverilogleng;
128+
129+
const verilog_indexert::parsert::tokent &verilog_indexert::parsert::peek()
130+
{
131+
if(!peeked)
132+
{
133+
peeked_token.kind = yyveriloglex();
134+
peeked_token.text = std::string(yyverilogtext, yyverilogleng);
135+
peeked = true;
136+
}
137+
138+
return peeked_token;
139+
}
140+
141+
void verilog_indexert::parsert::rDescription()
142+
{
143+
if(next_token().kind != TOK_PARSE_LANGUAGE)
144+
DATA_INVARIANT(false, "expected TOK_PARSE_LANGUAGE");
145+
146+
while(true)
147+
{
148+
auto &token = next_token();
149+
if(token.is_eof())
150+
break;
151+
if(token.text == "module")
152+
rModule();
153+
}
154+
}
155+
156+
void verilog_indexert::parsert::rModule()
157+
{
158+
auto name = next_token();
159+
if(name.is_identifier())
160+
std::cout << "MODULE: " << name.text << '\n';
161+
}
162+
163+
std::vector<std::filesystem::path> verilog_files()
164+
{
165+
std::vector<std::filesystem::path> result;
166+
167+
for(auto &entry : std::filesystem::recursive_directory_iterator("."))
168+
if(!is_directory(entry.path()))
169+
if(has_suffix(entry.path(), ".v") || has_suffix(entry.path(), ".sv"))
170+
result.push_back(entry.path());
171+
172+
return result;
173+
}
174+
175+
int verilog_index()
176+
{
177+
// First find all .v and .sv files
178+
auto files = verilog_files();
179+
180+
// Now index them.
181+
verilog_indexert indexer;
182+
183+
for(const auto &file : files)
184+
{
185+
indexer(std::string(file));
186+
}
187+
188+
// Show the modules.
189+
std::vector<irep_idt> modules;
190+
191+
for(auto &id : indexer.id_map)
192+
if(id.second.is_module())
193+
modules.push_back(id.first);
194+
195+
std::sort(
196+
modules.begin(),
197+
modules.end(),
198+
[](const irep_idt &a, const irep_idt &b) { return a.compare(b) < 0; });
199+
200+
for(auto m : modules)
201+
std::cout << "MODULE: " << m << '\n';
202+
203+
return 0;
204+
}

src/verilog/verilog_indexer.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*******************************************************************\
2+
3+
Module: Verilog Indexer
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef VERILOG_INDEXER_H
10+
#define VERILOG_INDEXER_H
11+
12+
/// Verilog allows modules, classes, packages, interfaces,
13+
/// tasks, functions, wires to be used before they are declared,
14+
/// which makes typing identifier tokens difficult.
15+
/// This maps identifiers to their kind and file,
16+
/// for the benefit of parsing/typechecking.
17+
18+
int verilog_index();
19+
20+
#endif // VERILOG_INDEXER_H

0 commit comments

Comments
 (0)