Skip to content
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

Refactor Verilog pass to use verilogAST #770

Merged
merged 42 commits into from
Jul 31, 2019
Merged

Refactor Verilog pass to use verilogAST #770

merged 42 commits into from
Jul 31, 2019

Conversation

leonardt
Copy link
Collaborator

Finally ready for review, I'd mainly first like to get comments on code design/quality (e.g. refactor repeated things, encapsulate that into an object, etc..). This code passes the CoreIR test suite, but I'm a little worried about code paths that haven't been captured by our tests (e.g. the garnet/lassen flow). We should make sure those work before merging this into master. We could also merge this into dev, but as of creating this PR, it seems that dev is behind master so when I target dev, the diff includes commits that aren't a part of this PR, so I'll leave it as master now.

There are some limitations, but I think it's important to get this merged ASAP so we avoid future integration pains. Inlining doesn't work yet, but my goal is to have the functionality provided as generic AST passes by verilogAST, so that work will mostly be done in a separate code path (the backend will just need to invoke those passes). Thus, I've disabled the inlining tests for now (I don't think they were working on travis anyways) since this feature shouldn't block users and I'd rather not block this PR for that.

Another limitation is that this backend doesn't support inout connections in module definitions. It doesn't seem like any tests in the coreir suite cover this use case, so perhaps this is not a blocking feature, but we should make sure that is true for our upstream users (garnet/lassen). It's not hard to add this support, but again, I just wanted to get this merged in ASAP to avoid integration pains (rather than waiting until every single edge case was covered).

@leonardt
Copy link
Collaborator Author

