diff options
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/cxxrtl/cxxrtl.cc | 20 | ||||
| -rw-r--r-- | backends/firrtl/firrtl.cc | 63 | 
2 files changed, 65 insertions, 18 deletions
diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc index 549404184..0cceecbba 100644 --- a/backends/cxxrtl/cxxrtl.cc +++ b/backends/cxxrtl/cxxrtl.cc @@ -513,7 +513,6 @@ struct CxxrtlWorker {  	bool elide_public = false;  	bool localize_internal = false;  	bool localize_public = false; -	bool run_opt_clean_purge = false;  	bool run_proc_flatten = false;  	bool max_opt_level = false; @@ -2009,6 +2008,7 @@ struct CxxrtlWorker {  				log("Module `%s' contains feedback arcs through wires:\n", log_id(module));  				for (auto wire : feedback_wires)  					log("  %s\n", log_id(wire)); +				log("\n");  			}  			for (auto wire : module->wires()) { @@ -2040,20 +2040,20 @@ struct CxxrtlWorker {  				log("Module `%s' contains buffered combinatorial wires:\n", log_id(module));  				for (auto wire : buffered_wires)  					log("  %s\n", log_id(wire)); +				log("\n");  			}  			eval_converges[module] = feedback_wires.empty() && buffered_wires.empty();  		}  		if (has_feedback_arcs || has_buffered_wires) {  			// Although both non-feedback buffered combinatorial wires and apparent feedback wires may be eliminated -			// by optimizing the design, if after `opt_clean -purge` there are any feedback wires remaining, it is very +			// by optimizing the design, if after `proc; flatten` there are any feedback wires remaining, it is very  			// likely that these feedback wires are indicative of a true logic loop, so they get emphasized in the message.  			const char *why_pessimistic = nullptr;  			if (has_feedback_arcs)  				why_pessimistic = "feedback wires";  			else if (has_buffered_wires)  				why_pessimistic = "buffered combinatorial wires"; -			log("\n");  			log_warning("Design contains %s, which require delta cycles during evaluation.\n", why_pessimistic);  			if (!max_opt_level)  				log("Increasing the optimization level may eliminate %s from the design.\n", why_pessimistic); @@ -2087,34 +2087,39 @@ struct CxxrtlWorker {  	void prepare_design(RTLIL::Design *design)  	{ +		bool did_anything = false;  		bool has_sync_init, has_packed_mem;  		log_push();  		check_design(design, has_sync_init, has_packed_mem);  		if (run_proc_flatten) {  			Pass::call(design, "proc");  			Pass::call(design, "flatten"); +			did_anything = true;  		} else if (has_sync_init) {  			// We're only interested in proc_init, but it depends on proc_prune and proc_clean, so call those  			// in case they weren't already. (This allows `yosys foo.v -o foo.cc` to work.)  			Pass::call(design, "proc_prune");  			Pass::call(design, "proc_clean");  			Pass::call(design, "proc_init"); +			did_anything = true;  		} -		if (has_packed_mem) +		if (has_packed_mem) {  			Pass::call(design, "memory_unpack"); +			did_anything = true; +		}  		// Recheck the design if it was modified.  		if (has_sync_init || has_packed_mem)  			check_design(design, has_sync_init, has_packed_mem);  		log_assert(!(has_sync_init || has_packed_mem)); -		if (run_opt_clean_purge) -			Pass::call(design, "opt_clean -purge");  		log_pop(); +		if (did_anything) +			log_spacer();  		analyze_design(design);  	}  };  struct CxxrtlBackend : public Backend { -	static const int DEFAULT_OPT_LEVEL = 6; +	static const int DEFAULT_OPT_LEVEL = 5;  	CxxrtlBackend() : Backend("cxxrtl", "convert design to C++ RTL simulation") { }  	void help() YS_OVERRIDE @@ -2340,6 +2345,7 @@ struct CxxrtlBackend : public Backend {  		extra_args(f, filename, args, argidx);  		switch (opt_level) { +			// the highest level here must match DEFAULT_OPT_LEVEL  			case 5:  				worker.max_opt_level = true;  				worker.run_proc_flatten = true; diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index f6dae1d8c..a90b0b87a 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -392,7 +392,34 @@ struct FirrtlWorker  		return result;  	} -	void run() +	void emit_extmodule() +	{ +		std::string moduleFileinfo = getFileinfo(module); +		f << stringf("  extmodule %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); +		vector<std::string> port_decls; + +		for (auto wire : module->wires()) +		{ +			const auto wireName = make_id(wire->name); +			std::string wireFileinfo = getFileinfo(wire); + +			if (wire->port_input && wire->port_output) +			{ +				log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); +			} +			port_decls.push_back(stringf("    %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output", +					wireName, wire->width, wireFileinfo.c_str())); +		} + +		for (auto &str : port_decls) +		{ +			f << str; +		} + +		f << stringf("\n"); +	} + +	void emit_module()  	{  		std::string moduleFileinfo = getFileinfo(module);  		f << stringf("  module %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); @@ -446,7 +473,7 @@ struct FirrtlWorker  			string y_id = make_id(cell->name);  			std::string cellFileinfo = getFileinfo(cell); -			if (cell->type.in(ID($not), ID($logic_not), ID($neg), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_bool), ID($reduce_xnor))) +			if (cell->type.in(ID($not), ID($logic_not), ID($_NOT_), ID($neg), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_bool), ID($reduce_xnor)))  			{  				string a_expr = make_expr(cell->getPort(ID::A));  				wire_decls.push_back(stringf("    wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); @@ -462,7 +489,7 @@ struct FirrtlWorker  				// Assume the FIRRTL width is a single bit.  				firrtl_width = 1; -				if (cell->type == ID($not)) primop = "not"; +				if (cell->type.in(ID($not), ID($_NOT_))) primop = "not";  				else if (cell->type == ID($neg)) {  					primop = "neg";  					firrtl_is_signed = true;	// Result of "neg" is signed (an SInt). @@ -494,7 +521,7 @@ struct FirrtlWorker  				continue;  			} -			if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($xnor), ID($and), ID($or), ID($eq), ID($eqx), +			if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($_XOR_), ID($xnor), ID($and), ID($_AND_), ID($or), ID($_OR_), ID($eq), ID($eqx),                                          ID($gt), ID($ge), ID($lt), ID($le), ID($ne), ID($nex), ID($shr), ID($sshr), ID($sshl), ID($shl),                                          ID($logic_and), ID($logic_or), ID($pow)))  			{ @@ -524,7 +551,7 @@ struct FirrtlWorker  				// For the arithmetic ops, expand operand widths to result widths befor performing the operation.  				// This corresponds (according to iverilog) to what verilog compilers implement. -				if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($xnor), ID($and), ID($or))) +				if (cell->type.in(ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($xor), ID($_XOR_), ID($xnor), ID($and), ID($_AND_), ID($or), ID($_OR_)))  				{  					if (a_width < y_width) {  						a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); @@ -560,17 +587,17 @@ struct FirrtlWorker  				} else if (cell->type == ID($mod)) {  					primop = "rem";  					firrtl_width = min(a_width, b_width); -				} else if (cell->type == ID($and)) { +				} else if (cell->type.in(ID($and), ID($_AND_))) {  					primop = "and";  					always_uint = true;  					firrtl_width = max(a_width, b_width);  				} -				else if (cell->type == ID($or) ) { +				else if (cell->type.in(ID($or), ID($_OR_))) {  					primop =  "or";  					always_uint = true;  					firrtl_width = max(a_width, b_width);  				} -				else if (cell->type == ID($xor)) { +				else if (cell->type.in(ID($xor), ID($_XOR_))) {  					primop = "xor";  					always_uint = true;  					firrtl_width = max(a_width, b_width); @@ -694,7 +721,8 @@ struct FirrtlWorker  					}  				} -				if (!cell->parameters.at(ID::B_SIGNED).as_bool()) { +				auto it = cell->parameters.find(ID::B_SIGNED); +				if (it == cell->parameters.end() || !it->second.as_bool()) {  					b_expr = "asUInt(" + b_expr + ")";  				} @@ -723,9 +751,10 @@ struct FirrtlWorker  				continue;  			} -			if (cell->type.in(ID($mux))) +			if (cell->type.in(ID($mux), ID($_MUX_)))  			{ -				int width = cell->parameters.at(ID::WIDTH).as_int(); +				auto it = cell->parameters.find(ID::WIDTH); +				int width = it == cell->parameters.end()? 1 : it->second.as_int();  				string a_expr = make_expr(cell->getPort(ID::A));  				string b_expr = make_expr(cell->getPort(ID::B));  				string s_expr = make_expr(cell->getPort(ID::S)); @@ -1076,6 +1105,18 @@ struct FirrtlWorker  		for (auto str : wire_exprs)  			f << str; + +		f << stringf("\n"); +	} + +	void run() +	{ +		// Blackboxes should be emitted as `extmodule`s in firrtl. Only ports are +		// emitted in such a case. +		if (module->get_blackbox_attribute()) +			emit_extmodule(); +		else +			emit_module();  	}  };  | 
