mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Merge branch 'master' of github.com:YosysHQ/yosys into pmgen
This commit is contained in:
		
						commit
						c06c062469
					
				
					 28 changed files with 627 additions and 199 deletions
				
			
		| 
						 | 
					@ -106,6 +106,10 @@ struct EdifBackend : public Backend {
 | 
				
			||||||
		log("        if the design contains constant nets. use \"hilomap\" to map to custom\n");
 | 
							log("        if the design contains constant nets. use \"hilomap\" to map to custom\n");
 | 
				
			||||||
		log("        constant drivers first)\n");
 | 
							log("        constant drivers first)\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -gndvccy\n");
 | 
				
			||||||
 | 
							log("        create \"GND\" and \"VCC\" cells with \"Y\" outputs. (the default is \"G\"\n");
 | 
				
			||||||
 | 
							log("        for \"GND\" and \"P\" for \"VCC\".)\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
		log("    -attrprop\n");
 | 
							log("    -attrprop\n");
 | 
				
			||||||
		log("        create EDIF properties for cell attributes\n");
 | 
							log("        create EDIF properties for cell attributes\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
| 
						 | 
					@ -126,7 +130,7 @@ struct EdifBackend : public Backend {
 | 
				
			||||||
		bool port_rename = false;
 | 
							bool port_rename = false;
 | 
				
			||||||
		bool attr_properties = false;
 | 
							bool attr_properties = false;
 | 
				
			||||||
		std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
 | 
							std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
 | 
				
			||||||
		bool nogndvcc = false;
 | 
							bool nogndvcc = false, gndvccy = true;
 | 
				
			||||||
		CellTypes ct(design);
 | 
							CellTypes ct(design);
 | 
				
			||||||
		EdifNames edif_names;
 | 
							EdifNames edif_names;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,6 +145,10 @@ struct EdifBackend : public Backend {
 | 
				
			||||||
				nogndvcc = true;
 | 
									nogndvcc = true;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (args[argidx] == "-gndvccy") {
 | 
				
			||||||
 | 
									gndvccy = true;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (args[argidx] == "-attrprop") {
 | 
								if (args[argidx] == "-attrprop") {
 | 
				
			||||||
				attr_properties = true;
 | 
									attr_properties = true;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
| 
						 | 
					@ -211,7 +219,7 @@ struct EdifBackend : public Backend {
 | 
				
			||||||
			*f << stringf("      (cellType GENERIC)\n");
 | 
								*f << stringf("      (cellType GENERIC)\n");
 | 
				
			||||||
			*f << stringf("      (view VIEW_NETLIST\n");
 | 
								*f << stringf("      (view VIEW_NETLIST\n");
 | 
				
			||||||
			*f << stringf("        (viewType NETLIST)\n");
 | 
								*f << stringf("        (viewType NETLIST)\n");
 | 
				
			||||||
			*f << stringf("        (interface (port G (direction OUTPUT)))\n");
 | 
								*f << stringf("        (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'G');
 | 
				
			||||||
			*f << stringf("      )\n");
 | 
								*f << stringf("      )\n");
 | 
				
			||||||
			*f << stringf("    )\n");
 | 
								*f << stringf("    )\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,7 +227,7 @@ struct EdifBackend : public Backend {
 | 
				
			||||||
			*f << stringf("      (cellType GENERIC)\n");
 | 
								*f << stringf("      (cellType GENERIC)\n");
 | 
				
			||||||
			*f << stringf("      (view VIEW_NETLIST\n");
 | 
								*f << stringf("      (view VIEW_NETLIST\n");
 | 
				
			||||||
			*f << stringf("        (viewType NETLIST)\n");
 | 
								*f << stringf("        (viewType NETLIST)\n");
 | 
				
			||||||
			*f << stringf("        (interface (port P (direction OUTPUT)))\n");
 | 
								*f << stringf("        (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'P');
 | 
				
			||||||
			*f << stringf("      )\n");
 | 
								*f << stringf("      )\n");
 | 
				
			||||||
			*f << stringf("    )\n");
 | 
								*f << stringf("    )\n");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -420,9 +428,9 @@ struct EdifBackend : public Backend {
 | 
				
			||||||
					if (nogndvcc)
 | 
										if (nogndvcc)
 | 
				
			||||||
						log_error("Design contains constant nodes (map with \"hilomap\" first).\n");
 | 
											log_error("Design contains constant nodes (map with \"hilomap\" first).\n");
 | 
				
			||||||
					if (sig == RTLIL::State::S0)
 | 
										if (sig == RTLIL::State::S0)
 | 
				
			||||||
						*f << stringf("            (portRef G (instanceRef GND))\n");
 | 
											*f << stringf("            (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');
 | 
				
			||||||
					if (sig == RTLIL::State::S1)
 | 
										if (sig == RTLIL::State::S1)
 | 
				
			||||||
						*f << stringf("            (portRef P (instanceRef VCC))\n");
 | 
											*f << stringf("            (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P');
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				*f << stringf("          ))\n");
 | 
									*f << stringf("          ))\n");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,11 @@
 | 
				
			||||||
#include "kernel/celltypes.h"
 | 
					#include "kernel/celltypes.h"
 | 
				
			||||||
#include "kernel/cellaigs.h"
 | 
					#include "kernel/cellaigs.h"
 | 
				
			||||||
#include "kernel/log.h"
 | 
					#include "kernel/log.h"
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <regex>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USING_YOSYS_NAMESPACE
 | 
					USING_YOSYS_NAMESPACE
 | 
				
			||||||
PRIVATE_NAMESPACE_BEGIN
 | 
					PRIVATE_NAMESPACE_BEGIN
 | 
				
			||||||
| 
						 | 
					@ -37,6 +41,7 @@ static const FDirection FD_NODIRECTION = 0x0;
 | 
				
			||||||
static const FDirection FD_IN = 0x1;
 | 
					static const FDirection FD_IN = 0x1;
 | 
				
			||||||
static const FDirection FD_OUT = 0x2;
 | 
					static const FDirection FD_OUT = 0x2;
 | 
				
			||||||
static const FDirection FD_INOUT = 0x3;
 | 
					static const FDirection FD_INOUT = 0x3;
 | 
				
			||||||
 | 
					static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get a port direction with respect to a specific module.
 | 
					// Get a port direction with respect to a specific module.
 | 
				
			||||||
FDirection getPortFDirection(IdString id, Module *module)
 | 
					FDirection getPortFDirection(IdString id, Module *module)
 | 
				
			||||||
| 
						 | 
					@ -173,6 +178,26 @@ struct FirrtlWorker
 | 
				
			||||||
	void process_instance(RTLIL::Cell *cell, vector<string> &wire_exprs)
 | 
						void process_instance(RTLIL::Cell *cell, vector<string> &wire_exprs)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		std::string cell_type = fid(cell->type);
 | 
							std::string cell_type = fid(cell->type);
 | 
				
			||||||
 | 
							std::string instanceOf;
 | 
				
			||||||
 | 
							// If this is a parameterized module, its parent module is encoded in the cell type
 | 
				
			||||||
 | 
							if (cell->type.substr(0, 8) == "$paramod")
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::string::iterator it;
 | 
				
			||||||
 | 
								for (it = cell_type.begin(); it < cell_type.end(); it++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									switch (*it) {
 | 
				
			||||||
 | 
										case '\\': /* FALL_THROUGH */
 | 
				
			||||||
 | 
										case '=': /* FALL_THROUGH */
 | 
				
			||||||
 | 
										case '\'': /* FALL_THROUGH */
 | 
				
			||||||
 | 
										case '$': instanceOf.append("_"); break;
 | 
				
			||||||
 | 
										default: instanceOf.append(1, *it); break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								instanceOf = cell_type;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::string cell_name = cellname(cell);
 | 
							std::string cell_name = cellname(cell);
 | 
				
			||||||
		std::string cell_name_comment;
 | 
							std::string cell_name_comment;
 | 
				
			||||||
| 
						 | 
					@ -182,7 +207,13 @@ struct FirrtlWorker
 | 
				
			||||||
			cell_name_comment = "";
 | 
								cell_name_comment = "";
 | 
				
			||||||
		// Find the module corresponding to this instance.
 | 
							// Find the module corresponding to this instance.
 | 
				
			||||||
		auto instModule = design->module(cell->type);
 | 
							auto instModule = design->module(cell->type);
 | 
				
			||||||
		wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), cell_type.c_str()));
 | 
							// If there is no instance for this, just return.
 | 
				
			||||||
 | 
							if (instModule == NULL)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str());
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) {
 | 
							for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) {
 | 
				
			||||||
			if (it->second.size() > 0) {
 | 
								if (it->second.size() > 0) {
 | 
				
			||||||
| 
						 | 
					@ -194,20 +225,20 @@ struct FirrtlWorker
 | 
				
			||||||
				std::string source, sink;
 | 
									std::string source, sink;
 | 
				
			||||||
				switch (dir) {
 | 
									switch (dir) {
 | 
				
			||||||
					case FD_INOUT:
 | 
										case FD_INOUT:
 | 
				
			||||||
						log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", log_id(cell_type), log_signal(it->second));
 | 
											log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second));
 | 
				
			||||||
					case FD_OUT:
 | 
										case FD_OUT:
 | 
				
			||||||
						source = firstName;
 | 
											source = firstName;
 | 
				
			||||||
						sink = secondName;
 | 
											sink = secondName;
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					case FD_NODIRECTION:
 | 
										case FD_NODIRECTION:
 | 
				
			||||||
						log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", log_id(cell_type), log_signal(it->second));
 | 
											log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second));
 | 
				
			||||||
						/* FALL_THROUGH */
 | 
											/* FALL_THROUGH */
 | 
				
			||||||
					case FD_IN:
 | 
										case FD_IN:
 | 
				
			||||||
						source = secondName;
 | 
											source = secondName;
 | 
				
			||||||
						sink = firstName;
 | 
											sink = firstName;
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					default:
 | 
										default:
 | 
				
			||||||
						log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", log_id(cell_type), log_signal(it->second), dir);
 | 
											log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", cell_type.c_str(), log_signal(it->second), dir);
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str()));
 | 
									wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str()));
 | 
				
			||||||
| 
						 | 
					@ -217,6 +248,20 @@ struct FirrtlWorker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Given an expression for a shift amount, and a maximum width,
 | 
				
			||||||
 | 
						//  generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics.
 | 
				
			||||||
 | 
						std::string gen_dshl(const string b_expr, const int b_padded_width)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							string result = b_expr;
 | 
				
			||||||
 | 
							if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) {
 | 
				
			||||||
 | 
								int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1;
 | 
				
			||||||
 | 
								string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<<max_shift_width_bits) - 1);
 | 
				
			||||||
 | 
								// Deal with the difference in semantics between FIRRTL and verilog
 | 
				
			||||||
 | 
								result = stringf("mux(gt(%s, %s), %s, bits(%s, %d, 0))", b_expr.c_str(), max_shift_string.c_str(), max_shift_string.c_str(), b_expr.c_str(), max_shift_width_bits - 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void run()
 | 
						void run()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		f << stringf("  module %s:\n", make_id(module->name));
 | 
							f << stringf("  module %s:\n", make_id(module->name));
 | 
				
			||||||
| 
						 | 
					@ -225,6 +270,12 @@ struct FirrtlWorker
 | 
				
			||||||
		for (auto wire : module->wires())
 | 
							for (auto wire : module->wires())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			const auto wireName = make_id(wire->name);
 | 
								const auto wireName = make_id(wire->name);
 | 
				
			||||||
 | 
								// If a wire has initial data, issue a warning since FIRRTL doesn't currently support it.
 | 
				
			||||||
 | 
								if (wire->attributes.count("\\init")) {
 | 
				
			||||||
 | 
									log_warning("Initial value (%s) for (%s.%s) not supported\n",
 | 
				
			||||||
 | 
												wire->attributes.at("\\init").as_string().c_str(),
 | 
				
			||||||
 | 
												log_id(module), log_id(wire));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (wire->port_id)
 | 
								if (wire->port_id)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (wire->port_input && wire->port_output)
 | 
									if (wire->port_input && wire->port_output)
 | 
				
			||||||
| 
						 | 
					@ -240,7 +291,8 @@ struct FirrtlWorker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto cell : module->cells())
 | 
							for (auto cell : module->cells())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		  // Is this cell is a module instance?
 | 
								bool extract_y_bits = false;		// Assume no extraction of final bits will be required.
 | 
				
			||||||
 | 
							    // Is this cell is a module instance?
 | 
				
			||||||
			if (cell->type[0] != '$')
 | 
								if (cell->type[0] != '$')
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				process_instance(cell, wire_exprs);
 | 
									process_instance(cell, wire_exprs);
 | 
				
			||||||
| 
						 | 
					@ -264,21 +316,21 @@ struct FirrtlWorker
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				string primop;
 | 
									string primop;
 | 
				
			||||||
                                bool always_uint = false;
 | 
									bool always_uint = false;
 | 
				
			||||||
				if (cell->type == "$not") primop = "not";
 | 
									if (cell->type == "$not") primop = "not";
 | 
				
			||||||
				if (cell->type == "$neg") primop = "neg";
 | 
									else if (cell->type == "$neg") primop = "neg";
 | 
				
			||||||
				if (cell->type == "$logic_not") {
 | 
									else if (cell->type == "$logic_not") {
 | 
				
			||||||
                                        primop = "eq";
 | 
					                                        primop = "eq";
 | 
				
			||||||
                                        a_expr = stringf("%s, UInt(0)", a_expr.c_str());
 | 
					                                        a_expr = stringf("%s, UInt(0)", a_expr.c_str());
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$reduce_and") primop = "andr";
 | 
									else if (cell->type == "$reduce_and") primop = "andr";
 | 
				
			||||||
				if (cell->type == "$reduce_or") primop = "orr";
 | 
									else if (cell->type == "$reduce_or") primop = "orr";
 | 
				
			||||||
				if (cell->type == "$reduce_xor") primop = "xorr";
 | 
									else if (cell->type == "$reduce_xor") primop = "xorr";
 | 
				
			||||||
				if (cell->type == "$reduce_xnor") {
 | 
									else if (cell->type == "$reduce_xnor") {
 | 
				
			||||||
                                        primop = "not";
 | 
					                                        primop = "not";
 | 
				
			||||||
                                        a_expr = stringf("xorr(%s)", a_expr.c_str());
 | 
					                                        a_expr = stringf("xorr(%s)", a_expr.c_str());
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$reduce_bool") {
 | 
									else if (cell->type == "$reduce_bool") {
 | 
				
			||||||
					primop = "neq";
 | 
										primop = "neq";
 | 
				
			||||||
					// Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
 | 
										// Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
 | 
				
			||||||
					bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
 | 
										bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
 | 
				
			||||||
| 
						 | 
					@ -297,14 +349,15 @@ struct FirrtlWorker
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx",
 | 
								if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx",
 | 
				
			||||||
                                        "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
 | 
												  "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
 | 
				
			||||||
                                        "$logic_and", "$logic_or"))
 | 
												  "$logic_and", "$logic_or"))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				string y_id = make_id(cell->name);
 | 
									string y_id = make_id(cell->name);
 | 
				
			||||||
				bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
 | 
									bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
 | 
				
			||||||
				int y_width =  cell->parameters.at("\\Y_WIDTH").as_int();
 | 
									int y_width =  cell->parameters.at("\\Y_WIDTH").as_int();
 | 
				
			||||||
				string a_expr = make_expr(cell->getPort("\\A"));
 | 
									string a_expr = make_expr(cell->getPort("\\A"));
 | 
				
			||||||
				string b_expr = make_expr(cell->getPort("\\B"));
 | 
									string b_expr = make_expr(cell->getPort("\\B"));
 | 
				
			||||||
 | 
									int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
 | 
				
			||||||
				wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width));
 | 
									wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (cell->parameters.at("\\A_SIGNED").as_bool()) {
 | 
									if (cell->parameters.at("\\A_SIGNED").as_bool()) {
 | 
				
			||||||
| 
						 | 
					@ -315,67 +368,93 @@ struct FirrtlWorker
 | 
				
			||||||
					if (cell->parameters.at("\\B_SIGNED").as_bool()) {
 | 
										if (cell->parameters.at("\\B_SIGNED").as_bool()) {
 | 
				
			||||||
						b_expr = "asSInt(" + b_expr + ")";
 | 
											b_expr = "asSInt(" + b_expr + ")";
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
 | 
										if (b_padded_width < y_width) {
 | 
				
			||||||
 | 
											auto b_sig = cell->getPort("\\B");
 | 
				
			||||||
 | 
											b_padded_width = y_width;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
 | 
									auto a_sig = cell->getPort("\\A");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (cell->parameters.at("\\A_SIGNED").as_bool()  & (cell->type == "$shr")) {
 | 
									if (cell->parameters.at("\\A_SIGNED").as_bool()  & (cell->type == "$shr")) {
 | 
				
			||||||
					a_expr = "asUInt(" + a_expr + ")";
 | 
										a_expr = "asUInt(" + a_expr + ")";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				string primop;
 | 
									string primop;
 | 
				
			||||||
                                bool always_uint = false;
 | 
									bool always_uint = false;
 | 
				
			||||||
				if (cell->type == "$add") primop = "add";
 | 
									if (cell->type == "$add") primop = "add";
 | 
				
			||||||
				if (cell->type == "$sub") primop = "sub";
 | 
									else if (cell->type == "$sub") primop = "sub";
 | 
				
			||||||
				if (cell->type == "$mul") primop = "mul";
 | 
									else if (cell->type == "$mul") primop = "mul";
 | 
				
			||||||
				if (cell->type == "$div") primop = "div";
 | 
									else if (cell->type == "$div") primop = "div";
 | 
				
			||||||
				if (cell->type == "$mod") primop = "rem";
 | 
									else if (cell->type == "$mod") primop = "rem";
 | 
				
			||||||
				if (cell->type == "$and") {
 | 
									else if (cell->type == "$and") {
 | 
				
			||||||
                                        primop = "and";
 | 
					                                        primop = "and";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$or" ) {
 | 
									else if (cell->type == "$or" ) {
 | 
				
			||||||
                                        primop =  "or";
 | 
					                                        primop =  "or";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$xor") {
 | 
									else if (cell->type == "$xor") {
 | 
				
			||||||
                                        primop = "xor";
 | 
					                                        primop = "xor";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if ((cell->type == "$eq") | (cell->type == "$eqx")) {
 | 
									else if ((cell->type == "$eq") | (cell->type == "$eqx")) {
 | 
				
			||||||
                                        primop = "eq";
 | 
					                                        primop = "eq";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if ((cell->type == "$ne") | (cell->type == "$nex")) {
 | 
									else if ((cell->type == "$ne") | (cell->type == "$nex")) {
 | 
				
			||||||
                                        primop = "neq";
 | 
					                                        primop = "neq";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$gt") {
 | 
									else if (cell->type == "$gt") {
 | 
				
			||||||
                                        primop = "gt";
 | 
					                                        primop = "gt";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$ge") {
 | 
									else if (cell->type == "$ge") {
 | 
				
			||||||
                                        primop = "geq";
 | 
					                                        primop = "geq";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$lt") {
 | 
									else if (cell->type == "$lt") {
 | 
				
			||||||
                                        primop = "lt";
 | 
					                                        primop = "lt";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if (cell->type == "$le") {
 | 
									else if (cell->type == "$le") {
 | 
				
			||||||
                                        primop = "leq";
 | 
					                                        primop = "leq";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if ((cell->type == "$shl") | (cell->type == "$sshl")) primop = "dshl";
 | 
									else if ((cell->type == "$shl") | (cell->type == "$sshl")) {
 | 
				
			||||||
				if ((cell->type == "$shr") | (cell->type == "$sshr")) primop = "dshr";
 | 
										// FIRRTL will widen the result (y) by the amount of the shift.
 | 
				
			||||||
				if ((cell->type == "$logic_and")) {
 | 
										// We'll need to offset this by extracting the un-widened portion as Verilog would do.
 | 
				
			||||||
 | 
										extract_y_bits = true;
 | 
				
			||||||
 | 
										// Is the shift amount constant?
 | 
				
			||||||
 | 
										auto b_sig = cell->getPort("\\B");
 | 
				
			||||||
 | 
										if (b_sig.is_fully_const()) {
 | 
				
			||||||
 | 
											primop = "shl";
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											primop = "dshl";
 | 
				
			||||||
 | 
											// Convert from FIRRTL left shift semantics.
 | 
				
			||||||
 | 
											b_expr = gen_dshl(b_expr, b_padded_width);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else if ((cell->type == "$shr") | (cell->type == "$sshr")) {
 | 
				
			||||||
 | 
										// We don't need to extract a specific range of bits.
 | 
				
			||||||
 | 
										extract_y_bits = false;
 | 
				
			||||||
 | 
										// Is the shift amount constant?
 | 
				
			||||||
 | 
										auto b_sig = cell->getPort("\\B");
 | 
				
			||||||
 | 
										if (b_sig.is_fully_const()) {
 | 
				
			||||||
 | 
											primop = "shr";
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											primop = "dshr";
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else if ((cell->type == "$logic_and")) {
 | 
				
			||||||
                                        primop = "and";
 | 
					                                        primop = "and";
 | 
				
			||||||
                                        a_expr = "neq(" + a_expr + ", UInt(0))";
 | 
					                                        a_expr = "neq(" + a_expr + ", UInt(0))";
 | 
				
			||||||
                                        b_expr = "neq(" + b_expr + ", UInt(0))";
 | 
					                                        b_expr = "neq(" + b_expr + ", UInt(0))";
 | 
				
			||||||
                                        always_uint = true;
 | 
					                                        always_uint = true;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
				if ((cell->type == "$logic_or")) {
 | 
									else if ((cell->type == "$logic_or")) {
 | 
				
			||||||
                                        primop = "or";
 | 
					                                        primop = "or";
 | 
				
			||||||
                                        a_expr = "neq(" + a_expr + ", UInt(0))";
 | 
					                                        a_expr = "neq(" + a_expr + ", UInt(0))";
 | 
				
			||||||
                                        b_expr = "neq(" + b_expr + ", UInt(0))";
 | 
					                                        b_expr = "neq(" + b_expr + ", UInt(0))";
 | 
				
			||||||
| 
						 | 
					@ -388,6 +467,11 @@ struct FirrtlWorker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
 | 
									string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Deal with FIRRTL's "shift widens" semantics
 | 
				
			||||||
 | 
									if (extract_y_bits) {
 | 
				
			||||||
 | 
										expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if ((is_signed && !always_uint) || cell->type.in("$sub"))
 | 
									if ((is_signed && !always_uint) || cell->type.in("$sub"))
 | 
				
			||||||
					expr = stringf("asUInt(%s)", expr.c_str());
 | 
										expr = stringf("asUInt(%s)", expr.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -513,7 +597,65 @@ struct FirrtlWorker
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
 | 
								// This may be a parameterized module - paramod.
 | 
				
			||||||
 | 
								if (cell->type.substr(0, 8) == "$paramod")
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									process_instance(cell, wire_exprs);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (cell->type == "$shiftx") {
 | 
				
			||||||
 | 
									// assign y = a[b +: y_width];
 | 
				
			||||||
 | 
									// We'll extract the correct bits as part of the primop.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									string y_id = make_id(cell->name);
 | 
				
			||||||
 | 
									int y_width =  cell->parameters.at("\\Y_WIDTH").as_int();
 | 
				
			||||||
 | 
									string a_expr = make_expr(cell->getPort("\\A"));
 | 
				
			||||||
 | 
									// Get the initial bit selector
 | 
				
			||||||
 | 
									string b_expr = make_expr(cell->getPort("\\B"));
 | 
				
			||||||
 | 
									wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (cell->getParam("\\B_SIGNED").as_bool()) {
 | 
				
			||||||
 | 
										// Use validif to constrain the selection (test the sign bit)
 | 
				
			||||||
 | 
										auto b_string = b_expr.c_str();
 | 
				
			||||||
 | 
										int b_sign = cell->parameters.at("\\B_WIDTH").as_int() - 1;
 | 
				
			||||||
 | 
										b_expr = stringf("validif(not(bits(%s, %d, %d)), %s)", b_string, b_sign, b_sign, b_string);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									string expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_expr.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str()));
 | 
				
			||||||
 | 
									register_reverse_wire_map(y_id, cell->getPort("\\Y"));
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (cell->type == "$shift") {
 | 
				
			||||||
 | 
									// assign y = a >> b;
 | 
				
			||||||
 | 
									//  where b may be negative
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									string y_id = make_id(cell->name);
 | 
				
			||||||
 | 
									int y_width =  cell->parameters.at("\\Y_WIDTH").as_int();
 | 
				
			||||||
 | 
									string a_expr = make_expr(cell->getPort("\\A"));
 | 
				
			||||||
 | 
									string b_expr = make_expr(cell->getPort("\\B"));
 | 
				
			||||||
 | 
									auto b_string = b_expr.c_str();
 | 
				
			||||||
 | 
									int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int();
 | 
				
			||||||
 | 
									string expr;
 | 
				
			||||||
 | 
									wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (cell->getParam("\\B_SIGNED").as_bool()) {
 | 
				
			||||||
 | 
										// We generate a left or right shift based on the sign of b.
 | 
				
			||||||
 | 
										std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width);
 | 
				
			||||||
 | 
										std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
 | 
				
			||||||
 | 
										expr = stringf("mux(%s < 0, %s, %s)",
 | 
				
			||||||
 | 
														 b_string,
 | 
				
			||||||
 | 
														 dshl.c_str(),
 | 
				
			||||||
 | 
														 dshr.c_str()
 | 
				
			||||||
 | 
														 );
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										expr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str()));
 | 
				
			||||||
 | 
									register_reverse_wire_map(y_id, cell->getPort("\\Y"));
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto conn : module->connections())
 | 
							for (auto conn : module->connections())
 | 
				
			||||||
| 
						 | 
					@ -629,38 +771,53 @@ struct FirrtlBackend : public Backend {
 | 
				
			||||||
		log("    write_firrtl [options] [filename]\n");
 | 
							log("    write_firrtl [options] [filename]\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
		log("Write a FIRRTL netlist of the current design.\n");
 | 
							log("Write a FIRRTL netlist of the current design.\n");
 | 
				
			||||||
 | 
							log("The following commands are executed by this command:\n");
 | 
				
			||||||
 | 
							log("        pmuxtree\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
						void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		size_t argidx;
 | 
							size_t argidx = args.size();	// We aren't expecting any arguments.
 | 
				
			||||||
		for (argidx = 1; argidx < args.size(); argidx++)
 | 
					
 | 
				
			||||||
		{
 | 
							// If we weren't explicitly passed a filename, use the last argument (if it isn't a flag).
 | 
				
			||||||
			// if (args[argidx] == "-aig") {
 | 
							if (filename == "") {
 | 
				
			||||||
			// 	aig_mode = true;
 | 
								if (argidx > 0 && args[argidx - 1][0] != '-') {
 | 
				
			||||||
			// 	continue;
 | 
									// extra_args and friends need to see this argument.
 | 
				
			||||||
			// }
 | 
									argidx -= 1;
 | 
				
			||||||
			break;
 | 
									filename = args[argidx];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		extra_args(f, filename, args, argidx);
 | 
							extra_args(f, filename, args, argidx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!design->full_selection())
 | 
				
			||||||
 | 
								log_cmd_error("This command only operates on fully selected designs!\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log_header(design, "Executing FIRRTL backend.\n");
 | 
							log_header(design, "Executing FIRRTL backend.\n");
 | 
				
			||||||
 | 
							log_push();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Module *top = design->top_module();
 | 
							Pass::call(design, stringf("pmuxtree"));
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (top == nullptr)
 | 
					 | 
				
			||||||
			log_error("No top module found!\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		namecache.clear();
 | 
							namecache.clear();
 | 
				
			||||||
		autoid_counter = 0;
 | 
							autoid_counter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Get the top module, or a reasonable facsimile - we need something for the circuit name.
 | 
				
			||||||
 | 
							Module *top = design->top_module();
 | 
				
			||||||
 | 
							Module *last = nullptr;
 | 
				
			||||||
 | 
							// Generate module and wire names.
 | 
				
			||||||
		for (auto module : design->modules()) {
 | 
							for (auto module : design->modules()) {
 | 
				
			||||||
			make_id(module->name);
 | 
								make_id(module->name);
 | 
				
			||||||
 | 
								last = module;
 | 
				
			||||||
 | 
								if (top == nullptr && module->get_bool_attribute("\\top")) {
 | 
				
			||||||
 | 
									top = module;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			for (auto wire : module->wires())
 | 
								for (auto wire : module->wires())
 | 
				
			||||||
				if (wire->port_id)
 | 
									if (wire->port_id)
 | 
				
			||||||
					make_id(wire->name);
 | 
										make_id(wire->name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (top == nullptr)
 | 
				
			||||||
 | 
								top = last;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		*f << stringf("circuit %s:\n", make_id(top->name));
 | 
							*f << stringf("circuit %s:\n", make_id(top->name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto module : design->modules())
 | 
							for (auto module : design->modules())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -784,7 +784,7 @@ class SmtIo:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_path(self, mod, path):
 | 
					    def get_path(self, mod, path):
 | 
				
			||||||
        assert mod in self.modinfo
 | 
					        assert mod in self.modinfo
 | 
				
			||||||
        path = path.split(".")
 | 
					        path = path.replace("\\", "/").split(".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i in range(len(path)-1):
 | 
					        for i in range(len(path)-1):
 | 
				
			||||||
            first = ".".join(path[0:i+1])
 | 
					            first = ".".join(path[0:i+1])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,33 @@ std::string id(RTLIL::IdString internal_id, bool may_rename = true)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const pool<string> keywords = {
 | 
				
			||||||
 | 
							// IEEE 1800-2017 Annex B
 | 
				
			||||||
 | 
							"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
 | 
				
			||||||
 | 
							"begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle",
 | 
				
			||||||
 | 
							"checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint",
 | 
				
			||||||
 | 
							"cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker",
 | 
				
			||||||
 | 
							"endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
 | 
				
			||||||
 | 
							"endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually",
 | 
				
			||||||
 | 
							"expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function",
 | 
				
			||||||
 | 
							"generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
 | 
				
			||||||
 | 
							"import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface",
 | 
				
			||||||
 | 
							"intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint",
 | 
				
			||||||
 | 
							"macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor",
 | 
				
			||||||
 | 
							"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive",
 | 
				
			||||||
 | 
							"priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
 | 
				
			||||||
 | 
							"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat",
 | 
				
			||||||
 | 
							"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
 | 
				
			||||||
 | 
							"s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify",
 | 
				
			||||||
 | 
							"specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on",
 | 
				
			||||||
 | 
							"sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
 | 
				
			||||||
 | 
							"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with",
 | 
				
			||||||
 | 
							"untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
 | 
				
			||||||
 | 
							"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						if (keywords.count(str))
 | 
				
			||||||
 | 
							do_escape = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (do_escape)
 | 
						if (do_escape)
 | 
				
			||||||
		return "\\" + std::string(str) + " ";
 | 
							return "\\" + std::string(str) + " ";
 | 
				
			||||||
	return std::string(str);
 | 
						return std::string(str);
 | 
				
			||||||
| 
						 | 
					@ -789,6 +816,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cell->type == "$tribuf")
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							f << stringf("%s" "assign ", indent.c_str());
 | 
				
			||||||
 | 
							dump_sigspec(f, cell->getPort("\\Y"));
 | 
				
			||||||
 | 
							f << stringf(" = ");
 | 
				
			||||||
 | 
							dump_sigspec(f, cell->getPort("\\EN"));
 | 
				
			||||||
 | 
							f << stringf(" ? ");
 | 
				
			||||||
 | 
							dump_sigspec(f, cell->getPort("\\A"));
 | 
				
			||||||
 | 
							f << stringf(" : %d'bz;\n", cell->parameters.at("\\WIDTH").as_int());
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cell->type == "$slice")
 | 
						if (cell->type == "$slice")
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		f << stringf("%s" "assign ", indent.c_str());
 | 
							f << stringf("%s" "assign ", indent.c_str());
 | 
				
			||||||
| 
						 | 
					@ -1026,43 +1065,46 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
				
			||||||
			use_rd_clk = cell->parameters["\\RD_CLK_ENABLE"].extract(i).as_bool();
 | 
								use_rd_clk = cell->parameters["\\RD_CLK_ENABLE"].extract(i).as_bool();
 | 
				
			||||||
			rd_clk_posedge = cell->parameters["\\RD_CLK_POLARITY"].extract(i).as_bool();
 | 
								rd_clk_posedge = cell->parameters["\\RD_CLK_POLARITY"].extract(i).as_bool();
 | 
				
			||||||
			rd_transparent = cell->parameters["\\RD_TRANSPARENT"].extract(i).as_bool();
 | 
								rd_transparent = cell->parameters["\\RD_TRANSPARENT"].extract(i).as_bool();
 | 
				
			||||||
 | 
								if (use_rd_clk)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				std::ostringstream os;
 | 
					 | 
				
			||||||
				dump_sigspec(os, sig_rd_clk);
 | 
					 | 
				
			||||||
				clk_domain_str = stringf("%sedge %s", rd_clk_posedge ? "pos" : "neg", os.str().c_str());
 | 
					 | 
				
			||||||
				if( clk_to_lof_body.count(clk_domain_str) == 0 )
 | 
					 | 
				
			||||||
					clk_to_lof_body[clk_domain_str] = std::vector<std::string>();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (use_rd_clk && !rd_transparent)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// for clocked read ports make something like:
 | 
					 | 
				
			||||||
				//   reg [..] temp_id;
 | 
					 | 
				
			||||||
				//   always @(posedge clk)
 | 
					 | 
				
			||||||
				//      if (rd_en) temp_id <= array_reg[r_addr];
 | 
					 | 
				
			||||||
				//   assign r_data = temp_id;
 | 
					 | 
				
			||||||
				std::string temp_id = next_auto_id();
 | 
					 | 
				
			||||||
				lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", sig_rd_data.size() - 1, temp_id.c_str()) );
 | 
					 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					std::ostringstream os;
 | 
										std::ostringstream os;
 | 
				
			||||||
					if (sig_rd_en != RTLIL::SigBit(true))
 | 
										dump_sigspec(os, sig_rd_clk);
 | 
				
			||||||
 | 
										clk_domain_str = stringf("%sedge %s", rd_clk_posedge ? "pos" : "neg", os.str().c_str());
 | 
				
			||||||
 | 
										if( clk_to_lof_body.count(clk_domain_str) == 0 )
 | 
				
			||||||
 | 
											clk_to_lof_body[clk_domain_str] = std::vector<std::string>();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (!rd_transparent)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										// for clocked read ports make something like:
 | 
				
			||||||
 | 
										//   reg [..] temp_id;
 | 
				
			||||||
 | 
										//   always @(posedge clk)
 | 
				
			||||||
 | 
										//      if (rd_en) temp_id <= array_reg[r_addr];
 | 
				
			||||||
 | 
										//   assign r_data = temp_id;
 | 
				
			||||||
 | 
										std::string temp_id = next_auto_id();
 | 
				
			||||||
 | 
										lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", sig_rd_data.size() - 1, temp_id.c_str()) );
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						os << stringf("if (");
 | 
											std::ostringstream os;
 | 
				
			||||||
						dump_sigspec(os, sig_rd_en);
 | 
											if (sig_rd_en != RTLIL::SigBit(true))
 | 
				
			||||||
						os << stringf(") ");
 | 
											{
 | 
				
			||||||
 | 
												os << stringf("if (");
 | 
				
			||||||
 | 
												dump_sigspec(os, sig_rd_en);
 | 
				
			||||||
 | 
												os << stringf(") ");
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str());
 | 
				
			||||||
 | 
											dump_sigspec(os, sig_rd_addr);
 | 
				
			||||||
 | 
											os << stringf("];\n");
 | 
				
			||||||
 | 
											clk_to_lof_body[clk_domain_str].push_back(os.str());
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											std::ostringstream os;
 | 
				
			||||||
 | 
											dump_sigspec(os, sig_rd_data);
 | 
				
			||||||
 | 
											std::string line = stringf("assign %s = %s;\n", os.str().c_str(), temp_id.c_str());
 | 
				
			||||||
 | 
											clk_to_lof_body[""].push_back(line);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str());
 | 
					 | 
				
			||||||
					dump_sigspec(os, sig_rd_addr);
 | 
					 | 
				
			||||||
					os << stringf("];\n");
 | 
					 | 
				
			||||||
					clk_to_lof_body[clk_domain_str].push_back(os.str());
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					std::ostringstream os;
 | 
					 | 
				
			||||||
					dump_sigspec(os, sig_rd_data);
 | 
					 | 
				
			||||||
					std::string line = stringf("assign %s = %s;\n", os.str().c_str(), temp_id.c_str());
 | 
					 | 
				
			||||||
					clk_to_lof_body[""].push_back(line);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				if (rd_transparent) {
 | 
					 | 
				
			||||||
					// for rd-transparent read-ports make something like:
 | 
										// for rd-transparent read-ports make something like:
 | 
				
			||||||
					//   reg [..] temp_id;
 | 
										//   reg [..] temp_id;
 | 
				
			||||||
					//   always @(posedge clk)
 | 
										//   always @(posedge clk)
 | 
				
			||||||
| 
						 | 
					@ -1082,15 +1124,15 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
				
			||||||
						std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), temp_id.c_str());
 | 
											std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), temp_id.c_str());
 | 
				
			||||||
						clk_to_lof_body[""].push_back(line);
 | 
											clk_to_lof_body[""].push_back(line);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					// for non-clocked read-ports make something like:
 | 
					 | 
				
			||||||
					//   assign r_data = array_reg[r_addr];
 | 
					 | 
				
			||||||
					std::ostringstream os, os2;
 | 
					 | 
				
			||||||
					dump_sigspec(os, sig_rd_data);
 | 
					 | 
				
			||||||
					dump_sigspec(os2, sig_rd_addr);
 | 
					 | 
				
			||||||
					std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str());
 | 
					 | 
				
			||||||
					clk_to_lof_body[""].push_back(line);
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// for non-clocked read-ports make something like:
 | 
				
			||||||
 | 
									//   assign r_data = array_reg[r_addr];
 | 
				
			||||||
 | 
									std::ostringstream os, os2;
 | 
				
			||||||
 | 
									dump_sigspec(os, sig_rd_data);
 | 
				
			||||||
 | 
									dump_sigspec(os2, sig_rd_addr);
 | 
				
			||||||
 | 
									std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str());
 | 
				
			||||||
 | 
									clk_to_lof_body[""].push_back(line);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								examples/igloo2/.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								examples/igloo2/.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
/netlist.edn
 | 
					/netlist.edn
 | 
				
			||||||
/netlist.v
 | 
					/netlist.vm
 | 
				
			||||||
/work
 | 
					/proj
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/igloo2/example.pdc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/igloo2/example.pdc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					# Add placement constraints here
 | 
				
			||||||
							
								
								
									
										1
									
								
								examples/igloo2/example.sdc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/igloo2/example.sdc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					# Add timing constraints here
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
module top (
 | 
					module example (
 | 
				
			||||||
	input  clk,
 | 
						input  clk,
 | 
				
			||||||
 | 
						input  EN,
 | 
				
			||||||
	output LED1,
 | 
						output LED1,
 | 
				
			||||||
	output LED2,
 | 
						output LED2,
 | 
				
			||||||
	output LED3,
 | 
						output LED3,
 | 
				
			||||||
| 
						 | 
					@ -14,7 +15,7 @@ module top (
 | 
				
			||||||
	reg [BITS-1:0] outcnt;
 | 
						reg [BITS-1:0] outcnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	always @(posedge clk) begin
 | 
						always @(posedge clk) begin
 | 
				
			||||||
		counter <= counter + 1;
 | 
							counter <= counter + EN;
 | 
				
			||||||
		outcnt <= counter >> LOG2DELAY;
 | 
							outcnt <= counter >> LOG2DELAY;
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +0,0 @@
 | 
				
			||||||
read_verilog example.v
 | 
					 | 
				
			||||||
synth_sf2 -top top -edif netlist.edn
 | 
					 | 
				
			||||||
write_verilog netlist.v
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,24 +1,36 @@
 | 
				
			||||||
# Run with "libero SCRIPT:libero.tcl"
 | 
					# Run with "libero SCRIPT:libero.tcl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					file delete -force proj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
new_project \
 | 
					new_project \
 | 
				
			||||||
    -name top \
 | 
					    -name example \
 | 
				
			||||||
    -location work \
 | 
					    -location proj \
 | 
				
			||||||
 | 
					    -block_mode 0 \
 | 
				
			||||||
 | 
					    -hdl "VERILOG" \
 | 
				
			||||||
    -family IGLOO2 \
 | 
					    -family IGLOO2 \
 | 
				
			||||||
    -die PA4MGL500 \
 | 
					    -die PA4MGL500 \
 | 
				
			||||||
    -package tq144 \
 | 
					    -package tq144 \
 | 
				
			||||||
    -speed -1 \
 | 
					    -speed -1
 | 
				
			||||||
    -hdl VERILOG
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# import_files -edif "[pwd]/netlist.edn"
 | 
					import_files -hdl_source {netlist.vm}
 | 
				
			||||||
 | 
					import_files -sdc {example.sdc}
 | 
				
			||||||
 | 
					import_files -io_pdc {example.pdc}
 | 
				
			||||||
 | 
					set_option -synth 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import_files -hdl_source "[pwd]/netlist.v"
 | 
					organize_tool_files -tool PLACEROUTE \
 | 
				
			||||||
set_root top
 | 
					    -file {proj/constraint/example.sdc} \
 | 
				
			||||||
 | 
					    -file {proj/constraint/io/example.pdc} \
 | 
				
			||||||
 | 
					    -input_type constraint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
save_project
 | 
					organize_tool_files -tool VERIFYTIMING \
 | 
				
			||||||
 | 
					    -file {proj/constraint/example.sdc} \
 | 
				
			||||||
 | 
					    -input_type constraint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
puts "**> SYNTHESIZE"
 | 
					configure_tool -name PLACEROUTE \
 | 
				
			||||||
run_tool -name {SYNTHESIZE}
 | 
					    -params TDPR:true \
 | 
				
			||||||
puts "<** SYNTHESIZE"
 | 
					    -params PDPR:false \
 | 
				
			||||||
 | 
					    -params EFFORT_LEVEL:false \
 | 
				
			||||||
 | 
					    -params REPAIR_MIN_DELAY:false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
puts "**> COMPILE"
 | 
					puts "**> COMPILE"
 | 
				
			||||||
run_tool -name {COMPILE}
 | 
					run_tool -name {COMPILE}
 | 
				
			||||||
| 
						 | 
					@ -28,6 +40,12 @@ puts "**> PLACEROUTE"
 | 
				
			||||||
run_tool -name {PLACEROUTE}
 | 
					run_tool -name {PLACEROUTE}
 | 
				
			||||||
puts "<** PLACEROUTE"
 | 
					puts "<** PLACEROUTE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					puts "**> VERIFYTIMING"
 | 
				
			||||||
 | 
					run_tool -name {VERIFYTIMING}
 | 
				
			||||||
 | 
					puts "<** VERIFYTIMING"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					save_project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# puts "**> export_bitstream"
 | 
					# puts "**> export_bitstream"
 | 
				
			||||||
# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
 | 
					# export_bitstream_file -trusted_facility_file 1 -trusted_facility_file_components {FABRIC}
 | 
				
			||||||
# puts "<** export_bitstream"
 | 
					# puts "<** export_bitstream"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
set -ex
 | 
					set -ex
 | 
				
			||||||
rm -rf work
 | 
					yosys -p 'synth_sf2 -top example -edif netlist.edn -vlog netlist.vm' example.v
 | 
				
			||||||
yosys example.ys
 | 
					 | 
				
			||||||
LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl
 | 
					LM_LICENSE_FILE=1702@`hostname` /opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero SCRIPT:libero.tcl
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -942,16 +942,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// simply return the corresponding RTLIL::SigSpec for an AST_CONSTANT node
 | 
						// simply return the corresponding RTLIL::SigSpec for an AST_CONSTANT node
 | 
				
			||||||
	case AST_CONSTANT:
 | 
						case AST_CONSTANT:
 | 
				
			||||||
 | 
						case AST_REALVALUE:
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (width_hint < 0)
 | 
								if (width_hint < 0)
 | 
				
			||||||
				detectSignWidth(width_hint, sign_hint);
 | 
									detectSignWidth(width_hint, sign_hint);
 | 
				
			||||||
 | 
					 | 
				
			||||||
			is_signed = sign_hint;
 | 
								is_signed = sign_hint;
 | 
				
			||||||
			return RTLIL::SigSpec(bitsAsConst());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case AST_REALVALUE:
 | 
								if (type == AST_CONSTANT)
 | 
				
			||||||
		{
 | 
									return RTLIL::SigSpec(bitsAsConst());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			RTLIL::SigSpec sig = realAsConst(width_hint);
 | 
								RTLIL::SigSpec sig = realAsConst(width_hint);
 | 
				
			||||||
			log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
 | 
								log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
 | 
				
			||||||
			return sig;
 | 
								return sig;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,8 @@ struct FsmOpt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			new_transition_table.swap(fsm_data.transition_table);
 | 
								new_transition_table.swap(fsm_data.transition_table);
 | 
				
			||||||
			new_state_table.swap(fsm_data.state_table);
 | 
								new_state_table.swap(fsm_data.state_table);
 | 
				
			||||||
			fsm_data.reset_state = old_to_new_state.at(fsm_data.reset_state);
 | 
								if (fsm_data.reset_state != -1)
 | 
				
			||||||
 | 
									fsm_data.reset_state = old_to_new_state.at(fsm_data.reset_state);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,9 +82,15 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (max_depth != 0)
 | 
								if (max_depth != 0)
 | 
				
			||||||
				proc_clean_case(cs, did_something, count, max_depth-1);
 | 
									proc_clean_case(cs, did_something, count, max_depth-1);
 | 
				
			||||||
 | 
								int size = 0;
 | 
				
			||||||
			for (auto cmp : cs->compare)
 | 
								for (auto cmp : cs->compare)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									size += cmp.size();
 | 
				
			||||||
				if (!cmp.is_fully_def())
 | 
									if (!cmp.is_fully_def())
 | 
				
			||||||
					all_fully_def = false;
 | 
										all_fully_def = false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (sw->signal.size() != size)
 | 
				
			||||||
 | 
									all_fully_def = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (all_fully_def)
 | 
							if (all_fully_def)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ module AL_MAP_LUT1 (
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
	parameter [1:0] INIT = 2'h0;
 | 
						parameter [1:0] INIT = 2'h0;
 | 
				
			||||||
	parameter EQN = "(A)";
 | 
						parameter EQN = "(A)";
 | 
				
			||||||
	assign Y = INIT >> A;
 | 
						assign o = INIT >> a;
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module AL_MAP_LUT2 (
 | 
					module AL_MAP_LUT2 (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OBJS += techlibs/sf2/synth_sf2.o
 | 
					OBJS += techlibs/sf2/synth_sf2.o
 | 
				
			||||||
 | 
					OBJS += techlibs/sf2/sf2_iobs.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
 | 
					$(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
 | 
				
			||||||
$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
 | 
					$(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,3 +73,24 @@ module CFG4 (
 | 
				
			||||||
	parameter [15:0] INIT = 16'h0;
 | 
						parameter [15:0] INIT = 16'h0;
 | 
				
			||||||
	assign Y = INIT >> {D, C, B, A};
 | 
						assign Y = INIT >> {D, C, B, A};
 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module CLKBUF (
 | 
				
			||||||
 | 
						input PAD,
 | 
				
			||||||
 | 
						output Y
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						assign Y = PAD;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module INBUF (
 | 
				
			||||||
 | 
						input PAD,
 | 
				
			||||||
 | 
						output Y
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						assign Y = PAD;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module OUTBUF (
 | 
				
			||||||
 | 
						input D,
 | 
				
			||||||
 | 
						output PAD
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						assign PAD = D;
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										130
									
								
								techlibs/sf2/sf2_iobs.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								techlibs/sf2/sf2_iobs.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,130 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  yosys -- Yosys Open SYnthesis Suite
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  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 "kernel/yosys.h"
 | 
				
			||||||
 | 
					#include "kernel/sigtools.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USING_YOSYS_NAMESPACE
 | 
				
			||||||
 | 
					PRIVATE_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Sf2IobsPass : public Pass {
 | 
				
			||||||
 | 
						Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
 | 
				
			||||||
 | 
						void help() YS_OVERRIDE
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    sf2_iobs [options] [selection]\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("Add SF2 I/O buffers to top module IOs as needed.\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							size_t argidx;
 | 
				
			||||||
 | 
							for (argidx = 1; argidx < args.size(); argidx++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// if (args[argidx] == "-singleton") {
 | 
				
			||||||
 | 
								// 	singleton_mode = true;
 | 
				
			||||||
 | 
								// 	continue;
 | 
				
			||||||
 | 
								// }
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							extra_args(args, argidx, design);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Module *module = design->top_module();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (module == nullptr)
 | 
				
			||||||
 | 
								log_cmd_error("No top module found.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SigMap sigmap(module);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pool<SigBit> clk_bits;
 | 
				
			||||||
 | 
							pool<SigBit> handled_io_bits;
 | 
				
			||||||
 | 
							dict<SigBit, SigBit> rewrite_bits;
 | 
				
			||||||
 | 
							vector<pair<Cell*, SigBit>> pad_bits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (auto cell : module->cells())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (cell->type == "\\SLE") {
 | 
				
			||||||
 | 
									for (auto bit : sigmap(cell->getPort("\\CLK")))
 | 
				
			||||||
 | 
										clk_bits.insert(bit);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (cell->type.in("\\INBUF", "\\OUTBUF", "\\CLKBUF")) {
 | 
				
			||||||
 | 
									for (auto bit : sigmap(cell->getPort("\\PAD")))
 | 
				
			||||||
 | 
										handled_io_bits.insert(bit);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (auto wire : vector<Wire*>(module->wires()))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (!wire->port_input && !wire->port_output)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (int index = 0; index < GetSize(wire); index++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									SigBit bit(wire, index);
 | 
				
			||||||
 | 
									SigBit canonical_bit = sigmap(bit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (handled_io_bits.count(canonical_bit))
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (wire->port_input && wire->port_output)
 | 
				
			||||||
 | 
										log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									IdString buf_type, buf_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (wire->port_output) {
 | 
				
			||||||
 | 
										buf_type = "\\OUTBUF";
 | 
				
			||||||
 | 
										buf_port = "\\D";
 | 
				
			||||||
 | 
									} else if (clk_bits.count(canonical_bit)) {
 | 
				
			||||||
 | 
										buf_type = "\\CLKBUF";
 | 
				
			||||||
 | 
										buf_port = "\\Y";
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										buf_type = "\\INBUF";
 | 
				
			||||||
 | 
										buf_port = "\\Y";
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									Cell *c = module->addCell(NEW_ID, buf_type);
 | 
				
			||||||
 | 
									SigBit new_bit = module->addWire(NEW_ID);
 | 
				
			||||||
 | 
									c->setPort(buf_port, new_bit);
 | 
				
			||||||
 | 
									pad_bits.push_back(make_pair(c, bit));
 | 
				
			||||||
 | 
									rewrite_bits[canonical_bit] = new_bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto rewrite_function = [&](SigSpec &s) {
 | 
				
			||||||
 | 
								for (auto &bit : s) {
 | 
				
			||||||
 | 
									SigBit canonical_bit = sigmap(bit);
 | 
				
			||||||
 | 
									if (rewrite_bits.count(canonical_bit))
 | 
				
			||||||
 | 
										bit = rewrite_bits.at(canonical_bit);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							module->rewrite_sigspecs(rewrite_function);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (auto &it : pad_bits)
 | 
				
			||||||
 | 
								it.first->setPort("\\PAD", it.second);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					} Sf2IobsPass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PRIVATE_NAMESPACE_END
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,10 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
		log("        write the design to the specified EDIF file. writing of an output file\n");
 | 
							log("        write the design to the specified EDIF file. writing of an output file\n");
 | 
				
			||||||
		log("        is omitted if this parameter is not specified.\n");
 | 
							log("        is omitted if this parameter is not specified.\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -vlog <file>\n");
 | 
				
			||||||
 | 
							log("        write the design to the specified Verilog file. writing of an output file\n");
 | 
				
			||||||
 | 
							log("        is omitted if this parameter is not specified.\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
		log("    -json <file>\n");
 | 
							log("    -json <file>\n");
 | 
				
			||||||
		log("        write the design to the specified JSON file. writing of an output file\n");
 | 
							log("        write the design to the specified JSON file. writing of an output file\n");
 | 
				
			||||||
		log("        is omitted if this parameter is not specified.\n");
 | 
							log("        is omitted if this parameter is not specified.\n");
 | 
				
			||||||
| 
						 | 
					@ -56,6 +60,9 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
		log("    -noflatten\n");
 | 
							log("    -noflatten\n");
 | 
				
			||||||
		log("        do not flatten design before synthesis\n");
 | 
							log("        do not flatten design before synthesis\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
 | 
							log("    -noiobs\n");
 | 
				
			||||||
 | 
							log("        run synthesis in \"block mode\", i.e. do not insert IO buffers\n");
 | 
				
			||||||
 | 
							log("\n");
 | 
				
			||||||
		log("    -retime\n");
 | 
							log("    -retime\n");
 | 
				
			||||||
		log("        run 'abc' with -dff option\n");
 | 
							log("        run 'abc' with -dff option\n");
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
| 
						 | 
					@ -65,16 +72,18 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
		log("\n");
 | 
							log("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	string top_opt, edif_file, json_file;
 | 
						string top_opt, edif_file, vlog_file, json_file;
 | 
				
			||||||
	bool flatten, retime;
 | 
						bool flatten, retime, iobs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void clear_flags() YS_OVERRIDE
 | 
						void clear_flags() YS_OVERRIDE
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		top_opt = "-auto-top";
 | 
							top_opt = "-auto-top";
 | 
				
			||||||
		edif_file = "";
 | 
							edif_file = "";
 | 
				
			||||||
 | 
							vlog_file = "";
 | 
				
			||||||
		json_file = "";
 | 
							json_file = "";
 | 
				
			||||||
		flatten = true;
 | 
							flatten = true;
 | 
				
			||||||
		retime = false;
 | 
							retime = false;
 | 
				
			||||||
 | 
							iobs = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
						void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
				
			||||||
| 
						 | 
					@ -93,6 +102,10 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
				edif_file = args[++argidx];
 | 
									edif_file = args[++argidx];
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (args[argidx] == "-vlog" && argidx+1 < args.size()) {
 | 
				
			||||||
 | 
									vlog_file = args[++argidx];
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (args[argidx] == "-json" && argidx+1 < args.size()) {
 | 
								if (args[argidx] == "-json" && argidx+1 < args.size()) {
 | 
				
			||||||
				json_file = args[++argidx];
 | 
									json_file = args[++argidx];
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
| 
						 | 
					@ -113,6 +126,10 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
				retime = true;
 | 
									retime = true;
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (args[argidx] == "-noiobs") {
 | 
				
			||||||
 | 
									iobs = false;
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		extra_args(args, argidx, design);
 | 
							extra_args(args, argidx, design);
 | 
				
			||||||
| 
						 | 
					@ -182,6 +199,13 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
			run("clean");
 | 
								run("clean");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (check_label("map_iobs"))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (iobs || help_mode)
 | 
				
			||||||
 | 
									run("sf2_iobs", "(unless -noiobs)");
 | 
				
			||||||
 | 
								run("clean");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (check_label("check"))
 | 
							if (check_label("check"))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			run("hierarchy -check");
 | 
								run("hierarchy -check");
 | 
				
			||||||
| 
						 | 
					@ -192,7 +216,13 @@ struct SynthSf2Pass : public ScriptPass
 | 
				
			||||||
		if (check_label("edif"))
 | 
							if (check_label("edif"))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (!edif_file.empty() || help_mode)
 | 
								if (!edif_file.empty() || help_mode)
 | 
				
			||||||
				run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
 | 
									run(stringf("write_edif -gndvccy %s", help_mode ? "<file-name>" : edif_file.c_str()));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (check_label("vlog"))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (!vlog_file.empty() || help_mode)
 | 
				
			||||||
 | 
									run(stringf("write_verilog %s", help_mode ? "<file-name>" : vlog_file.c_str()));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (check_label("json"))
 | 
							if (check_label("json"))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,22 +0,0 @@
 | 
				
			||||||
module misc1 (a,b,c,d,y);
 | 
					 | 
				
			||||||
input a, b,c,d;
 | 
					 | 
				
			||||||
output y;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
wire net1,net2,net3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
supply1 vdd;
 | 
					 | 
				
			||||||
supply0 vss;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// y = !((a+b+c).d)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pmos p1 (vdd,net1,a);
 | 
					 | 
				
			||||||
pmos p2 (net1,net2,b);
 | 
					 | 
				
			||||||
pmos p3 (net2,y,c);
 | 
					 | 
				
			||||||
pmos p4 (vdd,y,d);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nmos n1 (vss,net3,a);
 | 
					 | 
				
			||||||
nmos n2 (vss,net3,b);
 | 
					 | 
				
			||||||
nmos n3 (vss,net3,c);
 | 
					 | 
				
			||||||
nmos n4 (net3,y,d);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endmodule
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,22 +0,0 @@
 | 
				
			||||||
//-----------------------------------------------------
 | 
					 | 
				
			||||||
// Design Name : mux21_switch
 | 
					 | 
				
			||||||
// File Name   : mux21_switch.v
 | 
					 | 
				
			||||||
// Function    : 2:1 Mux using Switch Primitives
 | 
					 | 
				
			||||||
// Coder       : Deepak Kumar Tala
 | 
					 | 
				
			||||||
//-----------------------------------------------------
 | 
					 | 
				
			||||||
module mux21_switch (out, ctrl, in1, in2);
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
   output out;                    
 | 
					 | 
				
			||||||
   input  ctrl, in1, in2;         
 | 
					 | 
				
			||||||
   wire          w;            
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   supply1 power;             
 | 
					 | 
				
			||||||
   supply0 ground;      
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
   pmos N1 (w, power, ctrl);     
 | 
					 | 
				
			||||||
   nmos N2 (w, ground, ctrl);   
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
   cmos C1 (out, in1, w, ctrl);   
 | 
					 | 
				
			||||||
   cmos C2 (out, in2, ctrl, w);
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
endmodule
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,14 +0,0 @@
 | 
				
			||||||
module nand_switch(a,b,out);
 | 
					 | 
				
			||||||
input a,b;
 | 
					 | 
				
			||||||
output out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
supply0 vss;
 | 
					 | 
				
			||||||
supply1 vdd;
 | 
					 | 
				
			||||||
wire net1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pmos p1 (vdd,out,a);
 | 
					 | 
				
			||||||
pmos p2 (vdd,out,b);
 | 
					 | 
				
			||||||
nmos n1 (vss,net1,a);
 | 
					 | 
				
			||||||
nmos n2 (net1,out,b);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endmodule
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,11 +0,0 @@
 | 
				
			||||||
module t_gate_switch (L,R,nC,C);
 | 
					 | 
				
			||||||
 inout L;
 | 
					 | 
				
			||||||
 inout R;
 | 
					 | 
				
			||||||
 input nC;
 | 
					 | 
				
			||||||
 input C;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 //Syntax: keyword unique_name (drain. source, gate);
 | 
					 | 
				
			||||||
 pmos p1 (L,R,nC);
 | 
					 | 
				
			||||||
 nmos p2 (L,R,C);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endmodule
 | 
					 | 
				
			||||||
| 
						 | 
					@ -11,4 +11,4 @@ do
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
shift "$((OPTIND-1))"
 | 
					shift "$((OPTIND-1))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS="-e" *.v
 | 
					exec ${MAKE:-make} -f ../tools/autotest.mk $seed EXTRA_FLAGS+="-e" *.v
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										24
									
								
								tests/asicworld/xfirrtl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tests/asicworld/xfirrtl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					# This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures.
 | 
				
			||||||
 | 
					code_hdl_models_arbiter.v	error: reg rst; cannot be driven by primitives or continuous assignment.
 | 
				
			||||||
 | 
					code_hdl_models_clk_div_45.v	yosys issue: 2nd PMUXTREE pass yields: ERROR: Negative edge clock on FF clk_div_45.$procdff$49.
 | 
				
			||||||
 | 
					code_hdl_models_d_ff_gates.v	combinational loop
 | 
				
			||||||
 | 
					code_hdl_models_d_latch_gates.v	combinational loop
 | 
				
			||||||
 | 
					code_hdl_models_dff_async_reset.v	$adff
 | 
				
			||||||
 | 
					code_hdl_models_tff_async_reset.v	$adff
 | 
				
			||||||
 | 
					code_hdl_models_uart.v	$adff
 | 
				
			||||||
 | 
					code_specman_switch_fabric.v	subfield assignment (bits() <= ...)
 | 
				
			||||||
 | 
					code_tidbits_asyn_reset.v	$adff
 | 
				
			||||||
 | 
					code_tidbits_reg_seq_example.v	$adff
 | 
				
			||||||
 | 
					code_verilog_tutorial_always_example.v	empty module
 | 
				
			||||||
 | 
					code_verilog_tutorial_escape_id.v	make_id issues (name begins with a digit)
 | 
				
			||||||
 | 
					code_verilog_tutorial_explicit.v	firrtl backend bug (empty module)
 | 
				
			||||||
 | 
					code_verilog_tutorial_first_counter.v	error: reg rst; cannot be driven by primitives or continuous assignment.
 | 
				
			||||||
 | 
					code_verilog_tutorial_fsm_full.v	error: reg reset; cannot be driven by primitives or continuous assignment.
 | 
				
			||||||
 | 
					code_verilog_tutorial_if_else.v	empty module (everything is under 'always @ (posedge clk)')
 | 
				
			||||||
 | 
					[code_verilog_tutorial_n_out_primitive.v	empty module
 | 
				
			||||||
 | 
					code_verilog_tutorial_parallel_if.v	empty module (everything is under 'always @ (posedge clk)')
 | 
				
			||||||
 | 
					code_verilog_tutorial_simple_function.v	empty module (no hardware)
 | 
				
			||||||
 | 
					code_verilog_tutorial_simple_if.v	empty module (everything is under 'always @ (posedge clk)')
 | 
				
			||||||
 | 
					code_verilog_tutorial_task_global.v	empty module (everything is under 'always @ (posedge clk)')
 | 
				
			||||||
 | 
					code_verilog_tutorial_v2k_reg.v		empty module
 | 
				
			||||||
 | 
					code_verilog_tutorial_which_clock.v	 $adff
 | 
				
			||||||
							
								
								
									
										26
									
								
								tests/simple/xfirrtl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tests/simple/xfirrtl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					# This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures.
 | 
				
			||||||
 | 
					arraycells.v	inst id[0] of
 | 
				
			||||||
 | 
					dff_different_styles.v
 | 
				
			||||||
 | 
					generate.v	combinational loop
 | 
				
			||||||
 | 
					hierdefparam.v	inst id[0] of
 | 
				
			||||||
 | 
					i2c_master_tests.v   $adff
 | 
				
			||||||
 | 
					macros.v	drops modules
 | 
				
			||||||
 | 
					mem2reg.v	drops modules
 | 
				
			||||||
 | 
					mem_arst.v	$adff
 | 
				
			||||||
 | 
					memory.v	$adff
 | 
				
			||||||
 | 
					multiplier.v	inst id[0] of
 | 
				
			||||||
 | 
					muxtree.v	drops modules
 | 
				
			||||||
 | 
					omsp_dbg_uart.v	$adff
 | 
				
			||||||
 | 
					operators.v	$pow
 | 
				
			||||||
 | 
					paramods.v	subfield assignment (bits() <= ...)
 | 
				
			||||||
 | 
					partsel.v	drops modules
 | 
				
			||||||
 | 
					process.v	drops modules
 | 
				
			||||||
 | 
					realexpr.v	drops modules
 | 
				
			||||||
 | 
					scopes.v	original verilog issues ( -x where x isn't declared signed)
 | 
				
			||||||
 | 
					sincos.v	$adff
 | 
				
			||||||
 | 
					specify.v	no code (empty module generates error
 | 
				
			||||||
 | 
					subbytes.v	$adff
 | 
				
			||||||
 | 
					task_func.v	drops modules
 | 
				
			||||||
 | 
					values.v	combinational loop
 | 
				
			||||||
 | 
					vloghammer.v	combinational loop
 | 
				
			||||||
 | 
					wreduce.v	original verilog issues ( -x where x isn't declared signed)
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXTRA_FLAGS=
 | 
					# Don't bother defining default values for SEED and EXTRA_FLAGS.
 | 
				
			||||||
SEED=
 | 
					# Their "natural" default values should be sufficient,
 | 
				
			||||||
 | 
					#   and they may be overridden in the environment.
 | 
				
			||||||
ifneq ($(strip $(SEED)),)
 | 
					ifneq ($(strip $(SEED)),)
 | 
				
			||||||
SEEDOPT=-S$(SEED)
 | 
					SEEDOPT=-S$(SEED)
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,12 +17,18 @@ scriptfiles=""
 | 
				
			||||||
scriptopt=""
 | 
					scriptopt=""
 | 
				
			||||||
toolsdir="$(cd $(dirname $0); pwd)"
 | 
					toolsdir="$(cd $(dirname $0); pwd)"
 | 
				
			||||||
warn_iverilog_git=false
 | 
					warn_iverilog_git=false
 | 
				
			||||||
 | 
					# The following are used in verilog to firrtl regression tests.
 | 
				
			||||||
 | 
					# Typically these will be passed as environment variables:
 | 
				
			||||||
 | 
					#EXTRA_FLAGS="--firrtl2verilog 'java -cp /.../firrtl/utils/bin/firrtl.jar firrtl.Driver'"
 | 
				
			||||||
 | 
					# The tests are skipped if firrtl2verilog is the empty string (the default).
 | 
				
			||||||
 | 
					firrtl2verilog=""
 | 
				
			||||||
 | 
					xfirrtl="../xfirrtl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [ ! -f $toolsdir/cmp_tbdata -o $toolsdir/cmp_tbdata.c -nt $toolsdir/cmp_tbdata ]; then
 | 
					if [ ! -f $toolsdir/cmp_tbdata -o $toolsdir/cmp_tbdata.c -nt $toolsdir/cmp_tbdata ]; then
 | 
				
			||||||
	( set -ex; ${CC:-gcc} -Wall -o $toolsdir/cmp_tbdata $toolsdir/cmp_tbdata.c; ) || exit 1
 | 
						( set -ex; ${CC:-gcc} -Wall -o $toolsdir/cmp_tbdata $toolsdir/cmp_tbdata.c; ) || exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
while getopts xmGl:wkjvref:s:p:n:S:I: opt; do
 | 
					while getopts xmGl:wkjvref:s:p:n:S:I:-: opt; do
 | 
				
			||||||
	case "$opt" in
 | 
						case "$opt" in
 | 
				
			||||||
		x)
 | 
							x)
 | 
				
			||||||
			use_xsim=true ;;
 | 
								use_xsim=true ;;
 | 
				
			||||||
| 
						 | 
					@ -59,8 +65,24 @@ while getopts xmGl:wkjvref:s:p:n:S:I: opt; do
 | 
				
			||||||
			include_opts="$include_opts -I $OPTARG"
 | 
								include_opts="$include_opts -I $OPTARG"
 | 
				
			||||||
			xinclude_opts="$xinclude_opts -i $OPTARG"
 | 
								xinclude_opts="$xinclude_opts -i $OPTARG"
 | 
				
			||||||
			minclude_opts="$minclude_opts +incdir+$OPTARG" ;;
 | 
								minclude_opts="$minclude_opts +incdir+$OPTARG" ;;
 | 
				
			||||||
 | 
							-)
 | 
				
			||||||
 | 
								case "${OPTARG}" in
 | 
				
			||||||
 | 
								    xfirrtl)
 | 
				
			||||||
 | 
								    	xfirrtl="${!OPTIND}"
 | 
				
			||||||
 | 
									OPTIND=$(( $OPTIND + 1 ))
 | 
				
			||||||
 | 
									;;
 | 
				
			||||||
 | 
								    firrtl2verilog)
 | 
				
			||||||
 | 
								    	firrtl2verilog="${!OPTIND}"
 | 
				
			||||||
 | 
									OPTIND=$(( $OPTIND + 1 ))
 | 
				
			||||||
 | 
									;;
 | 
				
			||||||
 | 
								    *)
 | 
				
			||||||
 | 
								    	if [ "$OPTERR" == 1 ] && [ "${optspec:0:1}" != ":" ]; then
 | 
				
			||||||
 | 
									    echo "Unknown option --${OPTARG}" >&2
 | 
				
			||||||
 | 
									fi
 | 
				
			||||||
 | 
									;;
 | 
				
			||||||
 | 
								esac;;
 | 
				
			||||||
		*)
 | 
							*)
 | 
				
			||||||
			echo "Usage: $0 [-x|-m] [-G] [-w] [-k] [-j] [-v] [-r] [-e] [-l libs] [-f frontend] [-s script] [-p cmdstring] [-n iters] [-S seed] [-I incdir] verilog-files\n" >&2
 | 
								echo "Usage: $0 [-x|-m] [-G] [-w] [-k] [-j] [-v] [-r] [-e] [-l libs] [-f frontend] [-s script] [-p cmdstring] [-n iters] [-S seed] [-I incdir] [--xfirrtl FIRRTL test exclude file] [--firrtl2verilog command to generate verilog from firrtl] verilog-files\n" >&2
 | 
				
			||||||
			exit 1
 | 
								exit 1
 | 
				
			||||||
	esac
 | 
						esac
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
| 
						 | 
					@ -109,6 +131,8 @@ do
 | 
				
			||||||
		fn=$(basename $fn)
 | 
							fn=$(basename $fn)
 | 
				
			||||||
		bn=$(basename $bn)
 | 
							bn=$(basename $bn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rm -f ${bn}_ref.fir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.v
 | 
							egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if [ ! -f ../${bn}_tb.v ]; then
 | 
							if [ ! -f ../${bn}_tb.v ]; then
 | 
				
			||||||
| 
						 | 
					@ -148,6 +172,13 @@ do
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v
 | 
								test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v
 | 
				
			||||||
			test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v
 | 
								test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v
 | 
				
			||||||
 | 
								if [ -n "$firrtl2verilog" ]; then
 | 
				
			||||||
 | 
								    if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
 | 
				
			||||||
 | 
									"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v
 | 
				
			||||||
 | 
									$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v  -X verilog
 | 
				
			||||||
 | 
									test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v
 | 
				
			||||||
 | 
								    fi
 | 
				
			||||||
 | 
								fi
 | 
				
			||||||
		fi
 | 
							fi
 | 
				
			||||||
		touch ../${bn}.log
 | 
							touch ../${bn}.log
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -160,14 +191,18 @@ do
 | 
				
			||||||
		( set -ex; body; ) > ${bn}.err 2>&1
 | 
							( set -ex; body; ) > ${bn}.err 2>&1
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						did_firrtl=""
 | 
				
			||||||
 | 
						if [ -f ${bn}.out/${bn}_ref.fir ]; then
 | 
				
			||||||
 | 
						    did_firrtl="+FIRRTL "
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
	if [ -f ${bn}.log ]; then
 | 
						if [ -f ${bn}.log ]; then
 | 
				
			||||||
		mv ${bn}.err ${bn}.log
 | 
							mv ${bn}.err ${bn}.log
 | 
				
			||||||
		echo "${status_prefix}-> ok"
 | 
							echo "${status_prefix}${did_firrtl}-> ok"
 | 
				
			||||||
	elif [ -f ${bn}.skip ]; then
 | 
						elif [ -f ${bn}.skip ]; then
 | 
				
			||||||
		mv ${bn}.err ${bn}.skip
 | 
							mv ${bn}.err ${bn}.skip
 | 
				
			||||||
		echo "${status_prefix}-> skip"
 | 
							echo "${status_prefix}-> skip"
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		echo "${status_prefix}-> ERROR!"
 | 
							echo "${status_prefix}${did_firrtl}-> ERROR!"
 | 
				
			||||||
		if $warn_iverilog_git; then
 | 
							if $warn_iverilog_git; then
 | 
				
			||||||
			echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog."
 | 
								echo "Note: Make sure that 'iverilog' is an up-to-date git checkout of Icarus Verilog."
 | 
				
			||||||
		fi
 | 
							fi
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue