2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
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.
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.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/celltypes.h"
25 PRIVATE_NAMESPACE_BEGIN
33 dict
<Cell
*, SimInstance
*> children
;
36 dict
<SigBit
, State
> state_nets
;
37 dict
<SigBit
, pool
<Cell
*>> upd_cells
;
38 dict
<SigBit
, pool
<Wire
*>> upd_outports
;
40 pool
<SigBit
> dirty_bits
;
41 dict
<SigBit
, State
> next_state_nets
;
43 dict
<Wire
*, int> vcd_netids
;
45 SimInstance(Module
*module
, Cell
*instance
= nullptr, SimInstance
*parent
= nullptr) :
46 module(module
), instance(instance
), parent(parent
), sigmap(module
)
49 log_assert(parent
->children
.count(instance
) == 0);
50 parent
->children
[instance
] = this;
53 for (auto wire
: module
->wires())
55 SigSpec sig
= sigmap(wire
);
57 for (int i
= 0; i
< GetSize(sig
); i
++) {
58 if (state_nets
.count(sig
[i
]) == 0)
59 state_nets
[sig
[i
]] = State::Sx
;
60 if (wire
->port_output
) {
61 upd_outports
[sig
[i
]].insert(wire
);
62 dirty_bits
.insert(sig
[i
]);
66 if (wire
->attributes
.count("\\init")) {
67 Const initval
= wire
->attributes
.at("\\init");
68 for (int i
= 0; i
< GetSize(sig
) && i
< GetSize(initval
); i
++)
69 if (initval
[i
] == State::S0
|| initval
[i
] == State::S1
) {
70 state_nets
[sig
[i
]] = initval
[i
];
71 dirty_bits
.insert(sig
[i
]);
76 for (auto cell
: module
->cells())
78 Module
*mod
= module
->design
->module(cell
->type
);
81 new SimInstance(mod
, cell
, this);
84 for (auto &port
: cell
->connections()) {
85 if (cell
->input(port
.first
))
86 for (auto bit
: sigmap(port
.second
))
87 upd_cells
[bit
].insert(cell
);
94 if (instance
!= nullptr)
95 return instance
->name
;
99 std::string
hiername() const
101 if (instance
!= nullptr)
102 return parent
->hiername() + "." + log_id(instance
->name
);
104 return log_id(module
->name
);
107 Const
get_state(SigSpec sig
)
111 for (auto bit
: sigmap(sig
))
112 if (state_nets
.count(bit
))
113 value
.bits
.push_back(state_nets
.at(bit
));
115 value
.bits
.push_back(State::Sz
);
117 // log("[%s] get %s: %s\n", hiername().c_str(), log_signal(sig), log_signal(value));
121 void set_state(SigSpec sig
, Const value
)
124 log_assert(GetSize(sig
) == GetSize(value
));
126 for (int i
= 0; i
< GetSize(sig
); i
++)
127 if (state_nets
.at(sig
[i
]) != value
[i
]) {
128 state_nets
.at(sig
[i
]) = value
[i
];
129 dirty_bits
.insert(sig
[i
]);
132 // log("[%s] set %s: %s\n", hiername().c_str(), log_signal(sig), log_signal(value));
135 void update_cell(Cell
*cell
)
137 if (children
.count(cell
))
139 auto child
= children
.at(cell
);
140 for (auto &conn
: cell
->connections())
141 if (cell
->input(conn
.first
)) {
142 Const value
= get_state(conn
.second
);
143 child
->set_state(child
->module
->wire(conn
.first
), value
);
148 if (yosys_celltypes
.cell_evaluable(cell
->type
))
150 // log("[%s] eval %s (%s)\n", hiername().c_str(), log_id(cell), log_id(cell->type));
152 RTLIL::SigSpec sig_a
, sig_b
, sig_c
, sig_d
, sig_s
, sig_y
;
153 bool has_a
, has_b
, has_c
, has_d
, has_s
, has_y
;
155 has_a
= cell
->hasPort("\\A");
156 has_b
= cell
->hasPort("\\B");
157 has_c
= cell
->hasPort("\\C");
158 has_d
= cell
->hasPort("\\D");
159 has_s
= cell
->hasPort("\\S");
160 has_y
= cell
->hasPort("\\Y");
162 if (has_a
) sig_a
= cell
->getPort("\\A");
163 if (has_b
) sig_b
= cell
->getPort("\\B");
164 if (has_c
) sig_c
= cell
->getPort("\\C");
165 if (has_d
) sig_d
= cell
->getPort("\\D");
166 if (has_s
) sig_s
= cell
->getPort("\\S");
167 if (has_y
) sig_y
= cell
->getPort("\\Y");
169 // Simple (A -> Y) and (A,B -> Y) cells
170 if (has_a
&& !has_c
&& !has_d
&& !has_s
&& has_y
) {
171 set_state(sig_y
, CellTypes::eval(cell
, get_state(sig_a
), get_state(sig_b
)));
175 // (A,B,C -> Y) cells
176 if (has_a
&& has_b
&& has_c
&& !has_d
&& !has_s
&& has_y
) {
177 set_state(sig_y
, CellTypes::eval(cell
, get_state(sig_a
), get_state(sig_b
), get_state(sig_c
)));
181 // (A,B,S -> Y) cells
182 if (has_a
&& has_b
&& !has_c
&& !has_d
&& has_s
&& has_y
) {
183 set_state(sig_y
, CellTypes::eval(cell
, get_state(sig_a
), get_state(sig_b
), get_state(sig_s
)));
187 log_warning("Unsupported evaluable cell type: %s (%s.%s)\n", log_id(cell
->type
), log_id(module
), log_id(cell
));
193 log_warning("Unsupported cell type: %s (%s.%s)\n", log_id(cell
->type
), log_id(module
), log_id(cell
));
200 while (!dirty_bits
.empty())
202 SigBit bit
= *dirty_bits
.begin();
203 dirty_bits
.erase(bit
);
205 if (upd_cells
.count(bit
))
207 for (auto cell
: upd_cells
.at(bit
))
211 if (upd_outports
.count(bit
) && parent
!= nullptr)
213 for (auto wire
: upd_outports
.at(bit
))
214 if (instance
->hasPort(wire
->name
)) {
215 Const value
= get_state(wire
);
216 parent
->set_state(instance
->getPort(wire
->name
), value
);
221 for (auto child
: children
)
222 child
.second
->update();
224 if (dirty_bits
.empty())
229 void write_vcd_header(std::ofstream
&f
, int &id
)
231 f
<< stringf("$scope module %s $end\n", log_id(name()));
233 for (auto wire
: module
->wires())
235 if (wire
->name
[0] == '$')
238 f
<< stringf("$var wire %d n%d %s $end\n", GetSize(wire
), id
, log_id(wire
));
239 vcd_netids
[wire
] = id
++;
242 for (auto child
: children
)
243 child
.second
->write_vcd_header(f
, id
);
245 f
<< stringf("$upscope $end\n");
248 void write_vcd_step(std::ofstream
&f
)
250 for (auto it
: vcd_netids
)
252 Wire
*wire
= it
.first
;
253 Const value
= get_state(wire
);
257 for (int i
= GetSize(value
)-1; i
>= 0; i
--) {
259 case State::S0
: f
<< "0"; break;
260 case State::S1
: f
<< "1"; break;
261 case State::Sx
: f
<< "x"; break;
266 f
<< stringf(" n%d\n", id
);
269 for (auto child
: children
)
270 child
.second
->write_vcd_step(f
);
276 SimInstance
*top
= nullptr;
277 std::ofstream vcdfile
;
279 void initialize(Module
*topmod
)
281 top
= new SimInstance(topmod
);
290 void write_vcd_header()
292 if (!vcdfile
.is_open())
296 top
->write_vcd_header(vcdfile
, id
);
298 vcdfile
<< stringf("$enddefinitions $end\n");
301 void write_vcd_step(int n
)
303 if (!vcdfile
.is_open())
306 vcdfile
<< stringf("#%d\n", 10*n
);
307 top
->write_vcd_step(vcdfile
);
311 struct SimPass
: public Pass
{
312 SimPass() : Pass("sim", "simulate the circuit") { }
315 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
317 log(" sim [options] [top-level]\n");
319 log("This command simulates the circuit using the given top-level module.\n");
321 log(" -vcd <filename>\n");
322 log(" write the simulation results to the given VCD file\n");
324 log(" -n <integer>\n");
325 log(" number of steps to simulate (default: 20)\n");
328 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
333 log_header(design
, "Executing SIM pass (simulate the circuit).\n");
336 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
337 if (args
[argidx
] == "-vcd" && argidx
+1 < args
.size()) {
338 worker
.vcdfile
.open(args
[++argidx
].c_str());
341 if (args
[argidx
] == "-n" && argidx
+1 < args
.size()) {
342 numsteps
= atoi(args
[++argidx
].c_str());
347 extra_args(args
, argidx
, design
);
349 Module
*top_mod
= nullptr;
351 if (design
->full_selection()) {
352 top_mod
= design
->top_module();
354 auto mods
= design
->selected_whole_modules();
355 if (GetSize(mods
) != 1)
356 log_cmd_error("Only one top module must be selected.\n");
357 top_mod
= mods
.front();
360 worker
.initialize(top_mod
);
361 worker
.write_vcd_header();
362 worker
.write_vcd_step(0);
364 for (int i
= 1; i
< numsteps
; i
++) {
366 worker
.write_vcd_step(i
);
371 PRIVATE_NAMESPACE_END