mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge pull request #1797 from epfl-vlsc/firrtl_backend_fileinfo
Keep file information when emitting firrtl
This commit is contained in:
		
						commit
						7a434cdd7b
					
				
					 1 changed files with 51 additions and 29 deletions
				
			
		|  | @ -42,6 +42,13 @@ 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
 | static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this is actually one greater than the maximum allowed shift width
 | ||||||
| 
 | 
 | ||||||
|  | std::string getFileinfo(const RTLIL::AttrObject *design_entity) | ||||||
|  | { | ||||||
|  | 	std::string src(design_entity->get_src_attribute()); | ||||||
|  | 	std::string fileinfo_str = src.empty() ? "" : "@[" + src + "]"; | ||||||
|  | 	return fileinfo_str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // 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) | ||||||
| { | { | ||||||
|  | @ -193,6 +200,7 @@ struct FirrtlWorker | ||||||
| 				log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine()); | 				log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine()); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		// We need a default constructor for the dict insert.
 | 		// We need a default constructor for the dict insert.
 | ||||||
| 		memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} | 		memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} | ||||||
| 
 | 
 | ||||||
|  | @ -329,7 +337,8 @@ struct FirrtlWorker | ||||||
| 			log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); | 			log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); | ||||||
| 			return; | 			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())); | 		std::string cellFileinfo = getFileinfo(cell); | ||||||
|  | 		wire_exprs.push_back(stringf("%s" "inst %s%s of %s %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), instanceOf.c_str(), cellFileinfo.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) { | ||||||
|  | @ -370,7 +379,7 @@ struct FirrtlWorker | ||||||
| 					//  as part of the coalesced subfield assignments for this wire.
 | 					//  as part of the coalesced subfield assignments for this wire.
 | ||||||
| 					register_reverse_wire_map(sourceExpr, *sinkSig); | 					register_reverse_wire_map(sourceExpr, *sinkSig); | ||||||
| 				} else { | 				} else { | ||||||
| 					wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str())); | 					wire_exprs.push_back(stringf("\n%s%s <= %s %s", indent.c_str(), sinkExpr.c_str(), sourceExpr.c_str(), cellFileinfo.c_str())); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -394,12 +403,15 @@ struct FirrtlWorker | ||||||
| 
 | 
 | ||||||
