-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Verilog: introduce the Verilog indexer
- Loading branch information
Showing
5 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
/*******************************************************************\ | ||
Module: Verilog Indexer | ||
Author: Daniel Kroening, dkr@amazon.com | ||
\*******************************************************************/ | ||
|
||
#include "verilog_indexer.h" | ||
|
||
#include <util/suffix.h> | ||
#include <util/unicode.h> | ||
|
||
#include "verilog_parser.h" | ||
#include "verilog_preprocessor.h" | ||
#include "verilog_y.tab.h" | ||
|
||
#include <algorithm> | ||
#include <fstream> | ||
#include <iosfwd> | ||
#include <iostream> | ||
#include <unordered_map> | ||
|
||
class verilog_indexert | ||
{ | ||
public: | ||
struct idt | ||
{ | ||
using kindt = enum { MODULE, PACKAGE, CLASS, TYPEDEF, INSTANCE }; | ||
kindt kind; | ||
irep_idt file_name; | ||
bool is_module() const | ||
{ | ||
return kind == MODULE; | ||
} | ||
}; | ||
|
||
// The keys are Verilog hierarchical identifiers | ||
// without Verilog:: prefix, as this is Verilog only. | ||
using id_mapt = std::unordered_map<irep_idt, idt>; | ||
id_mapt id_map; | ||
|
||
// a lookup helper | ||
std::optional<const idt &> operator[](const irep_idt &) const; | ||
|
||
/// index the given file | ||
void operator()(const irep_idt &file_name); | ||
|
||
protected: | ||
struct parsert | ||
{ | ||
// grammar rules | ||
void rDescription(); | ||
void rModule(); | ||
|
||
struct tokent | ||
{ | ||
int kind; | ||
std::string text; | ||
bool is_eof() const | ||
{ | ||
return kind == YYEOF; | ||
} | ||
bool is_identifier() const | ||
{ | ||
return kind == TOK_NON_TYPE_IDENTIFIER; | ||
} | ||
}; | ||
|
||
const tokent &next_token() | ||
{ | ||
peek(); | ||
peeked = false; | ||
return peeked_token; | ||
} | ||
|
||
const tokent &peek(); | ||
|
||
bool peeked = false; | ||
tokent peeked_token; | ||
}; | ||
|
||
std::string preprocess(const std::string &file_name); | ||
}; | ||
|
||
void verilog_indexert::operator()(const irep_idt &file_name) | ||
{ | ||
// run the preprocessor | ||
const auto preprocessed_string = preprocess(id2string(file_name)); | ||
std::istringstream preprocessed(preprocessed_string); | ||
|
||
// set up the tokenizer | ||
verilog_parser.in=&preprocessed; | ||
verilog_scanner_init(); | ||
|
||
// now parse | ||
parsert parser; | ||
parser.rDescription(); | ||
} | ||
|
||
std::string verilog_indexert::preprocess(const std::string &file_name) | ||
{ | ||
std::stringstream preprocessed; | ||
|
||
auto in_stream = std::ifstream(widen_if_needed(file_name)); | ||
|
||
if(!in_stream) | ||
{ | ||
// We deliberately fail silently. | ||
// Errors on invalid file names are expected to be raised | ||
// later. | ||
return std::string(); | ||
} | ||
|
||
null_message_handlert message_handler; | ||
verilog_preprocessort preprocessor( | ||
in_stream, preprocessed, message_handler, file_name); | ||
|
||
preprocessor.preprocessor(); | ||
|
||
return preprocessed.str(); | ||
} | ||
|
||
// scanner interface | ||
int yyveriloglex(); | ||
extern char *yyverilogtext; | ||
extern int yyverilogleng; | ||
|
||
const verilog_indexert::parsert::tokent &verilog_indexert::parsert::peek() | ||
{ | ||
if(!peeked) | ||
{ | ||
peeked_token.kind = yyveriloglex(); | ||
peeked_token.text = std::string(yyverilogtext, yyverilogleng); | ||
peeked = true; | ||
} | ||
|
||
return peeked_token; | ||
} | ||
|
||
void verilog_indexert::parsert::rDescription() | ||
{ | ||
if(next_token().kind != TOK_PARSE_LANGUAGE) | ||
DATA_INVARIANT(false, "expected TOK_PARSE_LANGUAGE"); | ||
|
||
while(true) | ||
{ | ||
auto &token = next_token(); | ||
if(token.is_eof()) | ||
break; | ||
if(token.text == "module") | ||
rModule(); | ||
} | ||
} | ||
|
||
void verilog_indexert::parsert::rModule() | ||
{ | ||
auto name = next_token(); | ||
if(name.is_identifier()) | ||
std::cout << "MODULE: " << name.text << '\n'; | ||
} | ||
|
||
std::vector<std::filesystem::path> verilog_files() | ||
{ | ||
std::vector<std::filesystem::path> result; | ||
|
||
for(auto &entry : std::filesystem::recursive_directory_iterator(".")) | ||
if(!is_directory(entry.path())) | ||
if(has_suffix(entry.path(), ".v") || has_suffix(entry.path(), ".sv")) | ||
result.push_back(entry.path()); | ||
|
||
return result; | ||
} | ||
|
||
int verilog_index() | ||
{ | ||
// First find all .v and .sv files | ||
auto files = verilog_files(); | ||
|
||
// Now index them. | ||
verilog_indexert indexer; | ||
|
||
for(const auto &file : files) | ||
{ | ||
indexer(std::string(file)); | ||
} | ||
|
||
// Show the modules. | ||
std::vector<irep_idt> modules; | ||
|
||
for(auto &id : indexer.id_map) | ||
if(id.second.is_module()) | ||
modules.push_back(id.first); | ||
|
||
std::sort( | ||
modules.begin(), | ||
modules.end(), | ||
[](const irep_idt &a, const irep_idt &b) { return a.compare(b) < 0; }); | ||
|
||
for(auto m : modules) | ||
std::cout << "MODULE: " << m << '\n'; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/*******************************************************************\ | ||
Module: Verilog Indexer | ||
Author: Daniel Kroening, dkr@amazon.com | ||
\*******************************************************************/ | ||
|
||
#ifndef VERILOG_INDEXER_H | ||
#define VERILOG_INDEXER_H | ||
|
||
/// Verilog allows modules, classes, packages, interfaces, | ||
/// tasks, functions, wires to be used before they are declared, | ||
/// which makes typing identifier tokens difficult. | ||
/// This maps identifiers to their kind and file, | ||
/// for the benefit of parsing/typechecking. | ||
|
||
int verilog_index(); | ||
|
||
#endif // VERILOG_INDEXER_H |