Skip to content

Commit

Permalink
Merge branch 'master' into simplify-regex
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardt committed Aug 31, 2020
2 parents 3574b07 + 224548c commit f8793ca
Show file tree
Hide file tree
Showing 4 changed files with 389 additions and 25 deletions.
7 changes: 7 additions & 0 deletions include/verilogAST.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,13 @@ class If : public BehavioralStatement {
else_ifs(std::move(else_ifs)),
else_body(std::move(else_body)){};

If(std::unique_ptr<Expression> cond,
std::vector<std::unique_ptr<BehavioralStatement>> true_body,
std::vector<std::unique_ptr<BehavioralStatement>> else_body)
: cond(std::move(cond)),
true_body(std::move(true_body)),
else_body(std::move(else_body)){};

std::string toString();
~If(){};
};
Expand Down
32 changes: 32 additions & 0 deletions include/verilogAST/assign_inliner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class Blacklister : public Transformer {

protected:
bool blacklist = false;
// Allow numeric literals as valid drivers (okay for module instances, not
// okay for slice/index)
virtual bool allowNumDriver() { return false; };
void blacklist_invalid_driver(std::unique_ptr<Identifier> node);

public:
Blacklister(std::set<std::string> &wire_blacklist,
Expand Down Expand Up @@ -108,6 +112,34 @@ class IndexBlacklister : public Blacklister {
virtual std::unique_ptr<Index> visit(std::unique_ptr<Index> node);
};

class ModuleInstanceBlacklister : public Blacklister {
// Prevent inling wires into module instance nodes, e.g.
// wire z;
// assign b = a;
// assign z = i + a; // <--- not inlined into .w below
// inner_module inner_module_inst (
// .c(a),
// .i(i),
// .w(z),
// .o(o)
// );
//
// We can make this configurable, but for now we keep it as the default since
// some tools do not support general expressions inside module instance
// statements
protected:
bool allowNumDriver() override { return true; };

public:
ModuleInstanceBlacklister(
std::set<std::string> &wire_blacklist,
std::map<std::string, std::unique_ptr<Expression>> &assign_map)
: Blacklister(wire_blacklist, assign_map){};
using Blacklister::visit;
virtual std::unique_ptr<ModuleInstantiation> visit(
std::unique_ptr<ModuleInstantiation> node) override;
};

class AssignInliner : public Transformer {
std::map<std::string, int> read_count;
std::map<std::string, int> assign_count;
Expand Down
66 changes: 56 additions & 10 deletions src/assign_inliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,37 @@

namespace verilogAST {

void Blacklister::blacklist_invalid_driver(std::unique_ptr<Identifier> node) {
if (this->wire_blacklist.count(node->value)) {
// Already blacklisted
return;
}
if (!assign_map.count(node->toString())) {
// Not in assign map, means it's a module input, don't need to do anything
// because it won't be inlined
return;
}
auto driver = assign_map[node->toString()]->clone();
// Can only inline if driven by identifier, index, or slice
bool valid_driver =
dynamic_cast<Identifier*>(driver.get()) ||
dynamic_cast<Index*>(driver.get()) ||
dynamic_cast<Slice*>(driver.get()) ||
(this->allowNumDriver() && dynamic_cast<NumericLiteral*>(driver.get()));
if (!valid_driver) {
this->wire_blacklist.insert(node->value);
} else if (auto ptr = dynamic_cast<Identifier*>(driver.get())) {
// if driven by an id, we need to recursively blacklist any invalid
// drivers, else they'll eventually get inlined into here
driver.release();
blacklist_invalid_driver(std::unique_ptr<Identifier>(ptr));
}
}

std::unique_ptr<Identifier> Blacklister::visit(
std::unique_ptr<Identifier> node) {
if (this->blacklist) {
auto it = assign_map.find(node->toString());
// Can only inline if driven by identifier, index, or slice
bool valid_driver = it != assign_map.end() &&
(dynamic_cast<Identifier*>(it->second.get()) ||
dynamic_cast<Index*>(it->second.get()) ||
dynamic_cast<Slice*>(it->second.get()));
if (!valid_driver) {
this->wire_blacklist.insert(node->value);
}
blacklist_invalid_driver(node->clone());
}
return node;
}
Expand All @@ -37,6 +56,16 @@ std::unique_ptr<Index> IndexBlacklister::visit(std::unique_ptr<Index> node) {
return node;
}

std::unique_ptr<ModuleInstantiation> ModuleInstanceBlacklister::visit(
std::unique_ptr<ModuleInstantiation> node) {
this->blacklist = true;
for (auto&& conn : *node->connections) {
conn.second = this->visit(std::move(conn.second));
}
this->blacklist = false;
return node;
}

std::unique_ptr<Identifier> WireReadCounter::visit(
std::unique_ptr<Identifier> node) {
this->read_count[node->toString()]++;
Expand Down Expand Up @@ -112,7 +141,7 @@ bool AssignInliner::can_inline(std::string key) {
return false;
}
auto it = assign_map.find(key);
return it != assign_map.end() && (this->assign_count[key] == 1) &&
return it != assign_map.end() &&
(this->read_count[key] == 1 ||
dynamic_cast<Identifier*>(it->second.get()) ||
dynamic_cast<NumericLiteral*>(it->second.get()));
Expand All @@ -127,6 +156,12 @@ std::unique_ptr<Index> AssignInliner::visit(std::unique_ptr<Index> node) {
if (auto ptr = dynamic_cast<Identifier*>(value.get())) {
value.release();
node->value = std::unique_ptr<Identifier>(ptr);
} else if (auto ptr = dynamic_cast<Index*>(value.get())) {
value.release();
node->value = std::unique_ptr<Index>(ptr);
} else if (auto ptr = dynamic_cast<Slice*>(value.get())) {
value.release();
node->value = std::unique_ptr<Slice>(ptr);
}
}
return node;
Expand Down Expand Up @@ -235,6 +270,13 @@ std::unique_ptr<Module> AssignInliner::visit(std::unique_ptr<Module> node) {
this->non_input_ports, this->output_ports,
this->input_ports);
node = builder.visit(std::move(node));
for (auto entry : assign_count) {
if (entry.second > 1) {
// Do not inline things assigned more than once, e.g. a reg inside
// if/else statements
this->wire_blacklist.insert(entry.first);
}
}

WireReadCounter counter(this->read_count);
node = counter.visit(std::move(node));
Expand All @@ -245,6 +287,10 @@ std::unique_ptr<Module> AssignInliner::visit(std::unique_ptr<Module> node) {
SliceBlacklister slice_blacklist(this->wire_blacklist, this->assign_map);
node = slice_blacklist.visit(std::move(node));

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

std::vector<std::unique_ptr<AbstractPort>> new_ports;
for (auto&& item : node->ports) {
new_ports.push_back(this->visit(std::move(item)));
Expand Down
Loading

0 comments on commit f8793ca

Please sign in to comment.