| 	void run() | 	void run() | ||||||
| 	{ | 	{ | ||||||
| 		f << stringf("  module %s:\n", make_id(module->name)); | 		std::string moduleFileinfo = getFileinfo(module); | ||||||
|  | 		f << stringf("  module %s: %s\n", make_id(module->name), moduleFileinfo.c_str()); | ||||||
| 		vector<string> port_decls, wire_decls, cell_exprs, wire_exprs; | 		vector<string> port_decls, wire_decls, cell_exprs, wire_exprs; | ||||||
| 
 | 
 | ||||||
| 		for (auto wire : module->wires()) | 		for (auto wire : module->wires()) | ||||||
| 		{ | 		{ | ||||||
| 			const auto wireName = make_id(wire->name); | 			const auto wireName = make_id(wire->name); | ||||||
|  | 			std::string wireFileinfo = getFileinfo(wire); | ||||||
|  | 
 | ||||||
| 			// If a wire has initial data, issue a warning since FIRRTL doesn't currently support it.
 | 			// If a wire has initial data, issue a warning since FIRRTL doesn't currently support it.
 | ||||||
| 			if (wire->attributes.count(ID::init)) { | 			if (wire->attributes.count(ID::init)) { | ||||||
| 				log_warning("Initial value (%s) for (%s.%s) not supported\n", | 				log_warning("Initial value (%s) for (%s.%s) not supported\n", | ||||||
|  | @ -410,12 +422,12 @@ struct FirrtlWorker | ||||||
| 			{ | 			{ | ||||||
| 				if (wire->port_input && wire->port_output) | 				if (wire->port_input && wire->port_output) | ||||||
| 					log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); | 					log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire)); | ||||||
| 				port_decls.push_back(stringf("    %s %s: UInt<%d>\n", wire->port_input ? "input" : "output", | 				port_decls.push_back(stringf("    %s %s: UInt<%d> %s\n", wire->port_input ? "input" : "output", | ||||||
| 						wireName, wire->width)); | 						wireName, wire->width, wireFileinfo.c_str())); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", wireName, wire->width)); | 				wire_decls.push_back(stringf("    wire %s: UInt<%d> %s\n", wireName, wire->width, wireFileinfo.c_str())); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -441,11 +453,12 @@ struct FirrtlWorker | ||||||
| 			string primop; | 			string primop; | ||||||
| 			bool always_uint = false; | 			bool always_uint = false; | ||||||
| 			string y_id = make_id(cell->name); | 			string y_id = make_id(cell->name); | ||||||
|  | 			std::string cellFileinfo = getFileinfo(cell); | ||||||
| 
 | 
 | ||||||
| 			if (cell->type.in(ID($not), ID($logic_not), ID($neg), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_bool), ID($reduce_xnor))) | 			if (cell->type.in(ID($not), ID($logic_not), ID($neg), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_bool), ID($reduce_xnor))) | ||||||
| 			{ | 			{ | ||||||
| 				string a_expr = make_expr(cell->getPort(ID::A)); | 				string a_expr = make_expr(cell->getPort(ID::A)); | ||||||
| 				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> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); | ||||||
| 
 | 
 | ||||||
| 				if (a_signed) { | 				if (a_signed) { | ||||||
| 					a_expr = "asSInt(" + a_expr + ")"; | 					a_expr = "asSInt(" + a_expr + ")"; | ||||||
|  | @ -485,7 +498,7 @@ struct FirrtlWorker | ||||||
| 				if ((firrtl_is_signed && !always_uint)) | 				if ((firrtl_is_signed && !always_uint)) | ||||||
| 					expr = stringf("asUInt(%s)", expr.c_str()); | 					expr = stringf("asUInt(%s)", expr.c_str()); | ||||||
| 
 | 
 | ||||||
| 				cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str())); | 				cell_exprs.push_back(stringf("    %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); | ||||||
| 				register_reverse_wire_map(y_id, cell->getPort(ID::Y)); | 				register_reverse_wire_map(y_id, cell->getPort(ID::Y)); | ||||||
| 
 | 
 | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -496,7 +509,8 @@ struct FirrtlWorker | ||||||
| 			{ | 			{ | ||||||
| 				string a_expr = make_expr(cell->getPort(ID::A)); | 				string a_expr = make_expr(cell->getPort(ID::A)); | ||||||
| 				string b_expr = make_expr(cell->getPort(ID::B)); | 				string b_expr = make_expr(cell->getPort(ID::B)); | ||||||
| 				wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), y_width)); | 				std::string cellFileinfo = getFileinfo(cell); | ||||||
|  | 				wire_decls.push_back(stringf("    wire %s: UInt<%d> %s\n", y_id.c_str(), y_width, cellFileinfo.c_str())); | ||||||
| 
 | 
 | ||||||
| 				if (a_signed) { | 				if (a_signed) { | ||||||
| 					a_expr = "asSInt(" + a_expr + ")"; | 					a_expr = "asSInt(" + a_expr + ")"; | ||||||
|  | @ -712,7 +726,7 @@ struct FirrtlWorker | ||||||
| 				if ((firrtl_is_signed && !always_uint)) | 				if ((firrtl_is_signed && !always_uint)) | ||||||
| 					expr = stringf("asUInt(%s)", expr.c_str()); | 					expr = stringf("asUInt(%s)", expr.c_str()); | ||||||
| 
 | 
 | ||||||
| 				cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str())); | 				cell_exprs.push_back(stringf("    %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); | ||||||
| 				register_reverse_wire_map(y_id, cell->getPort(ID::Y)); | 				register_reverse_wire_map(y_id, cell->getPort(ID::Y)); | ||||||
| 
 | 
 | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -724,11 +738,11 @@ struct FirrtlWorker | ||||||
| 				string a_expr = make_expr(cell->getPort(ID::A)); | 				string a_expr = make_expr(cell->getPort(ID::A)); | ||||||
| 				string b_expr = make_expr(cell->getPort(ID::B)); | 				string b_expr = make_expr(cell->getPort(ID::B)); | ||||||
| 				string s_expr = make_expr(cell->getPort(ID::S)); | 				string s_expr = make_expr(cell->getPort(ID::S)); | ||||||
| 				wire_decls.push_back(stringf("    wire %s: UInt<%d>\n", y_id.c_str(), width)); | 				wire_decls.push_back(stringf("    wire %s: UInt<%d> %s\n", y_id.c_str(), width, cellFileinfo.c_str())); | ||||||
| 
 | 
 | ||||||
| 				string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); | 				string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str()); | ||||||
| 
 | 
 | ||||||
| 				cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str())); | 				cell_exprs.push_back(stringf("    %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); | ||||||
| 				register_reverse_wire_map(y_id, cell->getPort(ID::Y)); | 				register_reverse_wire_map(y_id, cell->getPort(ID::Y)); | ||||||
| 
 | 
 | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -867,9 +881,9 @@ struct FirrtlWorker | ||||||
| 				string expr = make_expr(cell->getPort(ID::D)); | 				string expr = make_expr(cell->getPort(ID::D)); | ||||||
| 				string clk_expr = "asClock(" + make_expr(cell->getPort(ID::CLK)) + ")"; | 				string clk_expr = "asClock(" + make_expr(cell->getPort(ID::CLK)) + ")"; | ||||||
| 
 | 
 | ||||||
| 				wire_decls.push_back(stringf("    reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str())); | 				wire_decls.push_back(stringf("    reg %s: UInt<%d>, %s %s\n", y_id.c_str(), width, clk_expr.c_str(), cellFileinfo.c_str())); | ||||||
| 
 | 
 | ||||||
| 				cell_exprs.push_back(stringf("    %s <= %s\n", y_id.c_str(), expr.c_str())); | 				cell_exprs.push_back(stringf("    %s <= %s %s\n", y_id.c_str(), expr.c_str(), cellFileinfo.c_str())); | ||||||
| 				register_reverse_wire_map(y_id, cell->getPort(ID::Q)); | 				register_reverse_wire_map(y_id, cell->getPort(ID::Q)); | ||||||
| 
 | 
 | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -959,6 +973,7 @@ struct FirrtlWorker | ||||||
| 		for (auto wire : module->wires()) | 		for (auto wire : module->wires()) | ||||||
| 		{ | 		{ | ||||||
| 			string expr; | 			string expr; | ||||||
|  | 			std::string wireFileinfo = getFileinfo(wire); | ||||||
| 
 | 
 | ||||||
| 			if (wire->port_input) | 			if (wire->port_input) | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -1017,14 +1032,20 @@ struct FirrtlWorker | ||||||
| 
 | 
 | ||||||
| 			if (is_valid) { | 			if (is_valid) { | ||||||
| 				if (make_unconn_id) { | 				if (make_unconn_id) { | ||||||
| 					wire_decls.push_back(stringf("    wire %s: UInt<1>\n", unconn_id.c_str())); | 					wire_decls.push_back(stringf("    wire %s: UInt<1> %s\n", unconn_id.c_str(), wireFileinfo.c_str())); | ||||||
|  | 					// `invalid` is a firrtl construction for simulation so we will not
 | ||||||
|  | 					// tag it with a @[fileinfo] tag as it doesn't directly correspond to
 | ||||||
|  | 					// a specific line of verilog code.
 | ||||||
| 					wire_decls.push_back(stringf("    %s is invalid\n", unconn_id.c_str())); | 					wire_decls.push_back(stringf("    %s is invalid\n", unconn_id.c_str())); | ||||||
| 				} | 				} | ||||||
| 				wire_exprs.push_back(stringf("    %s <= %s\n", make_id(wire->name), expr.c_str())); | 				wire_exprs.push_back(stringf("    %s <= %s %s\n", make_id(wire->name), expr.c_str(), wireFileinfo.c_str())); | ||||||
| 			} else { | 			} else { | ||||||
| 				if (make_unconn_id) { | 				if (make_unconn_id) { | ||||||
| 					unconn_id.clear(); | 					unconn_id.clear(); | ||||||
| 				} | 				} | ||||||
|  | 				// `invalid` is a firrtl construction for simulation so we will not
 | ||||||
|  | 				// tag it with a @[fileinfo] tag as it doesn't directly correspond to
 | ||||||
|  | 				// a specific line of verilog code.
 | ||||||
| 				wire_decls.push_back(stringf("    %s is invalid\n", make_id(wire->name))); | 				wire_decls.push_back(stringf("    %s is invalid\n", make_id(wire->name))); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1123,7 +1144,8 @@ struct FirrtlBackend : public Backend { | ||||||
| 		if (top == nullptr) | 		if (top == nullptr) | ||||||
| 			top = last; | 			top = last; | ||||||
| 
 | 
 | ||||||
| 		*f << stringf("circuit %s:\n", make_id(top->name)); | 		std::string circuitFileinfo = getFileinfo(top); | ||||||
|  | 		*f << stringf("circuit %s: %s\n", make_id(top->name), circuitFileinfo.c_str()); | ||||||
| 
 | 
 | ||||||
| 		for (auto module : design->modules()) | 		for (auto module : design->modules()) | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue