Skip to content

Commit

Permalink
Add support for inlining slice/index when just an ID
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardt committed Jul 23, 2020
1 parent 45ff717 commit 8a3a6ed
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 25 deletions.
15 changes: 11 additions & 4 deletions include/verilogAST/assign_inliner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,14 @@ class SliceBlacklister : public Transformer {
//
// Verilog does not support (y + z)[4:0]
std::set<std::string> &wire_blacklist;
std::map<std::string, std::unique_ptr<Expression>> &assign_map;
bool inside_slice = false;

public:
SliceBlacklister(std::set<std::string> &wire_blacklist)
: wire_blacklist(wire_blacklist){};
SliceBlacklister(
std::set<std::string> &wire_blacklist,
std::map<std::string, std::unique_ptr<Expression>> &assign_map)
: wire_blacklist(wire_blacklist), assign_map(assign_map){};

using Transformer::visit;
virtual std::unique_ptr<Slice> visit(std::unique_ptr<Slice> node);
Expand All @@ -88,11 +91,14 @@ class IndexBlacklister : public Transformer {
//
// Verilog does not support (y + z)[0]
std::set<std::string> &wire_blacklist;
std::map<std::string, std::unique_ptr<Expression>> &assign_map;
bool inside_index = false;

public:
IndexBlacklister(std::set<std::string> &wire_blacklist)
: wire_blacklist(wire_blacklist){};
IndexBlacklister(
std::set<std::string> &wire_blacklist,
std::map<std::string, std::unique_ptr<Expression>> &assign_map)
: wire_blacklist(wire_blacklist), assign_map(assign_map){};

using Transformer::visit;
virtual std::unique_ptr<Index> visit(std::unique_ptr<Index> node);
Expand Down Expand Up @@ -126,6 +132,7 @@ class AssignInliner : public Transformer {
: wire_blacklist(wire_blacklist){};
using Transformer::visit;
virtual std::unique_ptr<Expression> visit(std::unique_ptr<Expression> node);
virtual std::unique_ptr<Index> visit(std::unique_ptr<Index> node);
virtual std::unique_ptr<ContinuousAssign> visit(
std::unique_ptr<ContinuousAssign> node);
virtual std::unique_ptr<BlockingAssign> visit(
Expand Down
38 changes: 34 additions & 4 deletions src/assign_inliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ std::unique_ptr<Slice> SliceBlacklister::visit(std::unique_ptr<Slice> node) {

std::unique_ptr<Identifier> SliceBlacklister::visit(
std::unique_ptr<Identifier> node) {
if (this->inside_slice) this->wire_blacklist.insert(node->value);
if (this->inside_slice) {
auto it = assign_map.find(node->toString());
bool assigned_to_id =
it != assign_map.end() && dynamic_cast<Identifier*>(it->second.get());
if (!assigned_to_id) {
this->wire_blacklist.insert(node->value);
}
}
return node;
}

Expand All @@ -29,7 +36,14 @@ std::unique_ptr<Index> IndexBlacklister::visit(std::unique_ptr<Index> node) {

std::unique_ptr<Identifier> IndexBlacklister::visit(
std::unique_ptr<Identifier> node) {
if (this->inside_index) this->wire_blacklist.insert(node->value);
if (this->inside_index) {
auto it = assign_map.find(node->toString());
bool assigned_to_id =
it != assign_map.end() && dynamic_cast<Identifier*>(it->second.get());
if (!assigned_to_id) {
this->wire_blacklist.insert(node->value);
}
};
return node;
}

Expand Down Expand Up @@ -114,6 +128,22 @@ bool AssignInliner::can_inline(std::string key) {
dynamic_cast<NumericLiteral*>(it->second.get()));
}

std::unique_ptr<Index> AssignInliner::visit(std::unique_ptr<Index> node) {
if (std::holds_alternative<std::unique_ptr<Identifier>>(node->value)) {
std::string key =
std::get<std::unique_ptr<Identifier>>(node->value)->toString();
if (this->can_inline(key)) {
std::unique_ptr<Expression> value = this->visit(assign_map[key]->clone());
if (auto ptr = dynamic_cast<Identifier*>(value.get())) {
value.release();
node->value = std::unique_ptr<Identifier>(ptr);
}
}
return node;
}
return Transformer::visit(std::move(node));
}

std::unique_ptr<Expression> AssignInliner::visit(
std::unique_ptr<Expression> node) {
if (auto ptr = dynamic_cast<Identifier*>(node.get())) {
Expand Down Expand Up @@ -219,10 +249,10 @@ std::unique_ptr<Module> AssignInliner::visit(std::unique_ptr<Module> node) {
WireReadCounter counter(this->read_count);
node = counter.visit(std::move(node));

IndexBlacklister index_blacklist(this->wire_blacklist);
IndexBlacklister index_blacklist(this->wire_blacklist, this->assign_map);
node = index_blacklist.visit(std::move(node));

SliceBlacklister slice_blacklist(this->wire_blacklist);
SliceBlacklister slice_blacklist(this->wire_blacklist, this->assign_map);
node = slice_blacklist.visit(std::move(node));

std::vector<std::unique_ptr<AbstractPort>> new_ports;
Expand Down
97 changes: 80 additions & 17 deletions tests/assign_inliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,10 @@ TEST(InlineAssignTests, TestNoInlineIndex) {
std::make_unique<vAST::Vector>(vAST::make_id("i2"), vAST::make_num("1"),
vAST::make_num("0")),
vAST::INPUT, vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(vAST::make_id("o"), vAST::OUTPUT,
vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(vAST::make_id("o0"),
vAST::OUTPUT, vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(vAST::make_id("o1"),
vAST::OUTPUT, vAST::WIRE));

std::vector<std::variant<std::unique_ptr<vAST::StructuralStatement>,
std::unique_ptr<vAST::Declaration>>>
Expand All @@ -726,47 +728,80 @@ TEST(InlineAssignTests, TestNoInlineIndex) {
body.push_back(
std::make_unique<vAST::Wire>(std::make_unique<vAST::Identifier>("x")));

body.push_back(
std::make_unique<vAST::Wire>(std::make_unique<vAST::Identifier>("y")));

body.push_back(std::make_unique<vAST::ContinuousAssign>(
vAST::make_id("x"),
std::make_unique<vAST::BinaryOp>(vAST::make_id("i1"), vAST::BinOp::ADD,
vAST::make_id("i2"))));

body.push_back(std::make_unique<vAST::ContinuousAssign>(
vAST::make_id("o"),
vAST::make_id("o0"),
std::make_unique<vAST::Index>(vAST::make_id("x"), vAST::make_num("0"))));

body.push_back(std::make_unique<vAST::ContinuousAssign>(vAST::make_id("y"),
vAST::make_id("i1")));

body.push_back(std::make_unique<vAST::ContinuousAssign>(
vAST::make_id("o1"),
std::make_unique<vAST::Index>(vAST::make_id("y"), vAST::make_num("0"))));

std::unique_ptr<vAST::AbstractModule> module = std::make_unique<vAST::Module>(
"test_module", std::move(ports), std::move(body));

std::string raw_str =
"module test_module (\n"
" input [1:0] i1,\n"
" input [1:0] i2,\n"
" output o\n"
" output o0,\n"
" output o1\n"
");\n"
"wire x;\n"
"wire y;\n"
"assign x = i1 + i2;\n"
"assign o = x[0];\n"
"assign o0 = x[0];\n"
"assign y = i1;\n"
"assign o1 = y[0];\n"
"endmodule\n";

EXPECT_EQ(module->toString(), raw_str);

std::string expected_str =
"module test_module (\n"
" input [1:0] i1,\n"
" input [1:0] i2,\n"
" output o0,\n"
" output o1\n"
");\n"
"wire x;\n"
"assign x = i1 + i2;\n"
"assign o0 = x[0];\n"
"assign o1 = i1[0];\n"
"endmodule\n";

vAST::AssignInliner transformer;
EXPECT_EQ(transformer.visit(std::move(module))->toString(), raw_str);
EXPECT_EQ(transformer.visit(std::move(module))->toString(), expected_str);
}

TEST(InlineAssignTests, TestNoInlineSlice) {
TEST(InlineAssignTests, TestNoInlineSliceUnlessID) {
std::vector<std::unique_ptr<vAST::AbstractPort>> ports;
ports.push_back(std::make_unique<vAST::Port>(
std::make_unique<vAST::Vector>(vAST::make_id("i1"), vAST::make_num("1"),
std::make_unique<vAST::Vector>(vAST::make_id("i1"), vAST::make_num("4"),
vAST::make_num("0")),
vAST::INPUT, vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(
std::make_unique<vAST::Vector>(vAST::make_id("i2"), vAST::make_num("1"),
std::make_unique<vAST::Vector>(vAST::make_id("i2"), vAST::make_num("4"),
vAST::make_num("0")),
vAST::INPUT, vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(vAST::make_id("o"), vAST::OUTPUT,
vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(
std::make_unique<vAST::Vector>(vAST::make_id("o0"), vAST::make_num("3"),
vAST::make_num("0")),
vAST::OUTPUT, vAST::WIRE));
ports.push_back(std::make_unique<vAST::Port>(
std::make_unique<vAST::Vector>(vAST::make_id("o1"), vAST::make_num("3"),
vAST::make_num("0")),
vAST::OUTPUT, vAST::WIRE));

std::vector<std::variant<std::unique_ptr<vAST::StructuralStatement>,
std::unique_ptr<vAST::Declaration>>>
Expand All @@ -775,34 +810,62 @@ TEST(InlineAssignTests, TestNoInlineSlice) {
body.push_back(
std::make_unique<vAST::Wire>(std::make_unique<vAST::Identifier>("x")));

body.push_back(
std::make_unique<vAST::Wire>(std::make_unique<vAST::Identifier>("y")));

body.push_back(std::make_unique<vAST::ContinuousAssign>(
vAST::make_id("x"),
std::make_unique<vAST::BinaryOp>(vAST::make_id("i1"), vAST::BinOp::ADD,
vAST::make_id("i2"))));

body.push_back(std::make_unique<vAST::ContinuousAssign>(
vAST::make_id("o"),
vAST::make_id("o0"),
std::make_unique<vAST::Slice>(vAST::make_id("x"), vAST::make_num("3"),
vAST::make_num("0"))));

body.push_back(std::make_unique<vAST::ContinuousAssign>(vAST::make_id("y"),
vAST::make_id("i1")));

body.push_back(std::make_unique<vAST::ContinuousAssign>(
vAST::make_id("o1"),
std::make_unique<vAST::Slice>(vAST::make_id("y"), vAST::make_num("3"),
vAST::make_num("0"))));

std::unique_ptr<vAST::AbstractModule> module = std::make_unique<vAST::Module>(
"test_module", std::move(ports), std::move(body));

std::string raw_str =
"module test_module (\n"
" input [1:0] i1,\n"
" input [1:0] i2,\n"
" output o\n"
" input [4:0] i1,\n"
" input [4:0] i2,\n"
" output [3:0] o0,\n"
" output [3:0] o1\n"
");\n"
"wire x;\n"
"wire y;\n"
"assign x = i1 + i2;\n"
"assign o = x[3:0];\n"
"assign o0 = x[3:0];\n"
"assign y = i1;\n"
"assign o1 = y[3:0];\n"
"endmodule\n";

EXPECT_EQ(module->toString(), raw_str);

std::string expected_str =
"module test_module (\n"
" input [4:0] i1,\n"
" input [4:0] i2,\n"
" output [3:0] o0,\n"
" output [3:0] o1\n"
");\n"
"wire x;\n"
"assign x = i1 + i2;\n"
"assign o0 = x[3:0];\n"
"assign o1 = i1[3:0];\n"
"endmodule\n";

vAST::AssignInliner transformer;
EXPECT_EQ(transformer.visit(std::move(module))->toString(), raw_str);
EXPECT_EQ(transformer.visit(std::move(module))->toString(), expected_str);
}

} // namespace
Expand Down

0 comments on commit 8a3a6ed

Please sign in to comment.