diff options
Diffstat (limited to 'backends/cxxrtl/cxxrtl_backend.cc')
| -rw-r--r-- | backends/cxxrtl/cxxrtl_backend.cc | 181 | 
1 files changed, 91 insertions, 90 deletions
diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 052053c52..bd2666a78 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -171,11 +171,6 @@ struct Scheduler {  	}  }; -bool is_input_wire(const RTLIL::Wire *wire) -{ -	return wire->port_input && !wire->port_output; -} -  bool is_unary_cell(RTLIL::IdString type)  {  	return type.in( @@ -202,7 +197,7 @@ bool is_extending_cell(RTLIL::IdString type)  bool is_elidable_cell(RTLIL::IdString type)  {  	return is_unary_cell(type) || is_binary_cell(type) || type.in( -		ID($mux), ID($concat), ID($slice)); +		ID($mux), ID($concat), ID($slice), ID($pmux));  }  bool is_sync_ff_cell(RTLIL::IdString type) @@ -804,7 +799,7 @@ struct CxxrtlWorker {  					default:  						log_assert(false);  				} -			} else if (unbuffered_wires[chunk.wire] || is_input_wire(chunk.wire)) { +			} else if (unbuffered_wires[chunk.wire]) {  				f << mangle(chunk.wire);  			} else {  				f << mangle(chunk.wire) << (is_lhs ? ".next" : ".curr"); @@ -947,6 +942,21 @@ struct CxxrtlWorker {  			f << " : ";  			dump_sigspec_rhs(cell->getPort(ID::A));  			f << ")"; +		// Parallel (one-hot) muxes +		} else if (cell->type == ID($pmux)) { +			int width = cell->getParam(ID::WIDTH).as_int(); +			int s_width = cell->getParam(ID::S_WIDTH).as_int(); +			for (int part = 0; part < s_width; part++) { +				f << "("; +				dump_sigspec_rhs(cell->getPort(ID::S).extract(part)); +				f << " ? "; +				dump_sigspec_rhs(cell->getPort(ID::B).extract(part * width, width)); +				f << " : "; +			} +			dump_sigspec_rhs(cell->getPort(ID::A)); +			for (int part = 0; part < s_width; part++) { +				f << ")"; +			}  		// Concats  		} else if (cell->type == ID($concat)) {  			dump_sigspec_rhs(cell->getPort(ID::B)); @@ -1013,35 +1023,6 @@ struct CxxrtlWorker {  			f << " = ";  			dump_cell_elided(cell);  			f << ";\n"; -		// Parallel (one-hot) muxes -		} else if (cell->type == ID($pmux)) { -			int width = cell->getParam(ID::WIDTH).as_int(); -			int s_width = cell->getParam(ID::S_WIDTH).as_int(); -			bool first = true; -			for (int part = 0; part < s_width; part++) { -				f << (first ? indent : " else "); -				first = false; -				f << "if ("; -				dump_sigspec_rhs(cell->getPort(ID::S).extract(part)); -				f << ") {\n"; -				inc_indent(); -					f << indent; -					dump_sigspec_lhs(cell->getPort(ID::Y)); -					f << " = "; -					dump_sigspec_rhs(cell->getPort(ID::B).extract(part * width, width)); -					f << ";\n"; -				dec_indent(); -				f << indent << "}"; -			} -			f << " else {\n"; -			inc_indent(); -				f << indent; -				dump_sigspec_lhs(cell->getPort(ID::Y)); -				f << " = "; -				dump_sigspec_rhs(cell->getPort(ID::A)); -				f << ";\n"; -			dec_indent(); -			f << indent << "}\n";  		// Flip-flops  		} else if (is_ff_cell(cell->type)) {  			if (cell->hasPort(ID::CLK) && cell->getPort(ID::CLK).is_wire()) { @@ -1153,31 +1134,33 @@ struct CxxrtlWorker {  				f << indent << "if(" << valid_index_temp << ".valid) {\n";  				inc_indent();  					if (writable_memories[memory]) { -						std::string addr_temp = fresh_temporary(); -						f << indent << "const value<" << cell->getPort(ID::ADDR).size() << "> &" << addr_temp << " = "; -						dump_sigspec_rhs(cell->getPort(ID::ADDR)); -						f << ";\n";  						std::string lhs_temp = fresh_temporary();  						f << indent << "value<" << memory->width << "> " << lhs_temp << " = "  						            << mangle(memory) << "[" << valid_index_temp << ".index];\n";  						std::vector<const RTLIL::Cell*> memwr_cells(transparent_for[cell].begin(), transparent_for[cell].end()); -						std::sort(memwr_cells.begin(), memwr_cells.end(), -							[](const RTLIL::Cell *a, const RTLIL::Cell *b) { -								return a->getParam(ID::PRIORITY).as_int() < b->getParam(ID::PRIORITY).as_int(); -							}); -						for (auto memwr_cell : memwr_cells) { -							f << indent << "if (" << addr_temp << " == "; -							dump_sigspec_rhs(memwr_cell->getPort(ID::ADDR)); -							f << ") {\n"; -							inc_indent(); -								f << indent << lhs_temp << " = " << lhs_temp; -								f << ".update("; -								dump_sigspec_rhs(memwr_cell->getPort(ID::DATA)); -								f << ", "; -								dump_sigspec_rhs(memwr_cell->getPort(ID::EN)); -								f << ");\n"; -							dec_indent(); -							f << indent << "}\n"; +						if (!memwr_cells.empty()) { +							std::string addr_temp = fresh_temporary(); +							f << indent << "const value<" << cell->getPort(ID::ADDR).size() << "> &" << addr_temp << " = "; +							dump_sigspec_rhs(cell->getPort(ID::ADDR)); +							f << ";\n"; +							std::sort(memwr_cells.begin(), memwr_cells.end(), +								[](const RTLIL::Cell *a, const RTLIL::Cell *b) { +									return a->getParam(ID::PRIORITY).as_int() < b->getParam(ID::PRIORITY).as_int(); +								}); +							for (auto memwr_cell : memwr_cells) { +								f << indent << "if (" << addr_temp << " == "; +								dump_sigspec_rhs(memwr_cell->getPort(ID::ADDR)); +								f << ") {\n"; +								inc_indent(); +									f << indent << lhs_temp << " = " << lhs_temp; +									f << ".update("; +									dump_sigspec_rhs(memwr_cell->getPort(ID::DATA)); +									f << ", "; +									dump_sigspec_rhs(memwr_cell->getPort(ID::EN)); +									f << ");\n"; +								dec_indent(); +								f << indent << "}\n"; +							}  						}  						f << indent;  						dump_sigspec_lhs(cell->getPort(ID::DATA)); @@ -1440,12 +1423,11 @@ struct CxxrtlWorker {  		if (elided_wires.count(wire))  			return; -		if (unbuffered_wires[wire]) { -			if (localized_wires[wire] == is_local_context) { -				dump_attrs(wire); -				f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n"; -			} -		} else if (!is_local_context) { +		if (localized_wires[wire] && is_local_context) { +			dump_attrs(wire); +			f << indent << "value<" << wire->width << "> " << mangle(wire) << ";\n"; +		} +		if (!localized_wires[wire] && !is_local_context) {  			std::string width;  			if (wire->module->has_attribute(ID(cxxrtl_blackbox)) && wire->has_attribute(ID(cxxrtl_width))) {  				width = wire->get_string_attribute(ID(cxxrtl_width)); @@ -1454,14 +1436,21 @@ struct CxxrtlWorker {  			}  			dump_attrs(wire); -			f << indent << (is_input_wire(wire) ? "value" : "wire") << "<" << width << "> " << mangle(wire); +			f << indent; +			if (wire->port_input && wire->port_output) +				f << "/*inout*/ "; +			else if (wire->port_input) +				f << "/*input*/ "; +			else if (wire->port_output) +				f << "/*output*/ "; +			f << (unbuffered_wires[wire] ? "value" : "wire") << "<" << width << "> " << mangle(wire);  			if (wire->has_attribute(ID::init)) {  				f << " ";  				dump_const_init(wire->attributes.at(ID::init));  			}  			f << ";\n";  			if (edge_wires[wire]) { -				if (is_input_wire(wire)) { +				if (unbuffered_wires[wire]) {  					f << indent << "value<" << width << "> prev_" << mangle(wire);  					if (wire->has_attribute(ID::init)) {  						f << " "; @@ -1472,7 +1461,7 @@ struct CxxrtlWorker {  				for (auto edge_type : edge_types) {  					if (edge_type.first.wire == wire) {  						std::string prev, next; -						if (is_input_wire(wire)) { +						if (unbuffered_wires[wire]) {  							prev = "prev_" + mangle(edge_type.first.wire);  							next =           mangle(edge_type.first.wire);  						} else { @@ -1595,9 +1584,9 @@ struct CxxrtlWorker {  		inc_indent();  			f << indent << "bool changed = false;\n";  			for (auto wire : module->wires()) { -				if (elided_wires.count(wire) || unbuffered_wires.count(wire)) +				if (elided_wires.count(wire))  					continue; -				if (is_input_wire(wire)) { +				if (unbuffered_wires[wire]) {  					if (edge_wires[wire])  						f << indent << "prev_" << mangle(wire) << " = " << mangle(wire) << ";\n";  					continue; @@ -1634,41 +1623,49 @@ struct CxxrtlWorker {  			for (auto wire : module->wires()) {  				if (wire->name[0] != '\\')  					continue; +				if (module->get_bool_attribute(ID(cxxrtl_blackbox)) && (wire->port_id == 0)) +					continue;  				count_public_wires++;  				if (debug_const_wires.count(wire)) {  					// Wire tied to a constant  					f << indent << "static const value<" << wire->width << "> const_" << mangle(wire) << " = ";  					dump_const(debug_const_wires[wire]);  					f << ";\n"; -					f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(wire)); -					f << ", debug_item(const_" << mangle(wire) << "));\n"; +					f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); +					f << ", debug_item(const_" << mangle(wire) << ", "; +					f << wire->start_offset << "));\n";  					count_const_wires++;  				} else if (debug_alias_wires.count(wire)) {  					// Alias of a member wire -					f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(wire)); -					f << ", debug_item(debug_alias(), " << mangle(debug_alias_wires[wire]) << "));\n"; +					f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); +					f << ", debug_item(debug_alias(), " << mangle(debug_alias_wires[wire]) << ", "; +					f << wire->start_offset << "));\n";  					count_alias_wires++;  				} else if (!localized_wires.count(wire)) {  					// Member wire -					f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(wire)); -					f << ", debug_item(" << mangle(wire) << "));\n"; +					f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); +					f << ", debug_item(" << mangle(wire) << ", "; +					f << wire->start_offset << "));\n";  					count_member_wires++;  				} else {  					count_skipped_wires++;  				}  			} -			for (auto &memory_it : module->memories) { -				if (memory_it.first[0] != '\\') -					continue; -				f << indent << "items.emplace(path + " << escape_cxx_string(get_hdl_name(memory_it.second)); -				f << ", debug_item(" << mangle(memory_it.second) << "));\n"; -			} -			for (auto cell : module->cells()) { -				if (is_internal_cell(cell->type)) -					continue; -				const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; -				f << indent << mangle(cell) << access << "debug_info(items, "; -				f << "path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ");\n"; +			if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { +				for (auto &memory_it : module->memories) { +					if (memory_it.first[0] != '\\') +						continue; +					f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(memory_it.second)); +					f << ", debug_item(" << mangle(memory_it.second) << ", "; +					f << memory_it.second->start_offset << "));\n"; +				} +				for (auto cell : module->cells()) { +					if (is_internal_cell(cell->type)) +						continue; +					const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; +					f << indent << mangle(cell) << access << "debug_info(items, "; +					f << "path + " << escape_cxx_string(get_hdl_name(cell) + ' ') << ");\n"; +				}  			}  		dec_indent(); @@ -1848,7 +1845,8 @@ struct CxxrtlWorker {  				topo_design.edge(cell_module, module);  			}  		} -		log_assert(topo_design.sort()); +		bool no_loops = topo_design.sort(); +		log_assert(no_loops);  		modules.insert(modules.end(), topo_design.sorted.begin(), topo_design.sorted.end());  		if (split_intf) { @@ -1970,6 +1968,8 @@ struct CxxrtlWorker {  			if (module->get_bool_attribute(ID(cxxrtl_blackbox))) {  				for (auto port : module->ports) {  					RTLIL::Wire *wire = module->wire(port); +					if (wire->port_input && !wire->port_output) +						unbuffered_wires.insert(wire);  					if (wire->has_attribute(ID(cxxrtl_edge))) {  						RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)];  						if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire)) @@ -2158,13 +2158,14 @@ struct CxxrtlWorker {  			for (auto wire : module->wires()) {  				if (feedback_wires[wire]) continue; -				if (wire->port_id != 0) continue; -				if (wire->get_bool_attribute(ID::keep)) continue; +				if (wire->port_output && !module->get_bool_attribute(ID::top)) continue;  				if (wire->name.begins_with("$") && !unbuffer_internal) continue;  				if (wire->name.begins_with("\\") && !unbuffer_public) continue; -				if (edge_wires[wire]) continue;  				if (flow.wire_sync_defs.count(wire) > 0) continue;  				unbuffered_wires.insert(wire); +				if (edge_wires[wire]) continue; +				if (wire->get_bool_attribute(ID::keep)) continue; +				if (wire->port_input || wire->port_output) continue;  				if (wire->name.begins_with("$") && !localize_internal) continue;  				if (wire->name.begins_with("\\") && !localize_public) continue;  				localized_wires.insert(wire);  | 
