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 |