Only run derive on blackbox modules when ports have dynamic size
authorClifford Wolf <clifford@clifford.at>
Sat, 2 Mar 2019 20:36:46 +0000 (12:36 -0800)
committerClifford Wolf <clifford@clifford.at>
Sat, 2 Mar 2019 20:36:46 +0000 (12:36 -0800)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
README.md
frontends/ast/ast.h
frontends/ast/simplify.cc
passes/hierarchy/hierarchy.cc

index f17046488d5b115519fa175f356cc06660fcb41a..9bac468a7fa37a4f605e0cd9aeecb6a1b611c4e5 100644 (file)
--- 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.
index 89f7e6e4f9a3297fb8ef7eceab48ae8908654a8a..8b185ff5158652b0db8bd06f2c046d4514d5bab7 100644 (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;
index d0b31078a2ea1c0d23022bddbe1f5798b319fa0d..7160c6c0f7b46aba15d946859377e594241348ca 100644 (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)
 {
index 2d8edebb5d5879d6ad66d07ade6f0cc1486765aa..88c339e8ca72c8e9ea9c8fb106e3bb237dec05a4 100644 (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;