mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	metadata -> jny: migrated to the proper name for the pass
This commit is contained in:
		
							parent
							
								
									bdf14557ca
								
							
						
					
					
						commit
						0e20619189
					
				
					 3 changed files with 19 additions and 21 deletions
				
			
		
							
								
								
									
										2
									
								
								backends/jny/Makefile.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								backends/jny/Makefile.inc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
 | 
			
		||||
OBJS += backends/jny/jny.o
 | 
			
		||||
							
								
								
									
										326
									
								
								backends/jny/jny.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								backends/jny/jny.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,326 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Aki "lethalbit" Van Ness <aki@yosyshq.com> <aki@lethalbit.net>
 | 
			
		||||
 *
 | 
			
		||||
 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
 *  purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 *  copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "kernel/rtlil.h"
 | 
			
		||||
#include "kernel/register.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "kernel/cellaigs.h"
 | 
			
		||||
#include "kernel/log.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct JnyWriter
 | 
			
		||||
{
 | 
			
		||||
    private:
 | 
			
		||||
        std::ostream &f;
 | 
			
		||||
        bool _use_selection;
 | 
			
		||||
        std::unordered_map<std::string, std::vector<Cell*>> _cells{};
 | 
			
		||||
 | 
			
		||||
        // XXX(aki): this was pulled from the json backend, needs to be pulled
 | 
			
		||||
        // out possibly into some sort of utilities file, or integrated into rtlil.h
 | 
			
		||||
        // directly
 | 
			
		||||
        string get_string(string str)
 | 
			
		||||
        {
 | 
			
		||||
            string newstr = "\"";
 | 
			
		||||
            for (char c : str) {
 | 
			
		||||
                if (c == '\\')
 | 
			
		||||
                    newstr += c;
 | 
			
		||||
                newstr += c;
 | 
			
		||||
            }
 | 
			
		||||
            return newstr + "\"";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // XXX(aki): I know this is far from ideal but i'm out of spoons and cant focus so
 | 
			
		||||
        // it'll have to do for now,
 | 
			
		||||
        void coalesce_cells(Module* mod)
 | 
			
		||||
        {
 | 
			
		||||
            for (auto cell : mod->cells()) {
 | 
			
		||||
                const auto cell_type = get_string(RTLIL::unescape_id(cell->type));
 | 
			
		||||
 | 
			
		||||
                if (_cells.find(cell_type) == _cells.end())
 | 
			
		||||
                    _cells.emplace(cell_type, std::vector<Cell*>());
 | 
			
		||||
 | 
			
		||||
                _cells.at(cell_type).push_back(cell);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
    JnyWriter(std::ostream &f, bool use_selection) noexcept: f(f), _use_selection(use_selection) { }
 | 
			
		||||
 | 
			
		||||
    void write_metadata(Design *design)
 | 
			
		||||
    {
 | 
			
		||||
        log_assert(design != nullptr);
 | 
			
		||||
 | 
			
		||||
        design->sort();
 | 
			
		||||
 | 
			
		||||
        f << "{\n";
 | 
			
		||||
        f << stringf("  \"generator\": %s,\n", get_string(yosys_version_str).c_str());
 | 
			
		||||
        // XXX(aki): Replace this with a proper version info eventually:tm:
 | 
			
		||||
        f << "  \"version\": \"0.0.0\",\n";
 | 
			
		||||
        f << "  \"modules\": [\n";
 | 
			
		||||
 | 
			
		||||
        bool first{true};
 | 
			
		||||
        for (auto mod : _use_selection ? design->selected_modules() : design->modules()) {
 | 
			
		||||
            if (!first)
 | 
			
		||||
                f << ",\n";
 | 
			
		||||
            write_module(mod);
 | 
			
		||||
 | 
			
		||||
            f << "\n";
 | 
			
		||||
 | 
			
		||||
            first = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        f << "  ]\n";
 | 
			
		||||
        f << "}\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void write_module(Module* mod)
 | 
			
		||||
    {
 | 
			
		||||
        log_assert(mod != nullptr);
 | 
			
		||||
 | 
			
		||||
        coalesce_cells(mod);
 | 
			
		||||
 | 
			
		||||
        f << "    {\n";
 | 
			
		||||
        f << stringf("      \"name\": %s,\n", get_string(RTLIL::unescape_id(mod->name)).c_str());
 | 
			
		||||
        f << "      \"cell_sorts\": [\n";
 | 
			
		||||
 | 
			
		||||
        bool first_sort{true};
 | 
			
		||||
        for (auto& sort : _cells) {
 | 
			
		||||
            if (!first_sort)
 | 
			
		||||
                f << ",\n";
 | 
			
		||||
 | 
			
		||||
            write_cell_sort(sort);
 | 
			
		||||
 | 
			
		||||
            first_sort = false;
 | 
			
		||||
        }
 | 
			
		||||
        f << "\n";
 | 
			
		||||
 | 
			
		||||
        f << "      ],\n";
 | 
			
		||||
        f << "      \"connections\": [\n";
 | 
			
		||||
 | 
			
		||||
        f << "      ]\n";
 | 
			
		||||
        f << "    }";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void write_cell_sort(std::pair<const std::string, std::vector<Cell*>>& sort)
 | 
			
		||||
    {
 | 
			
		||||
        const auto port_cell = sort.second.front();
 | 
			
		||||
 | 
			
		||||
        f << "        {\n";
 | 
			
		||||
        f << stringf("          \"type\": %s,\n", sort.first.c_str());
 | 
			
		||||
        f << "          \"ports\": [\n";
 | 
			
		||||
 | 
			
		||||
        bool first_port{true};
 | 
			
		||||
        for (auto con : port_cell->connections()) {
 | 
			
		||||
            if (!first_port)
 | 
			
		||||
                f << ",\n";
 | 
			
		||||
 | 
			
		||||
            f << "          {\n";
 | 
			
		||||
            f << stringf("            \"name\": %s,\n", get_string(RTLIL::unescape_id(con.first)).c_str());
 | 
			
		||||
            f << "            \"direction\": \"";
 | 
			
		||||
            if (port_cell->input(con.first))
 | 
			
		||||
                f << "i";
 | 
			
		||||
            if (port_cell->input(con.first))
 | 
			
		||||
                f << "o";
 | 
			
		||||
            f << "\",\n";
 | 
			
		||||
            if (con.second.size() == 1)
 | 
			
		||||
                f << "            \"range\": [0, 0]\n";
 | 
			
		||||
            else
 | 
			
		||||
                f << stringf("            \"range\": [%d, %d]\n", con.second.size(), 0);
 | 
			
		||||
            f << "          }";
 | 
			
		||||
 | 
			
		||||
            first_port = false;
 | 
			
		||||
        }
 | 
			
		||||
        f << "\n";
 | 
			
		||||
 | 
			
		||||
        f << "          ],\n          \"cells\": [\n";
 | 
			
		||||
        bool first_cell{true};
 | 
			
		||||
        for (auto& cell : sort.second) {
 | 
			
		||||
            if (!first_cell)
 | 
			
		||||
                f << ",\n";
 | 
			
		||||
 | 
			
		||||
            write_cell(cell);
 | 
			
		||||
 | 
			
		||||
            first_cell = false;
 | 
			
		||||
        }
 | 
			
		||||
        f << "\n";
 | 
			
		||||
        f << "          ]\n";
 | 
			
		||||
        f << "        }";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void write_param_val(const Const& v)
 | 
			
		||||
    {
 | 
			
		||||
        if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) == RTLIL::ConstFlags::CONST_FLAG_STRING) {
 | 
			
		||||
            const auto str = v.decode_string();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            f << get_string(str);
 | 
			
		||||
        } else if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) == RTLIL::ConstFlags::CONST_FLAG_SIGNED) {
 | 
			
		||||
            f << stringf("\"%dsd %d\"", v.size(), v.as_int());
 | 
			
		||||
        } else if ((v.flags & RTLIL::ConstFlags::CONST_FLAG_REAL) == RTLIL::ConstFlags::CONST_FLAG_REAL) {
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            f << get_string(v.as_string());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void write_cell(Cell* cell)
 | 
			
		||||
    {
 | 
			
		||||
        log_assert(cell != nullptr);
 | 
			
		||||
 | 
			
		||||
        f << "            {\n";
 | 
			
		||||
        f << stringf("              \"name\": %s,\n", get_string(RTLIL::unescape_id(cell->name)).c_str());
 | 
			
		||||
        f << "              \"attributes\": {\n";
 | 
			
		||||
 | 
			
		||||
        bool first_attr{true};
 | 
			
		||||
        for (auto& attr : cell->attributes) {
 | 
			
		||||
            if (!first_attr)
 | 
			
		||||
                f << stringf(",\n");
 | 
			
		||||
            const auto attr_val = attr.second;
 | 
			
		||||
            if (!attr_val.empty()) {
 | 
			
		||||
                f << stringf("                %s: ", get_string(RTLIL::unescape_id(attr.first)).c_str());
 | 
			
		||||
                write_param_val(attr_val);
 | 
			
		||||
            } else {
 | 
			
		||||
                f << stringf("                %s: true", get_string(RTLIL::unescape_id(attr.first)).c_str());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            first_attr = false;
 | 
			
		||||
        }
 | 
			
		||||
        f << "\n";
 | 
			
		||||
 | 
			
		||||
        f << "              },\n";
 | 
			
		||||
        f << "              \"parameters\": {\n";
 | 
			
		||||
 | 
			
		||||
        bool first_param{true};
 | 
			
		||||
        for (auto& param : cell->parameters) {
 | 
			
		||||
            if (!first_param)
 | 
			
		||||
                f << stringf(",\n");
 | 
			
		||||
            const auto param_val = param.second;
 | 
			
		||||
            if (!param_val.empty()) {
 | 
			
		||||
                f << stringf("                %s: ", get_string(RTLIL::unescape_id(param.first)).c_str());
 | 
			
		||||
                write_param_val(param_val);
 | 
			
		||||
            } else {
 | 
			
		||||
                f << stringf("                %s: true", get_string(RTLIL::unescape_id(param.first)).c_str());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            first_param = false;
 | 
			
		||||
        }
 | 
			
		||||
        f << "\n";
 | 
			
		||||
 | 
			
		||||
        f << "              },\n";
 | 
			
		||||
        f << "            }";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct JnyBackend : public Backend {
 | 
			
		||||
    JnyBackend() : Backend("jny", "generate design metadata") { }
 | 
			
		||||
    void help() override
 | 
			
		||||
    {
 | 
			
		||||
        //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("    jny [options] [selection]\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("Write a JSON metadata for the current design\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
 | 
			
		||||
    {
 | 
			
		||||
        size_t argidx{1};
 | 
			
		||||
        extra_args(f, filename, args, argidx);
 | 
			
		||||
 | 
			
		||||
        log_header(design, "Executing jny backend.\n");
 | 
			
		||||
 | 
			
		||||
        JnyWriter jny_writer(*f, false);
 | 
			
		||||
        jny_writer.write_metadata(design);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
} JnyBackend;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct JnyPass : public Pass {
 | 
			
		||||
    JnyPass() : Pass("jny", "write design and metadata") { }
 | 
			
		||||
 | 
			
		||||
    void help() override
 | 
			
		||||
    {
 | 
			
		||||
        //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("    jny [options] [selection]\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("Write a JSON netlist metadata for the current design\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("    -o <filename>\n");
 | 
			
		||||
        log("        write to the specified file.\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
        log("See 'help write_jny' for a description of the JSON format used.\n");
 | 
			
		||||
        log("\n");
 | 
			
		||||
    }
 | 
			
		||||
    void execute(std::vector<std::string> args, RTLIL::Design *design) override
 | 
			
		||||
    {
 | 
			
		||||
        std::string filename{};
 | 
			
		||||
 | 
			
		||||
        size_t argidx;
 | 
			
		||||
        for (argidx = 1; argidx < args.size(); argidx++)
 | 
			
		||||
        {
 | 
			
		||||
            if (args[argidx] == "-o" && argidx+1 < args.size()) {
 | 
			
		||||
                filename = args[++argidx];
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
        std::ostream *f;
 | 
			
		||||
        std::stringstream buf;
 | 
			
		||||
 | 
			
		||||
        if (!filename.empty()) {
 | 
			
		||||
            rewrite_filename(filename);
 | 
			
		||||
            std::ofstream *ff = new std::ofstream;
 | 
			
		||||
            ff->open(filename.c_str(), std::ofstream::trunc);
 | 
			
		||||
            if (ff->fail()) {
 | 
			
		||||
                delete ff;
 | 
			
		||||
                log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
 | 
			
		||||
            }
 | 
			
		||||
            f = ff;
 | 
			
		||||
        } else {
 | 
			
		||||
            f = &buf;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        JnyWriter jny_writer(*f, false);
 | 
			
		||||
        jny_writer.write_metadata(design);
 | 
			
		||||
 | 
			
		||||
        if (!filename.empty()) {
 | 
			
		||||
            delete f;
 | 
			
		||||
        } else {
 | 
			
		||||
            log("%s", buf.str().c_str());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
} JnyPass;
 | 
			
		||||
 | 
			
		||||
PRIVATE_NAMESPACE_END
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue