-
Notifications
You must be signed in to change notification settings - Fork 272
[WIP] Verible standalone preprocessor #1360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 12 commits
24a9b7c
42db6ab
ebd1e49
392c605
31d1bb6
a7c5f16
52856a4
325ae9b
6c82797
af28b7f
8c37dec
48abc7b
18e990c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| // Copyright 2017-2020 The Verible Authors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| #include "common/util/cmd_positional_arguments.h" | ||
|
|
||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include "absl/status/status.h" | ||
| #include "absl/strings/str_split.h" | ||
| #include "absl/strings/string_view.h" | ||
|
|
||
| namespace verible { | ||
|
|
||
| // Sets a file argument. | ||
| absl::Status CmdPositionalArguments::SetFile(absl::string_view file) { | ||
| files_.push_back(file); | ||
| return absl::OkStatus(); | ||
| } | ||
|
|
||
| // Sets a define arguments. | ||
| absl::Status CmdPositionalArguments::SetDefine( | ||
| std::pair<absl::string_view, absl::string_view> define) { | ||
| defines_.push_back(define); | ||
| return absl::OkStatus(); | ||
| } | ||
|
|
||
| // Sets a include directory argument. | ||
| absl::Status CmdPositionalArguments::SetIncludeDir( | ||
| absl::string_view include_dir) { | ||
| include_dirs_.push_back(include_dir); | ||
| return absl::OkStatus(); | ||
| } | ||
|
|
||
| // Gets include directories arguments. | ||
| std::vector<absl::string_view> CmdPositionalArguments::GetIncludeDirs() { | ||
| return include_dirs_; | ||
| } | ||
|
|
||
| std::vector<std::pair<absl::string_view, absl::string_view>> | ||
|
|
||
| // Gets macro defines arguments. | ||
| CmdPositionalArguments::GetDefines() { | ||
| return defines_; | ||
| } | ||
|
|
||
| // Gets SV files arguments. | ||
| std::vector<absl::string_view> CmdPositionalArguments::GetFiles() { | ||
| return files_; | ||
| } | ||
|
|
||
| // Main function that parses arguments and add them to the correct data memeber. | ||
| absl::Status CmdPositionalArguments::ParseArgs() { | ||
| // Positional arguments types: | ||
| // 1) <file> | ||
| // 2) +define+<foo>[=<value>] | ||
| // 3) +incdir+<dir> | ||
|
|
||
| int argument_index = 0; | ||
| for (absl::string_view argument : all_args_) { | ||
| if (!argument_index) { | ||
| argument_index++; | ||
| continue; | ||
| } // all_args_[0] is the tool's name, which can be skipped. | ||
| if (argument[0] != '+') { // the argument is a SV file name. | ||
| if (auto status = SetFile(argument); !status.ok()) | ||
| return status; // add it to the file arguments. | ||
| } else { // it should be either a define or incdir. | ||
| std::vector<absl::string_view> argument_plus_splitted = | ||
| absl::StrSplit(argument, absl::ByChar('+'), absl::SkipEmpty()); | ||
| if (argument_plus_splitted.size() < 2) { | ||
| // Unknown argument. | ||
| return absl::InvalidArgumentError("Unkown argument."); | ||
| } | ||
| absl::string_view plus_argument_type = argument_plus_splitted[0]; | ||
| if (absl::StrContains(plus_argument_type, "define")) { | ||
| // define argument. | ||
| int define_argument_index = 0; | ||
| for (absl::string_view define_argument : argument_plus_splitted) { | ||
| if (!define_argument_index) { | ||
| define_argument_index++; | ||
| continue; | ||
| } | ||
| // define_argument is something like <macro1>=<value>. | ||
| std::pair<absl::string_view, absl::string_view> macro_pair = | ||
| absl::StrSplit( | ||
| define_argument, absl::ByChar('='), | ||
| absl::SkipEmpty()); // parse the macro name and value. | ||
| if (auto status = CmdPositionalArguments::SetDefine(macro_pair); | ||
| !status.ok()) | ||
| return status; // add the define argument. | ||
| define_argument_index++; | ||
| } | ||
| } else if (absl::StrContains(plus_argument_type, "incdir")) { | ||
| // incdir argument. | ||
| int incdir_argument_index = 0; | ||
| for (absl::string_view incdir_argument : argument_plus_splitted) { | ||
| if (!incdir_argument_index) { | ||
| incdir_argument_index++; | ||
| continue; | ||
| } | ||
| if (auto status = | ||
| CmdPositionalArguments::SetIncludeDir(incdir_argument); | ||
| !status.ok()) | ||
| return status; // add file argument. | ||
| incdir_argument_index++; | ||
| } | ||
| } else { | ||
| return absl::InvalidArgumentError("Unkown argument."); | ||
| } | ||
| } | ||
| argument_index++; | ||
| } | ||
| return absl::OkStatus(); | ||
| } | ||
|
|
||
| } // namespace verible | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| // Copyright 2017-2020 The Verible Authors. | ||
karimtera marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| #ifndef VERIBLE_COMMON_UTIL_CMD_POSITIONAL_ARGUMENTS_H_ | ||
| #define VERIBLE_COMMON_UTIL_CMD_POSITIONAL_ARGUMENTS_H_ | ||
|
|
||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include "absl/status/status.h" | ||
| #include "absl/strings/string_view.h" | ||
|
|
||
| namespace verible { | ||
|
|
||
| class CmdPositionalArguments { | ||
| public: | ||
| explicit CmdPositionalArguments(const std::vector<char *> &args) | ||
| : all_args_(args){}; | ||
|
|
||
| // Main function that parses arguments. | ||
| absl::Status ParseArgs(); | ||
|
|
||
| // Gets include directories arguments. | ||
| std::vector<absl::string_view> GetIncludeDirs(); | ||
|
|
||
| // Gets macro defines arguments. | ||
| std::vector<std::pair<absl::string_view, absl::string_view>> GetDefines(); | ||
|
|
||
| // Gets SV files arguments. | ||
| std::vector<absl::string_view> GetFiles(); | ||
|
||
|
|
||
| private: | ||
| // Sets a include directory argument. | ||
| absl::Status SetIncludeDir(absl::string_view include_dir); | ||
|
|
||
| // Sets a define arguments. | ||
| absl::Status SetDefine( | ||
| std::pair<absl::string_view, absl::string_view> define); | ||
|
|
||
| // Sets a file argument. | ||
| absl::Status SetFile(absl::string_view file); | ||
|
|
||
| std::vector<char *> | ||
| all_args_; // contains all arguments (tool's name is included). | ||
| std::vector<absl::string_view> | ||
| include_dirs_; // contains all arugments that follows +incdir+<dir>. | ||
| std::vector<absl::string_view> | ||
| files_; // contains all SV files passed to the tool. | ||
| std::vector<std::pair<absl::string_view, absl::string_view>> | ||
| defines_; // contains all arguments that follow +define+<name>[=<value>] | ||
| // as a pair<name,value>. | ||
| }; // class CmdPositionalArguments | ||
|
|
||
| } // namespace verible | ||
|
|
||
| #endif // VERIBLE_COMMON_UTIL_CMD_POSITIONAL_ARGUMENTS_H_ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| // Copyright 2017-2020 The Verible Authors. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance wedge_from_iteratorh the | ||
| // License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in wredge_from_iteratoring, | ||
| // software distributed under the License is distributed on an "AS IS" BASIS, | ||
| // Wedge_from_iteratorHOUT WARRANTIES OR CONDedge_from_iteratorIONS OF ANY KIND, | ||
| // eedge_from_iteratorher express or implied. See the License for the specific | ||
| // language governing permissions and limedge_from_iteratorations under the | ||
| // License. | ||
|
|
||
| #include "verilog/analysis/flow_tree.h" | ||
|
|
||
| #include <map> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include "absl/status/status.h" | ||
| #include "absl/strings/str_cat.h" | ||
| #include "absl/strings/string_view.h" | ||
| #include "common/lexer/token_stream_adapter.h" | ||
| #include "verilog/parser/verilog_token_enum.h" | ||
|
|
||
| namespace verilog { | ||
|
|
||
| // Constructs the control flow tree, which determines the edge from each node | ||
| // (token index) to the next possible childs, And save edge_from_iterator in | ||
| // edges_. | ||
| absl::Status FlowTree::GenerateControlFlowTree() { | ||
| // Adding edges for if blocks. | ||
| int token_index = 0; | ||
| int current_token_enum = 0; | ||
| for (auto current_token : source_sequence_) { | ||
| current_token_enum = current_token.token_enum(); | ||
|
|
||
| if (current_token_enum == PP_ifdef || current_token_enum == PP_ifndef) { | ||
| ifs_.push_back(token_index); // add index of `ifdef and `ifndef to ifs_. | ||
| elses_[ifs_.back()].push_back( | ||
| token_index); // also add edge_from_iterator to elses_ as if will | ||
| // help marking edges later on. | ||
|
|
||
| } else if (current_token_enum == PP_else || | ||
| current_token_enum == PP_elsif || | ||
| current_token_enum == PP_endif) { | ||
| elses_[ifs_.back()].push_back( | ||
| token_index); // add index of `elsif, `else and `endif to else_ of | ||
| // the last recent if block. | ||
| if (current_token_enum == | ||
| PP_endif) { // if the current token is an `endif, then we are ready | ||
| // to create edges for this if block. | ||
| auto& current_if_block = | ||
| elses_[ifs_.back()]; // current_if_block contains all indexes of | ||
| // ifs and elses in the latest block. | ||
|
|
||
| // Adding edges for each index in the if block using a nested loop. | ||
| for (auto edge_from_iterator = current_if_block.begin(); | ||
| edge_from_iterator != current_if_block.end(); | ||
| edge_from_iterator++) { | ||
| for (auto edge_to_iterator = edge_from_iterator + 1; | ||
| edge_to_iterator != current_if_block.end(); edge_to_iterator++) { | ||
| if (edge_from_iterator == current_if_block.begin() && | ||
| edge_to_iterator == current_if_block.end() - 1 && | ||
| current_if_block.size() > 2) | ||
| continue; // skip edges from `if to `endif if there is an else in | ||
| // this bloc wheneven there is an else in this block. | ||
| edges_[*edge_from_iterator].push_back( | ||
| *edge_to_iterator + | ||
| (edge_to_iterator != | ||
| current_if_block.end() - 1)); // add the possible edge. | ||
| } | ||
| } | ||
| ifs_.pop_back(); // the if block edges were added, ready to pop it. | ||
| } | ||
| } | ||
| token_index++; // increment the token index. | ||
| } | ||
|
|
||
| // Adding edges for non-if blocks. | ||
| token_index = 0; | ||
| for (auto current_token : source_sequence_) { | ||
| current_token_enum = current_token.token_enum(); | ||
| if (current_token_enum != PP_else && current_token_enum != PP_elsif) { | ||
| if (token_index > 0) | ||
| edges_[token_index - 1].push_back( | ||
| token_index); // edges from a token to the one coming after it | ||
| // directly. | ||
| } else { | ||
| if (token_index > 0) | ||
| edges_[token_index - 1].push_back( | ||
| edges_[token_index] | ||
| .back()); // edges from the last token in `ifdef/`ifndef body | ||
| // to `endif from the same if block. | ||
| } | ||
| token_index++; // increment the token index. | ||
| } | ||
|
|
||
| return absl::OkStatus(); | ||
| } | ||
|
|
||
| // Traveses the control flow tree in a depth first manner, appending the visited | ||
| // tokens to current_sequence_, then adding current_sequence_ to variants_ upon | ||
| // completing. | ||
| absl::Status FlowTree::DepthFirstSearch(int current_node_index) { | ||
| // skips preprocessor directives so that current_sequence_ doesn't contain | ||
| // any. | ||
| const auto& current_token = source_sequence_[current_node_index]; | ||
| if (current_token.token_enum() != PP_Identifier && | ||
| current_token.token_enum() != PP_ifndef && | ||
| current_token.token_enum() != PP_ifdef && | ||
| current_token.token_enum() != PP_define && | ||
| current_token.token_enum() != PP_define_body && | ||
| current_token.token_enum() != PP_elsif && | ||
| current_token.token_enum() != PP_else && | ||
| current_token.token_enum() != PP_endif) | ||
| current_sequence_.push_back(current_token); | ||
|
|
||
| // do recursive search through every possible edge. | ||
| for (auto next_node : edges_[current_node_index]) { | ||
| if (auto status = FlowTree::DepthFirstSearch(next_node); !status.ok()) { | ||
| std::cerr << "ERROR: DepthFirstSearch fails\n"; | ||
| return status; | ||
| } | ||
| } | ||
| if (current_node_index == | ||
| int(source_sequence_.size()) - | ||
| 1) { // if the current node is the last one, push the completed | ||
| // current_sequence_ to variants_. | ||
| variants_.push_back(current_sequence_); | ||
| } | ||
| if (current_token.token_enum() != PP_Identifier && | ||
| current_token.token_enum() != PP_ifndef && | ||
| current_token.token_enum() != PP_ifdef && | ||
| current_token.token_enum() != PP_define && | ||
| current_token.token_enum() != PP_define_body && | ||
| current_token.token_enum() != PP_elsif && | ||
| current_token.token_enum() != PP_else && | ||
| current_token.token_enum() != PP_endif) | ||
| current_sequence_ | ||
| .pop_back(); // remove tokens to back track into other variants. | ||
| return absl::OkStatus(); | ||
| } | ||
|
|
||
| } // namespace verilog |
Uh oh!
There was an error while loading. Please reload this page.