Added "add" command (only wires for now)
[yosys.git] / passes / cmds / add.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/register.h"
21 #include "kernel/rtlil.h"
22 #include "kernel/log.h"
23
24 static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global)
25 {
26 name = RTLIL::escape_id(name);
27
28 if (module->count_id(name) != 0)
29 {
30 RTLIL::Wire *wire = NULL;
31
32 if (module->wires.count(name) > 0)
33 wire = module->wires.at(name);
34
35 if (wire != NULL && wire->width != width)
36 wire = NULL;
37
38 if (wire != NULL && wire->port_input != flag_input)
39 wire = NULL;
40
41 if (wire != NULL && wire->port_output != flag_output)
42 wire = NULL;
43
44 if (wire == NULL)
45 log_cmd_error("Found incompatible object with same name in module %s!\n", module->name.c_str());
46 log("Skipping module %s as it already has such an object.\n", module->name.c_str());
47 return;
48 }
49
50 RTLIL::Wire *wire = new RTLIL::Wire;
51 wire->name = name;
52 wire->width = width;
53 wire->port_input = flag_input;
54 wire->port_output = flag_output;
55 module->add(wire);
56
57 if (flag_input || flag_output) {
58 wire->port_id = module->wires.size();
59 module->fixup_ports();
60 }
61
62 log("Added wire %s to module %s.\n", name.c_str(), module->name.c_str());
63
64 if (!flag_global)
65 return;
66
67 for (auto &it : module->cells)
68 {
69 if (design->modules.count(it.second->type) == 0)
70 continue;
71
72 RTLIL::Module *mod = design->modules.at(it.second->type);
73 if (!design->selected_whole_module(mod->name))
74 continue;
75 if (mod->get_bool_attribute("\\placeholder"))
76 continue;
77 if (it.second->connections.count(name) > 0)
78 continue;
79
80 it.second->connections[name] = wire;
81 log("Added connection %s to cell %s.%s (%s).\n", name.c_str(), module->name.c_str(), it.first.c_str(), it.second->type.c_str());
82 }
83 }
84
85 struct AddPass : public Pass {
86 AddPass() : Pass("add", "add objects to the design") { }
87 virtual void help()
88 {
89 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
90 log("\n");
91 log(" add <command> [selection]\n");
92 log("\n");
93 log("This command adds objects to the design. It operates on all fully selected\n");
94 log("modules. So e.g. 'add -wire foo' will add a wire foo to all selected modules.\n");
95 log("\n");
96 log("\n");
97 log(" add {-wire|-input|-inout|-output} <name> <width> [selection]\n");
98 log("\n");
99 log("Add a wire (input, inout, output port) with the given name and width. The\n");
100 log("command will fail if the object exists already and has different properties\n");
101 log("than the object to be created.\n");
102 log("\n");
103 log("\n");
104 log(" add -global_input <name> <width> [selection]\n");
105 log("\n");
106 log("Like 'add -input', but also connect the signal between instances of the\n");
107 log("selected modules.\n");
108 log("\n");
109 }
110 virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
111 {
112 std::string command;
113 std::string arg_name;
114 bool arg_flag_input = false;
115 bool arg_flag_output = false;
116 bool arg_flag_global = false;
117 int arg_width = 0;
118
119 size_t argidx;
120 for (argidx = 1; argidx < args.size(); argidx++)
121 {
122 std::string arg = args[argidx];
123 if (arg == "-wire" || arg == "-input" || arg == "-inout" || arg == "-output" || arg == "-global_input") {
124 if (argidx+2 >= args.size())
125 break;
126 command = "wire";
127 if (arg == "-input" || arg == "-inout" || arg == "-global_input")
128 arg_flag_input = true;
129 if (arg == "-output" || arg == "-inout")
130 arg_flag_output = true;
131 if (arg == "-global_input")
132 arg_flag_global = true;
133 arg_name = args[++argidx];
134 arg_width = atoi(args[++argidx].c_str());
135 continue;
136 }
137 break;
138 }
139 extra_args(args, argidx, design);
140
141 for (auto &mod : design->modules)
142 {
143 RTLIL::Module *module = mod.second;
144 if (!design->selected_whole_module(module->name))
145 continue;
146 if (module->get_bool_attribute("\\placeholder"))
147 continue;
148
149 if (command == "wire")
150 add_wire(design, module, arg_name, arg_width, arg_flag_input, arg_flag_output, arg_flag_global);
151 }
152 }
153 } AddPass;
154