mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	functional backend: add different types of input/output/state variables
This commit is contained in:
		
							parent
							
								
									79a1b691ea
								
							
						
					
					
						commit
						50047d25b3
					
				
					 5 changed files with 237 additions and 120 deletions
				
			
		|  | @ -150,8 +150,8 @@ template<class NodePrinter> struct CxxPrintVisitor : public Functional::Abstract | |||
| 	void arithmetic_shift_right(Node, Node a, Node b) override { print("{}.arithmetic_shift_right({})", a, b); } | ||||
| 	void mux(Node, Node a, Node b, Node s) override { print("{2}.any() ? {1} : {0}", a, b, s); } | ||||
| 	void constant(Node, RTLIL::Const const & value) override { print("{}", cxx_const(value)); } | ||||
| 	void input(Node, IdString name) override { print("input.{}", input_struct[name]); } | ||||
| 	void state(Node, IdString name) override { print("current_state.{}", state_struct[name]); } | ||||
| 	void input(Node, IdString name, IdString type) override { log_assert(type == ID($input)); print("input.{}", input_struct[name]); } | ||||
| 	void state(Node, IdString name, IdString type) override { log_assert(type == ID($state)); print("current_state.{}", state_struct[name]); } | ||||
| 	void memory_read(Node, Node mem, Node addr) override { print("{}.read({})", mem, addr); } | ||||
| 	void memory_write(Node, Node mem, Node addr, Node data) override { print("{}.write({}, {})", mem, addr, data); } | ||||
| }; | ||||
|  | @ -175,12 +175,12 @@ struct CxxModule { | |||
| 		output_struct("Outputs"), | ||||
| 		state_struct("State") | ||||
| 	{ | ||||
| 		for (auto [name, sort] : ir.inputs()) | ||||
| 			input_struct.insert(name, sort); | ||||
| 		for (auto [name, sort] : ir.outputs()) | ||||
| 			output_struct.insert(name, sort); | ||||
| 		for (auto [name, sort] : ir.state()) | ||||
| 			state_struct.insert(name, sort); | ||||
| 		for (auto input : ir.inputs()) | ||||
| 			input_struct.insert(input->name, input->sort); | ||||
| 		for (auto output : ir.outputs()) | ||||
| 			output_struct.insert(output->name, output->sort); | ||||
| 		for (auto state : ir.states()) | ||||
| 			state_struct.insert(state->name, state->sort); | ||||
| 		module_name = CxxScope<int>().unique_name(module->name); | ||||
| 	} | ||||
| 	void write_header(CxxWriter &f) { | ||||
|  | @ -197,19 +197,19 @@ struct CxxModule { | |||
| 	} | ||||
| 	void write_initial_def(CxxWriter &f) { | ||||
| 		f.print("void {0}::initialize({0}::State &state)\n{{\n", module_name); | ||||
| 		for (auto [name, sort] : ir.state()) { | ||||
| 			if (sort.is_signal()) | ||||
| 				f.print("\tstate.{} = {};\n", state_struct[name], cxx_const(ir.get_initial_state_signal(name))); | ||||
| 			else if (sort.is_memory()) { | ||||
| 		for (auto state : ir.states()) { | ||||
| 			if (state->sort.is_signal()) | ||||
| 				f.print("\tstate.{} = {};\n", state_struct[state->name], cxx_const(state->initial_value_signal())); | ||||
| 			else if (state->sort.is_memory()) { | ||||
| 				f.print("\t{{\n"); | ||||
| 				f.print("\t\tstd::array<Signal<{}>, {}> mem;\n", sort.data_width(), 1<<sort.addr_width()); | ||||
| 				const auto &contents = ir.get_initial_state_memory(name); | ||||
| 				f.print("\t\tstd::array<Signal<{}>, {}> mem;\n", state->sort.data_width(), 1<<state->sort.addr_width()); | ||||
| 				const auto &contents = state->initial_value_memory(); | ||||
| 				f.print("\t\tmem.fill({});\n", cxx_const(contents.default_value())); | ||||
| 				for(auto range : contents) | ||||
| 					for(auto addr = range.base(); addr < range.limit(); addr++) | ||||
| 						if(!equal_def(range[addr], contents.default_value())) | ||||
| 							f.print("\t\tmem[{}] = {};\n", addr, cxx_const(range[addr])); | ||||
| 				f.print("\t\tstate.{} = mem;\n", state_struct[name]); | ||||
| 				f.print("\t\tstate.{} = mem;\n", state_struct[state->name]); | ||||
| 				f.print("\t}}\n"); | ||||
| 			} | ||||
| 		} | ||||
|  | @ -229,10 +229,10 @@ struct CxxModule { | |||
| 			node.visit(printVisitor); | ||||
| 			f.print(";\n"); | ||||
| 		} | ||||
| 		for (auto [name, sort] : ir.state()) | ||||
| 			f.print("\tnext_state.{} = {};\n", state_struct[name], node_name(ir.get_state_next_node(name))); | ||||
| 		for (auto [name, sort] : ir.outputs()) | ||||
| 			f.print("\toutput.{} = {};\n", output_struct[name], node_name(ir.get_output_node(name))); | ||||
| 		for (auto state : ir.states()) | ||||
| 			f.print("\tnext_state.{} = {};\n", state_struct[state->name], node_name(state->next_value())); | ||||
| 		for (auto output : ir.outputs()) | ||||
| 			f.print("\toutput.{} = {};\n", output_struct[output->name], node_name(output->value())); | ||||
| 		f.print("}}\n\n"); | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
|  | @ -178,8 +178,8 @@ struct SmtPrintVisitor : public Functional::AbstractVisitor<SExpr> { | |||
| 	SExpr memory_read(Node, Node mem, Node addr) override { return list("select", n(mem), n(addr)); } | ||||
| 	SExpr memory_write(Node, Node mem, Node addr, Node data) override { return list("store", n(mem), n(addr), n(data)); } | ||||
| 
 | ||||
| 	SExpr input(Node, IdString name) override { return input_struct.access("inputs", name); } | ||||
| 	SExpr state(Node, IdString name) override { return state_struct.access("state", name); } | ||||
| 	SExpr input(Node, IdString name, IdString type) override { log_assert(type == ID($input)); return input_struct.access("inputs", name); } | ||||
| 	SExpr state(Node, IdString name, IdString type) override { log_assert(type == ID($state)); return state_struct.access("state", name); } | ||||
| }; | ||||
| 
 | ||||
| struct SmtModule { | ||||
|  | @ -200,12 +200,12 @@ struct SmtModule { | |||
| 		, state_struct(scope.unique_name(module->name.str() + "_State"), scope) | ||||
| 	{ | ||||
| 		scope.reserve(name + "-initial"); | ||||
| 		for (const auto &input : ir.inputs()) | ||||
| 			input_struct.insert(input.first, input.second); | ||||
| 		for (const auto &output : ir.outputs()) | ||||
| 			output_struct.insert(output.first, output.second); | ||||
| 		for (const auto &state : ir.state()) | ||||
| 			state_struct.insert(state.first, state.second); | ||||
| 		for (auto input : ir.inputs()) | ||||
| 			input_struct.insert(input->name, input->sort); | ||||
| 		for (auto output : ir.outputs()) | ||||
| 			output_struct.insert(output->name, output->sort); | ||||
| 		for (auto state : ir.states()) | ||||
| 			state_struct.insert(state->name, state->sort); | ||||
| 	} | ||||
| 
 | ||||
| 	void write_eval(SExprWriter &w) | ||||
|  | @ -232,8 +232,8 @@ struct SmtModule { | |||
| 				w.comment(SmtSort(n.sort()).to_sexpr().to_string(), true); | ||||
| 			} | ||||
| 		w.open(list("pair")); | ||||
| 		output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.get_output_node(name)); }); | ||||
| 		state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.get_state_next_node(name)); }); | ||||
| 		output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.output(name).value()); }); | ||||
| 		state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.state(name).next_value()); }); | ||||
| 		w.pop(); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -241,14 +241,14 @@ struct SmtModule { | |||
| 	{ | ||||
| 		std::string initial = name + "-initial"; | ||||
| 		w << list("declare-const", initial, state_struct.name); | ||||
| 		for (const auto &[name, sort] : ir.state()) { | ||||
| 			if(sort.is_signal()) | ||||
| 				w << list("assert", list("=", state_struct.access(initial, name), smt_const(ir.get_initial_state_signal(name)))); | ||||
| 			else if(sort.is_memory()) { | ||||
| 				auto contents = ir.get_initial_state_memory(name); | ||||
| 				for(int i = 0; i < 1<<sort.addr_width(); i++) { | ||||
| 					auto addr = smt_const(RTLIL::Const(i, sort.addr_width())); | ||||
| 					w << list("assert", list("=", list("select", state_struct.access(initial, name), addr), smt_const(contents[i]))); | ||||
| 		for (auto state : ir.states()) { | ||||
| 			if(state->sort.is_signal()) | ||||
| 				w << list("assert", list("=", state_struct.access(initial, state->name), smt_const(state->initial_value_signal()))); | ||||
| 			else if(state->sort.is_memory()) { | ||||
| 				const auto &contents = state->initial_value_memory(); | ||||
| 				for(int i = 0; i < 1<<state->sort.addr_width(); i++) { | ||||
| 					auto addr = smt_const(RTLIL::Const(i, state->sort.addr_width())); | ||||
| 					w << list("assert", list("=", list("select", state_struct.access(initial, state->name), addr), smt_const(contents[i]))); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -142,10 +142,10 @@ struct FunctionalTestGeneric : public Pass | |||
| 			auto fir = Functional::IR::from_module(module); | ||||
| 			for(auto node : fir) | ||||
| 				std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n"; | ||||
| 			for(auto [name, sort] : fir.outputs()) | ||||
| 				std::cout << "output " << RTLIL::unescape_id(name) << " = " << RTLIL::unescape_id(fir.get_output_node(name).name()) << "\n"; | ||||
| 			for(auto [name, sort] : fir.state()) | ||||
| 				std::cout << "state " << RTLIL::unescape_id(name) << " = " << RTLIL::unescape_id(fir.get_state_next_node(name).name()) << "\n"; | ||||
| 			for(auto output : fir.all_outputs()) | ||||
| 				std::cout << RTLIL::unescape_id(output->type) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n"; | ||||
| 			for(auto state : fir.all_states()) | ||||
| 				std::cout << RTLIL::unescape_id(state->type) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n"; | ||||
| 		} | ||||
| 	} | ||||
| } FunctionalCxxBackend; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue