Merge pull request #7 from YosysHQ/master
[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/yosys.h"
21
22 USING_YOSYS_NAMESPACE
23 PRIVATE_NAMESPACE_BEGIN
24
25 static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string name, int width, bool flag_input, bool flag_output, bool flag_global)
26 {
27 RTLIL::Wire *wire = NULL;
28 name = RTLIL::escape_id(name);
29
30 if (module->count_id(name) != 0)
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
47 log("Module %s already has such an object.\n", module->name.c_str());
48 }
49 else
50 {
51 wire = module->addWire(name, width);
52 wire->port_input = flag_input;
53 wire->port_output = flag_output;
54
55 if (flag_input || flag_output) {
56 wire->port_id = module->wires_.size();
57 module->fixup_ports();
58 }
59
60 log("Added wire %s to module %s.\n", name.c_str(), module->name.c_str());
61 }
62
63 if (!flag_global)
64 return;
65
66 for (auto &it : module->cells_)
67 {
68 if (design->modules_.count(it.second->type) == 0)
69 continue;
70
71 RTLIL::Module *mod = design->modules_.at(it.second->type);
72 if (!design->selected_whole_module(mod->name))
73 continue;
74 if (mod->get_blackbox_attribute())
75 continue;
76 if (it.second->hasPort(name))
77 continue;
78
79 it.second->setPort(name, wire);
80 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());
81 }
82 }
83
84 struct AddPass : public Pass {
85 AddPass() : Pass("add", "add objects to the design") { }
86 void help() YS_OVERRIDE
87 {
88 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
89 log("\n");
90 log(" add <command> [selection]\n");
91 log("\n");
92 log("This command adds objects to the design. It operates on all fully selected\n");
93 log("modules. So e.g. 'add -wire foo' will add a wire foo to all selected modules.\n");
94 log("\n");
95 log("\n");
96 log(" add {-wire|-input|-inout|-output} <name> <width> [selection]\n");
97 log("\n");
98 log("Add a wire (input, inout, output port) with the given name and width. The\n");
99 log("command will fail if the object exists already and has different properties\n");
100 log("than the object to be created.\n");
101 log("\n");
102 log("\n");
103 log(" add -global_input <name> <width> [selection]\n");
104 log("\n");
105 log("Like 'add -input', but also connect the signal between instances of the\n");
106 log("selected modules.\n");
107 log("\n");
108 log("\n");
109 log(" add -mod <name[s]>\n");
110 log("\n");
111 log("Add module[s] with the specified name[s].\n");
112 log("\n");
113 }
114 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
115 {
116 std::string command;
117 std::string arg_name;
118 bool arg_flag_input = false;
119 bool arg_flag_output = false;
120 bool arg_flag_global = false;
121 bool mod_mode = false;
122 int arg_width = 0;
123
124 size_t argidx;
125 for (argidx = 1; argidx < args.size(); argidx++)
126 {
127 std::string arg = args[argidx];
128 if (arg == "-wire" || arg == "-input" || arg == "-inout" || arg == "-output" || arg == "-global_input") {
129 if (argidx+2 >= args.size())
130 break;
131 command = "wire";
132 if (arg == "-input" || arg == "-inout" || arg == "-global_input")
133 arg_flag_input = true;
134 if (arg == "-output" || arg == "-inout")
135 arg_flag_output = true;
136 if (arg == "-global_input")
137 arg_flag_global = true;
138 arg_name = args[++argidx];
139 arg_width = atoi(args[++argidx].c_str());
140 continue;
141 }
142 if (arg == "-mod") {
143 mod_mode = true;
144 argidx++;
145 break;
146 }
147 break;
148 }
149
150 if (mod_mode) {
151 for (; argidx < args.size(); argidx++)
152 design->addModule(RTLIL::escape_id(args[argidx]));
153 return;
154 }
155
156 extra_args(args, argidx, design);
157
158 for (auto &mod : design->modules_)
159 {
160 RTLIL::Module *module = mod.second;
161 if (!design->selected_whole_module(module->name))
162 continue;
163 if (module->get_bool_attribute("\\blackbox"))
164 continue;
165
166 if (command == "wire")
167 add_wire(design, module, arg_name, arg_width, arg_flag_input, arg_flag_output, arg_flag_global);
168 }
169 }
170 } AddPass;
171
172 PRIVATE_NAMESPACE_END