diff options
Diffstat (limited to 'frontends')
| -rw-r--r-- | frontends/ast/Makefile.inc | 1 | ||||
| -rw-r--r-- | frontends/ast/ast.cc | 5 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 3 | ||||
| -rw-r--r-- | frontends/ast/ast_binding.cc | 49 | ||||
| -rw-r--r-- | frontends/ast/ast_binding.h | 58 | ||||
| -rw-r--r-- | frontends/ast/genrtlil.cc | 79 | 
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;  	}  | 
