Only run derive on blackbox modules when ports have dynamic size

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2019-03-02 12:36:46 -08:00
parent ce6695e22c
commit ae9286386d
4 changed files with 24 additions and 1 deletions

View File

@ -309,6 +309,9 @@ Verilog Attributes and non-standard features
passes to identify input and output ports of cells. The Verilog backend
also does not output blackbox modules on default.
- The ``dynports'' attribute is used by the Verilog front-end to mark modules
that have ports with a width that depends on a parameter.
- The ``keep`` attribute on cells and wires is used to mark objects that should
never be removed by the optimizer. This is used for example for cells that
have hidden connections that are not part of the netlist, such as IO pads.

View File

@ -239,6 +239,7 @@ namespace AST
bool has_const_only_constructs(bool &recommend_const_eval);
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
AstNode *eval_const_function(AstNode *fcall);
bool is_simple_const_expr();
// create a human-readable text representation of the AST (for debugging)
void dumpAst(FILE *f, std::string indent) const;

View File

@ -328,6 +328,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
if (node->type == AST_WIRE) {
if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
for (auto c : node->children[0]->children) {
if (!c->is_simple_const_expr()) {
if (attributes.count("\\dynports"))
delete attributes.at("\\dynports");
attributes["\\dynports"] = AstNode::mkconst_int(1, true);
}
}
}
if (this_wire_scope.count(node->str) > 0) {
AstNode *first_node = this_wire_scope[node->str];
if (first_node->is_input && node->is_reg)
@ -3323,6 +3332,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
return false;
}
bool AstNode::is_simple_const_expr()
{
if (type == AST_IDENTIFIER)
return false;
for (auto child : children)
if (!child->is_simple_const_expr())
return false;
return true;
}
// helper function for AstNode::eval_const_function()
void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)
{

View File

@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
if (m == nullptr)
continue;
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) {
if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
IdString new_m_name = m->derive(design, cell->parameters, true);
if (new_m_name.empty())
continue;