There's also more opportunities to improve the output verilog (e.g. wire up outputs of the module to instance ports when they can be bulk connected). We can do this in the verilog code generation logic, but we can also do this as passes on the AST (e.g. remove intermediate wires). I think it will be more robust and extensible to do this as AST passes, so I'd vote to "freeze" the verilog code generator as is in terms of output code quality (we can/should still fix bugs in the functionality of the produced code), and move logic to improve the code quality to be part of the verilogAST library (I'm thinking first passes will be module inlining for primitives and wire collapsing logic to remove intermediate/unnecessary wires).

@leonardt leonardt changed the title Refactor Verilog pass to use verilogAST but I th Refactor Verilog pass to use verilogAST Jul 22, 2019
@leonardt
Copy link
Collaborator Author

Also, this updates the requirements to gcc-7 which is for verilogAST. To do this, I also had to update the catch.hpp unit test framework. This didn't seem to cause any issues with the existing code/tests, but may have an impact on users.

@rdaly525
Copy link
Owner

rdaly525 commented Jul 22, 2019

Reviewing now.

In general I am not a big fan of some of the style. I know some of the repo is not completely consistent, but it would be good to start especially with such a large change.

In particular I would prefer:
-2 space indentation
-'else' on the following line from the closing bracket of the previous if/else if
-If you cannot fit function/template arguments on a single line, put each argument on its own line and the closing parentheses on its own line on the same indentation level in which you are calling the function. In my opinion this makes things significantly more readable than other styles.

int val = longfunctionname(
  reallylongarg1,
  reallylongarg2, //understandable comment about this argument
  otherlongfunctionname(
    otherlongarg1,
    otherlongarg2
  ),
  shortfunction(shortarg1,shortarg2)
);

@rsetaluri
Copy link
Collaborator

rsetaluri commented Jul 22, 2019

@rdaly525 can you point to an example of each thing you're talking about?

2 space indents are for proper "block" indents (while loops, for loops, function body, class body, etc.). 4 space indents should be used for line-break indents.

Both LLVM and Google C++ style are in agreement on this, and the } else { style.

Copy link
Owner

@rdaly525 rdaly525 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content of the code looks good as far as I can tell. I think it was pretty close to some of the original translation code I had but actually using a legitimate AST! This should make verilog backend much nicer. I think the next step is to make verilog code a first class citizen of CoreIR and maybe attaching the verilogAST definitions directly to coreIR modules instead of the hacky metadata way.

Some issues:
-You should never really need to call getKind() anywhere. the isa<>, dyn_cast<>, and cast<> should cover most cases. For direction, the functions isInput(), isOutput() and isInOut() should suffice.
-Some of the files were using 4 spaces instead of 2 spaces. A lot of the multiline assignments would become single line when using 2 spaces.
-style which I described in a previous comment.

this->vmods._verilator_debug = true;
}
void Passes::Verilog::initialize(int argc, char **argv) {
cxxopts::Options options("verilog", "translates coreir graph to verilog");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 2 spaces

}
void Passes::Verilog::initialize(int argc, char **argv) {
cxxopts::Options options("verilog", "translates coreir graph to verilog");
options.add_options()("i,inline", "Inline verilog modules if possible")(
Copy link
Owner

@rdaly525 rdaly525 Jul 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change this back to original style

std::unique_ptr<vAST::Expression> convert_value(Value *value) {
if (auto arg_value = dyn_cast<Arg>(value)) {
return std::make_unique<vAST::Identifier>(arg_value->getField());
} else if (auto int_value = dyn_cast<ConstInt>(value)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please place on new line

// `Vector` node if the signal is of type Array
std::variant<std::unique_ptr<vAST::Identifier>, std::unique_ptr<vAST::Vector>>
process_decl(std::unique_ptr<vAST::Identifier> id, Type *type) {
if (type->getKind() == Type::TK_Array) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use if (ArrayType* array_type = dyn_cast<ArrayType>(type)) {

In general getKind() should not be used much. dyn_cast<> and isa<> should be used instead.
See the doc/ProgrammingGuide.md

// bit), iteratively because perhaps you can name and named type?
// This is just a safety check for internal code, to improve performance,
// we could guard this assert logic behind a macro
while (type->getKind() == Type::TK_Named) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking about getting rid of named types anyways. That level of typing should probably be done at the magma level

// the output ports of each instance. We return a vector of a variant type for
// compatibility with the module AST node constructor, even though we only ever
// create Wire nodes.
std::vector<std::variant<std::unique_ptr<vAST::StructuralStatement>,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This templating is difficult to parse. I would prefer the arguments to variant to each be on their own line.

for (auto port :
cast<RecordType>(instance.second->getModuleRef()->getType())
->getRecord()) {
if (port.second->getDir() == Type::DK_Out) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type has isOutput() method

// **TODO** Need to add support for inouts
std::map<ConnMapKey, std::vector<ConnMapEntry>> build_connection_map(
std::set<Connection, ConnectionCompFast> connections,
std::map<std::string, Instance *> instances) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put closing parenthesis on new line

@rdaly525
Copy link
Owner

Also I suspect the C++17 change will break almost everything using CoreIR right now. Before we merge this to master, it might be prudent to add a buildkite with all our tools

@rdaly525
Copy link
Owner

Also in terms of the catch.hpp, I think this was from https://github.com/catchorg/Catch2. It says that it supports C++17, so we should probably just add that as another external dependency.

@leonardt
Copy link
Collaborator Author

FWIW the style provided in these changes are completely automatically formatted by clang-format, but I'm okay with making the changes you suggested to make the code consistent with the repo. I personally don't care much about these details and prefer automation but that's mainly because it avoids extra effort on my part.

Will also address the cast/direction check issues.

@rsetaluri
Copy link
Collaborator

I think it's better to have new code follow an automated and standard format then retro-fit new code to the non-uniform standard in the code base. Makes it more likely to improve the code quality overtime.

@rdaly525
Copy link
Owner

I would be willing to go with this style. It hits most of my preferences and we can use clang-format with it.
https://github.com/rdaly525/coreir/blob/style/format/.clang-format

@leonardt
Copy link
Collaborator Author

Okay, I merged that branch into this and ran clang-format on verilog.cpp with it.

@leonardt
Copy link
Collaborator Author

Removed the explicit Kind logic and changed it to use isa<{type}> and is{direction}().

@phanrahan phanrahan mentioned this pull request Jul 24, 2019
25 tasks
@rdaly525
Copy link
Owner

Merging

@rdaly525 rdaly525 merged commit d2356c3 into master Jul 31, 2019
@rdaly525 rdaly525 deleted the verilogAST branch July 31, 2019 03:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants