From ae9286386de117991f887f919f5af3fac40173cc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 2 Mar 2019 12:36:46 -0800 Subject: [PATCH] Only run derive on blackbox modules when ports have dynamic size Signed-off-by: Clifford Wolf --- README.md | 3 +++ frontends/ast/ast.h | 1 + frontends/ast/simplify.cc | 19 +++++++++++++++++++ passes/hierarchy/hierarchy.cc | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f17046488..9bac468a7 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 89f7e6e4f..8b185ff51 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -239,6 +239,7 @@ namespace AST bool has_const_only_constructs(bool &recommend_const_eval); void replace_variables(std::map &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; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d0b31078a..7160c6c0f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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 &variables, AstNode *fcall) { diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 2d8edebb5..88c339e8c 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -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; -- 2.30.2