aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/Makefile.inc1
-rw-r--r--frontends/ast/ast.cc5
-rw-r--r--frontends/ast/ast.h3
-rw-r--r--frontends/ast/ast_binding.cc49
-rw-r--r--frontends/ast/ast_binding.h58
-rw-r--r--frontends/ast/genrtlil.cc79
6 files changed, 193 insertions, 2 deletions
diff --git a/frontends/ast/Makefile.inc b/frontends/ast/Makefile.inc
index 91d917c91..9e6eee1e8 100644
--- a/frontends/ast/Makefile.inc
+++ b/frontends/ast/Makefile.inc
@@ -3,4 +3,5 @@ OBJS += frontends/ast/ast.o
OBJS += frontends/ast/simplify.o
OBJS += frontends/ast/genrtlil.o
OBJS += frontends/ast/dpicall.o
+OBJS += frontends/ast/ast_binding.o
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index fe503c547..4fbc238b0 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -1310,6 +1310,11 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
design->verilog_packages.push_back(child->clone());
current_scope.clear();
}
+ else if (child->type == AST_BIND) {
+ // top-level bind construct
+ for (RTLIL::Binding *binding : child->genBindings())
+ design->add(binding);
+ }
else {
// must be global definition
if (child->type == AST_PARAMETER)
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index ba5a11b96..63104bca4 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -284,6 +284,9 @@ namespace AST
void dumpAst(FILE *f, std::string indent) const;
void dumpVlog(FILE *f, std::string indent) const;
+ // Generate RTLIL for a bind construct
+ std::vector<RTLIL::Binding *> genBindings() const;
+
// used by genRTLIL() for detecting expression width and sign
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL);
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = NULL);
diff --git a/frontends/ast/ast_binding.cc b/frontends/ast/ast_binding.cc
new file mode 100644
index 000000000..c20d1df4d
--- /dev/null
+++ b/frontends/ast/ast_binding.cc
@@ -0,0 +1,49 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "ast_binding.h"
+#include "ast.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+using namespace AST_INTERNAL;
+
+AST::Binding::Binding(RTLIL::IdString target_type,
+ RTLIL::IdString target_name,
+ const AstNode &cell)
+ : RTLIL::Binding(target_type, target_name),
+ ast_node(cell.clone())
+{
+ log_assert(cell.type == AST_CELL);
+}
+
+std::string
+AST::Binding::describe() const
+{
+ std::ostringstream oss;
+ oss << "directive to bind " << ast_node->str
+ << " to " << target_name.str();
+ if (!target_type.empty())
+ oss << " (target type: "
+ << target_type.str()
+ << ")";
+ return oss.str();
+}
+
+PRIVATE_NAMESPACE_END
diff --git a/frontends/ast/ast_binding.h b/frontends/ast/ast_binding.h
new file mode 100644
index 000000000..641497d52
--- /dev/null
+++ b/frontends/ast/ast_binding.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*-
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * ---
+ *
+ * This header declares the AST::Binding class
+ *
+ * This is used to support the bind directive and is to RTLIL::Binding as
+ * AST::AstModule is to RTLIL::Module, holding a syntax-level representation of
+ * cells until we get to a stage where they make sense. In the case of a bind
+ * directive, this is when we elaborate the design in the hierarchy pass.
+ *
+ */
+
+#ifndef AST_BINDING_H
+#define AST_BINDING_H
+
+#include "kernel/rtlil.h"
+#include "kernel/binding.h"
+
+#include <memory>
+
+YOSYS_NAMESPACE_BEGIN
+
+namespace AST
+{
+ class Binding : public RTLIL::Binding
+ {
+ public:
+ Binding(RTLIL::IdString target_type,
+ RTLIL::IdString target_name,
+ const AstNode &cell);
+
+ std::string describe() const override;
+
+ private:
+ // The syntax-level representation of the cell to be bound.
+ std::unique_ptr<AstNode> ast_node;
+ };
+}
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 45aab9d8e..c82664b98 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -28,8 +28,10 @@
#include "kernel/log.h"
#include "kernel/utils.h"
+#include "kernel/binding.h"
#include "libs/sha1/sha1.h"
#include "ast.h"
+#include "ast_binding.h"
#include <sstream>
#include <stdarg.h>
@@ -733,6 +735,69 @@ struct AST_INTERNAL::ProcessGenerator
}
};
+// Generate RTLIL for a bind construct
+//
+// The AST node will have one or more AST_IDENTIFIER children, which were added
+// by bind_target_instance in the parser. After these, it will have one or more
+// cells, as parsed by single_cell. These have type AST_CELL.
+//
+// If there is more than one AST_IDENTIFIER, the first one should be considered
+// a module identifier. If there is only one AST_IDENTIFIER, we can't tell at
+// this point whether it's a module/interface name or the name of an instance
+// because the correct interpretation depends on what's visible at elaboration
+// time. For now, we just treat it as a target instance with unknown type, and
+// we'll deal with the corner case in the hierarchy pass.
+//
+// To simplify downstream code, RTLIL::Binding only has a single target and
+// single bound instance. If we see the syntax that allows more than one of
+// either, we split it into multiple Binding objects.
+std::vector<RTLIL::Binding *> AstNode::genBindings() const
+{
+ // Partition children into identifiers and cells
+ int num_ids = 0;
+ for (int i = 0; i < GetSize(children); ++i) {
+ if (children[i]->type != AST_IDENTIFIER) {
+ log_assert(i > 0);
+ num_ids = i;
+ break;
+ }
+ }
+
+ // We should have found at least one child that's not an identifier
+ log_assert(num_ids > 0);
+
+ // Make sense of the identifiers, extracting a possible type name and a
+ // list of hierarchical IDs. We represent an unknown type with an empty
+ // string.
+ RTLIL::IdString tgt_type;
+ int first_tgt_inst = 0;
+ if (num_ids > 1) {
+ tgt_type = children[0]->str;
+ first_tgt_inst = 1;
+ }
+
+ std::vector<RTLIL::Binding *> ret;
+
+ // At this point, we know that children with index >= first_tgt_inst and
+ // index < num_ids are (hierarchical?) names of target instances. Make a
+ // binding object for each of them, and fill in the generated instance
+ // cells each time.
+ for (int i = first_tgt_inst; i < num_ids; ++i) {
+ const AstNode &tgt_child = *children[i];
+
+ for (int j = num_ids; j < GetSize(children); ++j) {
+ const AstNode &cell_child = *children[j];
+
+ log_assert(cell_child.type == AST_CELL);
+
+ ret.push_back(new AST::Binding(tgt_type, tgt_child.str,
+ cell_child));
+ }
+ }
+
+ return ret;
+}
+
// detect sign and width of an expression
void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real)
{
@@ -1311,7 +1376,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::Wire *wire = current_module->addWire(str);
set_src_attr(wire, this);
wire->name = str;
- if (flag_autowire)
+
+ // If we are currently processing a bind directive which wires up
+ // signals or parameters explicitly, rather than with .*, then
+ // current_module will start out empty and we don't want to warn the
+ // user about it: we'll spot broken wiring later, when we run the
+ // hierarchy pass.
+ if (dynamic_cast<RTLIL::Binding*>(current_module)) {
+ /* nothing to do here */
+ } else if (flag_autowire)
log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
else
log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
@@ -1975,7 +2048,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
} break;
case AST_BIND: {
- // The bind construct. Currently unimplemented: just ignore it.
+ // Read a bind construct. This should have one or more cells as children.
+ for (RTLIL::Binding *binding : genBindings())
+ current_module->add(binding);
break;
}