diff options
Diffstat (limited to 'ghdl/ghdl.cc')
| -rw-r--r-- | ghdl/ghdl.cc | 580 | 
1 files changed, 0 insertions, 580 deletions
diff --git a/ghdl/ghdl.cc b/ghdl/ghdl.cc deleted file mode 100644 index e92e7e9..0000000 --- a/ghdl/ghdl.cc +++ /dev/null @@ -1,580 +0,0 @@ -/* -  Copyright (C) 2016  Tristan Gingold <tgingold@free.fr> - -  This program is free software: you can redistribute it and/or modify -  it under the terms of the GNU General Public License as published by -  the Free Software Foundation, either version 3 of the License, or -  (at your option) any later version. - -  This program is distributed in the hope that it will be useful, -  but WITHOUT ANY WARRANTY; without even the implied warranty of -  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -  GNU General Public License for more details. - -  You should have received a copy of the GNU General Public License -  along with this program.  If not, see <https://www.gnu.org/licenses/>. - -*/ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" -#include "kernel/log.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -USING_YOSYS_NAMESPACE - -#ifdef YOSYS_ENABLE_GHDL - -#include "ghdlsynth.h" - -using namespace GhdlSynth; - -static std::string to_str(Sname name) -{ -	std::string res; -	bool is_sys = false; - -	for (Sname pfx = name; is_valid(pfx); pfx = get_sname_prefix(pfx)) { -		switch (get_sname_kind(pfx)) { -		case Sname_Artificial: -			is_sys = true; -			// fallthrough -		case Sname_User: -			res = '.' + string(get_cstr(get_sname_suffix(pfx))) + res; -			break; -		case Sname_Version: -			res = '%' + stringf("%u", get_sname_version(pfx)) + res; -			break; -		} -	} -	res[0] = is_sys ? '$' : '\\'; -	return res; -} - -static RTLIL::SigSpec get_src(std::vector<RTLIL::Wire *> &net_map, Net n) -{ -	log_assert(n.id != 0); - -	//  Search if N is the output of a cell. -	Wire *res = n.id < net_map.size() ? net_map.at(n.id) : nullptr; -	if (res != nullptr) -		return res; - -	Instance inst = get_net_parent(n); -	switch(get_id(inst)) { -#define IN(N) get_src(net_map, get_input_net(inst, (N))) -	case Id_Signal: -	case Id_Isignal: -	case Id_Port: -		return IN(0); -	case Id_Uextend: -		{ -			RTLIL::SigSpec res = IN(0); -			res.extend_u0(get_width(n), false); -			return res; -		} -	case Id_Utrunc: -	case Id_Strunc: -		{ -			RTLIL::SigSpec res = IN(0); -			return res.extract(0, get_width(n)); -		} -	case Id_Const_UB32: -		return SigSpec(get_param_uns32(inst, 0), get_width(n)); -	case Id_Const_UL32: -		{ -		       std::vector<RTLIL::State> bits(get_width(n)); -		       unsigned int val01 = get_param_uns32(inst, 0); -		       unsigned int valzx = get_param_uns32(inst, 1); -		       for (unsigned int i = 0; i < get_width(n); i++) { -			switch(((val01 >> i)&1)+((valzx >> i)&1)*2) { -			    case 0: -				bits[i] = RTLIL::State::S0; -				break; -			    case 1: -				bits[i] = RTLIL::State::S1; -				break; -			    case 2: -				bits[i] = RTLIL::State::Sz; -				break; -			    case 3: -				bits[i] = RTLIL::State::Sx; -				break; -			} -		       } -		       return RTLIL::SigSpec(RTLIL::Const(bits)); -		} -	case Id_Extract: -		{ -			RTLIL::SigSpec res = IN(0); -			return res.extract(get_param_uns32(inst, 0), get_width(n)); -		} -        case Id_Insert: -		{ -			int pos = get_param_uns32(inst, 0); -			RTLIL::SigSpec in0 = IN(0); -			int size0 = in0.size(); -			RTLIL::SigSpec in1 = IN(1); -			int size1 = in1.size(); -			RTLIL::SigSpec res; - -			for (int i = 0; i < size0; i++) { -				 res.append((i >= pos && i < pos + size1) ? -					    in1[i - pos] : in0[i]); -			} -			return res; -		} -	case Id_Concat2: -	case Id_Concat3: -	case Id_Concat4: -	       { -			RTLIL::SigSpec res; -			unsigned nbr_in = get_nbr_inputs(get_module(inst)); -			//  ConcatN means { I0; I1; .. IN}, but append() adds -			//  bits to the MSB side. -			for (unsigned i = nbr_in; i > 0; i--) -				res.append(IN(i - 1)); -			return res; -	       } -	case Id_Concatn: -	       { -			RTLIL::SigSpec res; -			unsigned nbr_in = get_param_uns32(inst, 0); -			//  ConcatN means { I0; I1; .. IN}, but append() adds -			//  bits to the MSB side. -			for (unsigned i = nbr_in; i > 0; i--) -				res.append(IN(i - 1)); -			return res; -	       } -	default: -		log_cmd_error("wire not found for %s\n", to_str(get_module_name(get_module(inst))).c_str()); -		break; -	} -	return SigSpec(); -} - -static bool is_set(std::vector<RTLIL::Wire *> &net_map, Net n) -{ -	//  If not in the map, then certainly not present. -	if (n.id >= net_map.size()) -		return false; - -	Wire *res = net_map[n.id]; -	return (res != nullptr); -} - -static void set_src(std::vector<RTLIL::Wire *> &net_map, Net n, Wire *wire) -{ -	if (n.id >= net_map.size()) -		net_map.resize(n.id + 1, nullptr); -	log_assert(net_map[n.id] == nullptr); -	net_map[n.id] = wire; -} - -static void import_module(RTLIL::Design *design, GhdlSynth::Module m) -{ -	std::string module_name = to_str(get_module_name(m)); - -	if (design->has(module_name)) { -		log_cmd_error("Re-definition of module `%s'.\n", module_name.c_str()); -		return; -	} - -	RTLIL::Module *module = new RTLIL::Module; -	module->name = module_name; -	design->add(module); - -	log("Importing module %s.\n", RTLIL::id2cstr(module->name)); - -	//  TODO: support submodules -	if (is_valid(get_first_sub_module(m))) { -		log_cmd_error("Unsupported: submodules in `%s'.\n", module_name.c_str()); -		return; -	} - -	Instance self_inst = get_self_instance (m); -	if (!is_valid(self_inst)) { // blackbox -		module->set_bool_attribute("\\blackbox"); - -        Port_Idx nbr_inputs = get_nbr_inputs(m); -        for (Port_Idx idx = 0; idx < nbr_inputs; idx++) { -            RTLIL::Wire *wire = module->addWire( -                    to_str(get_input_name(m, idx)), -                    get_input_width(m, idx)); -            wire->port_input = true; -        } -        Port_Idx nbr_outputs = get_nbr_outputs(m); -        for (Port_Idx idx = 0; idx < nbr_outputs; idx++) { -            RTLIL::Wire *wire = module->addWire( -                    to_str(get_output_name(m, idx)), -                    get_output_width(m, idx)); -            wire->port_output = true; -        } -        module->fixup_ports(); -		return; -    } - -	//  Create input ports. -	//  They correspond to ouputs of the self instance. -	std::vector<RTLIL::Wire *> net_map; -	Port_Idx nbr_inputs = get_nbr_inputs(m); -	for (Port_Idx idx = 0; idx < nbr_inputs; idx++) { -		Net port = get_output(self_inst, idx); - -		RTLIL::Wire *wire = module->addWire(to_str(get_input_name(m, idx))); -		wire->port_id = idx + 1; -		wire->port_input = true; -		wire->width = get_width(port); -		set_src(net_map, port, wire); -	} -	//  Create output ports -	Port_Idx nbr_outputs = get_nbr_outputs(m); -	for (Port_Idx idx = 0; idx < nbr_outputs; idx++) { -		Net output_out = get_input_net(self_inst, idx); - -		//  Create wire -		RTLIL::Wire *wire = module->addWire(to_str(get_output_name(m, idx))); -		wire->port_id = nbr_inputs + idx + 1; -		wire->port_output = true; -		wire->width = get_width(output_out); -		set_src(net_map, output_out, wire); - -		if (0) { -		//  If the driver for this output drives only this output, -		//  reuse this wire. -		Instance output_inst = get_net_parent(output_out); -		log_assert(get_id(get_module(output_inst)) == Id_Output); -		Net output_drv = get_input_net(output_inst, 0); -		if (has_one_connection (output_drv)) -			set_src(net_map, output_drv, wire); -		} -	} - -	//  Create wires for outputs of (real) cells. -	for (Instance inst = get_first_instance(m); -	     is_valid(inst); -	     inst = get_next_instance(inst)) { -		GhdlSynth::Module im = get_module(inst); -		Module_Id id = get_id(im); -		switch (id) { -		case Id_And: -                case Id_Or: -                case Id_Xor: -		case Id_Nand: -                case Id_Nor: -                case Id_Xnor: -		case Id_Add: -		case Id_Sub: -		case Id_Mux2: -		case Id_Mux4: -		case Id_Dff: -		case Id_Adff: -		case Id_Idff: -		case Id_Eq: -                case Id_Ne: -                case Id_Ult: -                case Id_Ule: -                case Id_Ugt: -                case Id_Uge: -                case Id_Slt: -                case Id_Sle: -                case Id_Sgt: -                case Id_Sge: -		case Id_Not: -                case Id_Red_Or: -                case Id_Red_And: -                case Id_Assert:  // No output -                case Id_Assume:  // No output -                case Id_User_None: -			for (Port_Idx idx = 0; idx < get_nbr_outputs(im); idx++) { -				Net o = get_output(inst, idx); -				//  The wire may have been created for an output -				if (!is_set(net_map, o)) { -					RTLIL::Wire *wire = -                                          module->addWire(NEW_ID, get_width(o)); -					set_src(net_map, o, wire); -				} -			} -			break; -		case Id_Signal: -		case Id_Isignal: -		case Id_Output: -		case Id_Port: -		case Id_Const_UB32: -		case Id_Const_UL32: -		case Id_Uextend: -		case Id_Utrunc: -		case Id_Strunc: -		case Id_Extract: -                case Id_Insert: -		case Id_Concat2: -		case Id_Concat3: -		case Id_Concat4: -		case Id_Concatn: -			//  Skip: these won't create cells. -			break; -                case Id_Edge: -                  	//  The cell is ignored. -                  	break; -		default: -			log_cmd_error("Unsupported(1): instance %s of %s.\n", -				      to_str(get_instance_name(inst)).c_str(), -				      to_str(get_module_name(get_module(inst))).c_str()); -			return; -		} -	} - -	//  Create cells and connect. -	for (Instance inst = get_first_instance(m); -	     is_valid(inst); -	     inst = get_next_instance(inst)) { -		Module_Id id = get_id(inst); -		Sname iname = get_instance_name(inst); -		switch (id) { -#define IN(N) get_src(net_map, get_input_net(inst, (N))) -#define OUT(N) get_src(net_map, get_output(inst, (N))) -		case Id_And: -			module->addAnd(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Or: -			module->addOr(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Xor: -			module->addXor(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Nand: -                        { -                          SigSpec r = OUT(0); -                          RTLIL::Wire *w = module->addWire(NEW_ID, r.size()); -                          module->addAnd(NEW_ID, IN(0), IN(1), w); -                          module->addNot(to_str(iname), w, r); -                        } -			break; -		case Id_Nor: -                        { -                          SigSpec r = OUT(0); -                          RTLIL::Wire *w = module->addWire(NEW_ID, r.size()); -                          module->addOr(NEW_ID, IN(0), IN(1), w); -                          module->addNot(to_str(iname), w, r); -                        } -			break; -		case Id_Xnor: -			module->addXnor(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Add: -			module->addAdd(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Sub: -			module->addSub(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Not: -			module->addNot(to_str(iname), IN(0), OUT(0)); -			break; -		case Id_Eq: -			module->addEq(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Ne: -			module->addNe(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Ult: -			module->addLt(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Ule: -			module->addLe(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Ugt: -			module->addGt(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Uge: -			module->addGe(to_str(iname), IN(0), IN(1), OUT(0)); -			break; -		case Id_Slt: -			module->addLt(to_str(iname), IN(0), IN(1), OUT(0), true); -			break; -		case Id_Sle: -			module->addLe(to_str(iname), IN(0), IN(1), OUT(0), true); -			break; -		case Id_Sgt: -			module->addGt(to_str(iname), IN(0), IN(1), OUT(0), true); -			break; -		case Id_Sge: -			module->addGe(to_str(iname), IN(0), IN(1), OUT(0), true); -			break; -		case Id_Red_Or: -			module->addReduceOr(to_str(iname), IN(0), OUT(0)); -			break; -		case Id_Red_And: -			module->addReduceAnd(to_str(iname), IN(0), OUT(0)); -			break; -		case Id_Mux2: -			module->addMux(to_str(iname), IN(1), IN(2), IN(0), OUT(0)); -			break; -		case Id_Dff: -		case Id_Idff: -                        module->addDff(to_str(iname), IN(0), IN(1), OUT(0)); -			//  For idff, the initial value is set on the output -			//  wire. -			if (id == Id_Idff) { -				net_map[get_output(inst, 0).id]->attributes["\\init"] = IN(2).as_const(); -			} -			break; -		case Id_Adff: -            module->addAdff(to_str(iname), IN(0), IN(2), IN(1), OUT(0), IN(3).as_const()); -            break; -		case Id_Mux4: -			{ -				SigSpec Sel0 = IN(0).extract(0, 1); -				SigSpec Sel1 = IN(0).extract(1, 1); -				SigSpec in1 = IN(1); -				RTLIL::Wire *w0 = module->addWire(NEW_ID, in1.size()); -				RTLIL::Wire *w1 = module->addWire(NEW_ID, in1.size()); -				module->addMux(NEW_ID, in1, IN (2), Sel0, w0); -				module->addMux(NEW_ID, IN (3), IN (4), Sel0, w1); -				module->addMux(NEW_ID, w0, w1, Sel1, OUT (0)); -			} -			break; -                case Id_User_None: -                        { -                            RTLIL::Cell *cell = module->addCell( -                                    to_str(iname), -                                    to_str(get_module_name(get_module(inst)))); -                            GhdlSynth::Module submod = get_module(inst); -                            Port_Idx nbr_inputs = get_nbr_inputs(submod); -                            for (Port_Idx idx = 0; idx < nbr_inputs; idx++) { -                                cell->setPort(to_str(get_input_name(submod, idx)), IN(idx)); -                            } -                            Port_Idx nbr_outputs = get_nbr_outputs(submod); -                            for (Port_Idx idx = 0; idx < nbr_outputs; idx++) { -                                cell->setPort(to_str(get_output_name(submod, idx)), OUT(idx)); -                            } -                            break; -                        } -		case Id_Signal: -		case Id_Isignal: -			{ -				Net sig = get_input_net(inst, 0); -                                if (is_set(net_map, sig)) { -                                    Wire *w = net_map.at(sig.id); -                                    if (w) -                                        module->rename(w, to_str(iname)); -                                } -			} -			break; -		case Id_Output: -                case Id_Port: -			module->connect(OUT (0), IN (0)); -			break; -		case Id_Assert: -			module->addAssert(to_str(iname), IN(0), State::S1); -			break; -		case Id_Assume: -			module->addAssume(to_str(iname), IN(0), State::S1); -			break; -		case Id_Const_UB32: -		case Id_Const_UL32: -		case Id_Uextend: -		case Id_Utrunc: -		case Id_Strunc: -		case Id_Extract: -                case Id_Insert: -		case Id_Concat2: -		case Id_Concat3: -		case Id_Concat4: -                case Id_Edge: -			break; -#undef IN -#undef OUT -		default: -			log_cmd_error("Unsupported(2): instance %s of %s.\n", -				      to_str(get_instance_name(inst)).c_str(), -				      to_str(get_module_name(get_module(inst))).c_str()); -			return; -		} -	} - -	//  Connect output drivers to output -	for (Port_Idx idx = 0; idx < nbr_outputs; idx++) { -		Net output_out = get_input_net(self_inst, idx); -		Instance output_inst = get_net_parent(output_out); -		log_assert(get_id(get_module(output_inst)) == Id_Output); -		Net output_drv = get_input_net(output_inst, 0); -		if (!has_one_connection (output_drv)) -			module->connect(get_src(net_map, output_out), get_src(net_map, output_drv)); -	} - -	module->fixup_ports(); -} - -static void import_netlist(RTLIL::Design *design, GhdlSynth::Module top) -{ -	for (GhdlSynth::Module m = get_first_sub_module (top); -	     is_valid(m); -	     m = get_next_sub_module (m)) { -		if (get_id (m) < Id_User_None) -			continue; -		import_module(design, m); -	} -} - -#endif /* YOSYS_ENABLE_GHDL */ - -YOSYS_NAMESPACE_BEGIN - -struct GhdlPass : public Pass { -	GhdlPass() : Pass("ghdl", "load VHDL designs using GHDL") { } -	virtual void help() -	{ -		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| -#if 0 -		log("\n"); -		log("    ghdl -a [OPTIONS] <vhdl-file>..\n"); -		log("\n"); -		log("Analyze the specified VHDL files.\n"); -		log("\n"); -#endif -		log("\n"); -		log("    ghdl [FILES... -e] UNIT\n"); -		log("\n"); -		log("Elaborate the design and import to Yosys\n"); -		log("\n"); -	} -#ifdef YOSYS_ENABLE_GHDL -	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) -	{ -		static bool initialized; -		log_header(design, "Executing GHDL.\n"); - -		//  Initialize the library. -		if (!initialized) { -			initialized = 1; -			libghdl_init (); -			ghdlsynth__init_for_ghdl_synth(); -		} - -		if (args.size() == 2 && args[1] == "--disp-config") { -			ghdlcomp__disp_config(); -		} -		else { -			int cmd_argc = args.size() - 1; -			const char **cmd_argv = new const char *[cmd_argc]; -			for (int i = 0; i < cmd_argc; i++) -				cmd_argv[i] = args[i + 1].c_str(); - -			GhdlSynth::Module top; -			top = ghdl_synth(cmd_argc, cmd_argv); -			if (!is_valid(top)) { -				log_cmd_error("vhdl import failed.\n"); -			} -			import_netlist(design, top); -		} -	} -#else /* YOSYS_ENABLE_GHDL */ -	virtual void execute(std::vector<std::string>, RTLIL::Design *) { -		log_cmd_error("This version of Yosys is built without GHDL support.\n"); -	} -#endif -} GhdlPass; - -YOSYS_NAMESPACE_END  | 
