2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
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"
23 #include "kernel/mem.h"
24 #include "kernel/fstdata.h"
29 PRIVATE_NAMESPACE_BEGIN
34 bool hide_internal
= true;
35 bool writeback
= false;
38 FstData
*fst
= nullptr;
49 for (auto &bit
: v
.bits
)
62 dict
<Cell
*, SimInstance
*> children
;
65 dict
<SigBit
, State
> state_nets
;
66 dict
<SigBit
, pool
<Cell
*>> upd_cells
;
67 dict
<SigBit
, pool
<Wire
*>> upd_outports
;
69 pool
<SigBit
> dirty_bits
;
70 pool
<Cell
*> dirty_cells
;
71 pool
<IdString
> dirty_memories
;
72 pool
<SimInstance
*, hash_ptr_ops
> dirty_children
;
83 std::vector
<Const
> past_wr_clk
;
84 std::vector
<Const
> past_wr_en
;
85 std::vector
<Const
> past_wr_addr
;
86 std::vector
<Const
> past_wr_data
;
90 dict
<Cell
*, ff_state_t
> ff_database
;
91 dict
<IdString
, mem_state_t
> mem_database
;
92 pool
<Cell
*> formal_database
;
93 dict
<Cell
*, IdString
> mem_cells
;
95 std::vector
<Mem
> memories
;
97 dict
<Wire
*, pair
<int, Const
>> vcd_database
;
98 dict
<Wire
*, pair
<fstHandle
, Const
>> fst_database
;
100 SimInstance(SimShared
*shared
, std::string scope
, Module
*module
, Cell
*instance
= nullptr, SimInstance
*parent
= nullptr) :
101 shared(shared
), scope(scope
), module(module
), instance(instance
), parent(parent
), sigmap(module
)
106 log_assert(parent
->children
.count(instance
) == 0);
107 parent
->children
[instance
] = this;
110 for (auto wire
: module
->wires())
112 SigSpec sig
= sigmap(wire
);
114 for (int i
= 0; i
< GetSize(sig
); i
++) {
115 if (state_nets
.count(sig
[i
]) == 0)
116 state_nets
[sig
[i
]] = State::Sx
;
117 if (wire
->port_output
) {
118 upd_outports
[sig
[i
]].insert(wire
);
119 dirty_bits
.insert(sig
[i
]);
123 if (wire
->attributes
.count(ID::init
)) {
124 Const initval
= wire
->attributes
.at(ID::init
);
125 for (int i
= 0; i
< GetSize(sig
) && i
< GetSize(initval
); i
++)
126 if (initval
[i
] == State::S0
|| initval
[i
] == State::S1
) {
127 state_nets
[sig
[i
]] = initval
[i
];
128 dirty_bits
.insert(sig
[i
]);
133 memories
= Mem::get_all_memories(module
);
134 for (auto &mem
: memories
) {
135 auto &mdb
= mem_database
[mem
.memid
];
137 for (auto &port
: mem
.wr_ports
) {
138 mdb
.past_wr_clk
.push_back(Const(State::Sx
));
139 mdb
.past_wr_en
.push_back(Const(State::Sx
, GetSize(port
.en
)));
140 mdb
.past_wr_addr
.push_back(Const(State::Sx
, GetSize(port
.addr
)));
141 mdb
.past_wr_data
.push_back(Const(State::Sx
, GetSize(port
.data
)));
143 mdb
.data
= mem
.get_init_data();
146 for (auto cell
: module
->cells())
148 Module
*mod
= module
->design
->module(cell
->type
);
150 if (mod
!= nullptr) {
151 dirty_children
.insert(new SimInstance(shared
, scope
+ "." + RTLIL::unescape_id(module
->name
), mod
, cell
, this));
154 for (auto &port
: cell
->connections()) {
155 if (cell
->input(port
.first
))
156 for (auto bit
: sigmap(port
.second
)) {
157 upd_cells
[bit
].insert(cell
);
158 // Make sure cell inputs connected to constants are updated in the first cycle
159 if (bit
.wire
== nullptr)
160 dirty_bits
.insert(bit
);
164 if (cell
->type
.in(ID($dff
))) {
166 ff
.past_clock
= State::Sx
;
167 ff
.past_d
= Const(State::Sx
, cell
->getParam(ID::WIDTH
).as_int());
168 ff_database
[cell
] = ff
;
171 if (cell
->is_mem_cell())
173 mem_cells
[cell
] = cell
->parameters
.at(ID::MEMID
).decode_string();
175 if (cell
->type
.in(ID($
assert), ID($cover
), ID($assume
))) {
176 formal_database
.insert(cell
);
182 for (auto &it
: ff_database
)
184 Cell
*cell
= it
.first
;
185 ff_state_t
&ff
= it
.second
;
188 SigSpec qsig
= cell
->getPort(ID::Q
);
189 Const qdata
= get_state(qsig
);
191 set_state(qsig
, qdata
);
194 for (auto &it
: mem_database
) {
195 mem_state_t
&mem
= it
.second
;
196 for (auto &val
: mem
.past_wr_en
)
205 for (auto child
: children
)
209 IdString
name() const
211 if (instance
!= nullptr)
212 return instance
->name
;
216 std::string
hiername() const
218 if (instance
!= nullptr)
219 return parent
->hiername() + "." + log_id(instance
->name
);
221 return log_id(module
->name
);
224 Const
get_state(SigSpec sig
)
228 for (auto bit
: sigmap(sig
))
229 if (bit
.wire
== nullptr)
230 value
.bits
.push_back(bit
.data
);
231 else if (state_nets
.count(bit
))
232 value
.bits
.push_back(state_nets
.at(bit
));
234 value
.bits
.push_back(State::Sz
);
237 log("[%s] get %s: %s\n", hiername().c_str(), log_signal(sig
), log_signal(value
));
241 bool set_state(SigSpec sig
, Const value
)
243 bool did_something
= false;
246 log_assert(GetSize(sig
) <= GetSize(value
));
248 for (int i
= 0; i
< GetSize(sig
); i
++)
249 if (state_nets
.at(sig
[i
]) != value
[i
]) {
250 state_nets
.at(sig
[i
]) = value
[i
];
251 dirty_bits
.insert(sig
[i
]);
252 did_something
= true;
256 log("[%s] set %s: %s\n", hiername().c_str(), log_signal(sig
), log_signal(value
));
257 return did_something
;
260 void update_cell(Cell
*cell
)
262 if (ff_database
.count(cell
))
265 if (formal_database
.count(cell
))
268 if (mem_cells
.count(cell
))
270 dirty_memories
.insert(mem_cells
[cell
]);
274 if (children
.count(cell
))
276 auto child
= children
.at(cell
);
277 for (auto &conn
: cell
->connections())
278 if (cell
->input(conn
.first
) && GetSize(conn
.second
)) {
279 Const value
= get_state(conn
.second
);
280 child
->set_state(child
->module
->wire(conn
.first
), value
);
282 dirty_children
.insert(child
);
286 if (yosys_celltypes
.cell_evaluable(cell
->type
))
288 RTLIL::SigSpec sig_a
, sig_b
, sig_c
, sig_d
, sig_s
, sig_y
;
289 bool has_a
, has_b
, has_c
, has_d
, has_s
, has_y
;
291 has_a
= cell
->hasPort(ID::A
);
292 has_b
= cell
->hasPort(ID::B
);
293 has_c
= cell
->hasPort(ID::C
);
294 has_d
= cell
->hasPort(ID::D
);
295 has_s
= cell
->hasPort(ID::S
);
296 has_y
= cell
->hasPort(ID::Y
);
298 if (has_a
) sig_a
= cell
->getPort(ID::A
);
299 if (has_b
) sig_b
= cell
->getPort(ID::B
);
300 if (has_c
) sig_c
= cell
->getPort(ID::C
);
301 if (has_d
) sig_d
= cell
->getPort(ID::D
);
302 if (has_s
) sig_s
= cell
->getPort(ID::S
);
303 if (has_y
) sig_y
= cell
->getPort(ID::Y
);
306 log("[%s] eval %s (%s)\n", hiername().c_str(), log_id(cell
), log_id(cell
->type
));
308 // Simple (A -> Y) and (A,B -> Y) cells
309 if (has_a
&& !has_c
&& !has_d
&& !has_s
&& has_y
) {
310 set_state(sig_y
, CellTypes::eval(cell
, get_state(sig_a
), get_state(sig_b
)));
314 // (A,B,C -> Y) cells
315 if (has_a
&& has_b
&& has_c
&& !has_d
&& !has_s
&& has_y
) {
316 set_state(sig_y
, CellTypes::eval(cell
, get_state(sig_a
), get_state(sig_b
), get_state(sig_c
)));
320 // (A,B,S -> Y) cells
321 if (has_a
&& has_b
&& !has_c
&& !has_d
&& has_s
&& has_y
) {
322 set_state(sig_y
, CellTypes::eval(cell
, get_state(sig_a
), get_state(sig_b
), get_state(sig_s
)));
326 log_warning("Unsupported evaluable cell type: %s (%s.%s)\n", log_id(cell
->type
), log_id(module
), log_id(cell
));
330 log_error("Unsupported cell type: %s (%s.%s)\n", log_id(cell
->type
), log_id(module
), log_id(cell
));
333 void update_memory(IdString id
) {
334 auto &mdb
= mem_database
[id
];
335 auto &mem
= *mdb
.mem
;
337 for (int port_idx
= 0; port_idx
< GetSize(mem
.rd_ports
); port_idx
++)
339 auto &port
= mem
.rd_ports
[port_idx
];
340 Const addr
= get_state(port
.addr
);
341 Const data
= Const(State::Sx
, mem
.width
<< port
.wide_log2
);
344 log_error("Memory %s.%s has clocked read ports. Run 'memory' with -nordff.\n", log_id(module
), log_id(mem
.memid
));
346 if (addr
.is_fully_def()) {
347 int index
= addr
.as_int() - mem
.start_offset
;
348 if (index
>= 0 && index
< mem
.size
)
349 data
= mdb
.data
.extract(index
*mem
.width
, mem
.width
<< port
.wide_log2
);
352 set_state(port
.data
, data
);
358 pool
<Cell
*> queue_cells
;
359 pool
<Wire
*> queue_outports
;
361 queue_cells
.swap(dirty_cells
);
365 for (auto bit
: dirty_bits
)
367 if (upd_cells
.count(bit
))
368 for (auto cell
: upd_cells
.at(bit
))
369 queue_cells
.insert(cell
);
371 if (upd_outports
.count(bit
) && parent
!= nullptr)
372 for (auto wire
: upd_outports
.at(bit
))
373 queue_outports
.insert(wire
);
378 if (!queue_cells
.empty())
380 for (auto cell
: queue_cells
)
387 for (auto &memid
: dirty_memories
)
388 update_memory(memid
);
389 dirty_memories
.clear();
391 for (auto wire
: queue_outports
)
392 if (instance
->hasPort(wire
->name
)) {
393 Const value
= get_state(wire
);
394 parent
->set_state(instance
->getPort(wire
->name
), value
);
397 queue_outports
.clear();
399 for (auto child
: dirty_children
)
402 dirty_children
.clear();
404 if (dirty_bits
.empty())
411 bool did_something
= false;
413 for (auto &it
: ff_database
)
415 Cell
*cell
= it
.first
;
416 ff_state_t
&ff
= it
.second
;
418 if (cell
->type
.in(ID($dff
)))
420 bool clkpol
= cell
->getParam(ID::CLK_POLARITY
).as_bool();
421 State current_clock
= get_state(cell
->getPort(ID::CLK
))[0];
423 if (clkpol
? (ff
.past_clock
== State::S1
|| current_clock
!= State::S1
) :
424 (ff
.past_clock
== State::S0
|| current_clock
!= State::S0
))
427 if (set_state(cell
->getPort(ID::Q
), ff
.past_d
))
428 did_something
= true;
432 for (auto &it
: mem_database
)
434 mem_state_t
&mdb
= it
.second
;
435 auto &mem
= *mdb
.mem
;
437 for (int port_idx
= 0; port_idx
< GetSize(mem
.wr_ports
); port_idx
++)
439 auto &port
= mem
.wr_ports
[port_idx
];
440 Const addr
, data
, enable
;
442 if (!port
.clk_enable
)
444 addr
= get_state(port
.addr
);
445 data
= get_state(port
.data
);
446 enable
= get_state(port
.en
);
450 if (port
.clk_polarity
?
451 (mdb
.past_wr_clk
[port_idx
] == State::S1
|| get_state(port
.clk
) != State::S1
) :
452 (mdb
.past_wr_clk
[port_idx
] == State::S0
|| get_state(port
.clk
) != State::S0
))
455 addr
= mdb
.past_wr_addr
[port_idx
];
456 data
= mdb
.past_wr_data
[port_idx
];
457 enable
= mdb
.past_wr_en
[port_idx
];
460 if (addr
.is_fully_def())
462 int index
= addr
.as_int() - mem
.start_offset
;
463 if (index
>= 0 && index
< mem
.size
)
464 for (int i
= 0; i
< (mem
.width
<< port
.wide_log2
); i
++)
465 if (enable
[i
] == State::S1
&& mdb
.data
.bits
.at(index
*mem
.width
+i
) != data
[i
]) {
466 mdb
.data
.bits
.at(index
*mem
.width
+i
) = data
[i
];
467 dirty_memories
.insert(mem
.memid
);
468 did_something
= true;
474 for (auto it
: children
)
475 if (it
.second
->update_ph2()) {
476 dirty_children
.insert(it
.second
);
477 did_something
= true;
480 return did_something
;
485 for (auto &it
: ff_database
)
487 Cell
*cell
= it
.first
;
488 ff_state_t
&ff
= it
.second
;
490 if (cell
->type
.in(ID($dff
))) {
491 ff
.past_clock
= get_state(cell
->getPort(ID::CLK
))[0];
492 ff
.past_d
= get_state(cell
->getPort(ID::D
));
496 for (auto &it
: mem_database
)
498 mem_state_t
&mem
= it
.second
;
500 for (int i
= 0; i
< GetSize(mem
.mem
->wr_ports
); i
++) {
501 auto &port
= mem
.mem
->wr_ports
[i
];
502 mem
.past_wr_clk
[i
] = get_state(port
.clk
);
503 mem
.past_wr_en
[i
] = get_state(port
.en
);
504 mem
.past_wr_addr
[i
] = get_state(port
.addr
);
505 mem
.past_wr_data
[i
] = get_state(port
.data
);
509 for (auto cell
: formal_database
)
511 string label
= log_id(cell
);
512 if (cell
->attributes
.count(ID::src
))
513 label
= cell
->attributes
.at(ID::src
).decode_string();
515 State a
= get_state(cell
->getPort(ID::A
))[0];
516 State en
= get_state(cell
->getPort(ID::EN
))[0];
518 if (cell
->type
== ID($cover
) && en
== State::S1
&& a
!= State::S1
)
519 log("Cover %s.%s (%s) reached.\n", hiername().c_str(), log_id(cell
), label
.c_str());
521 if (cell
->type
== ID($assume
) && en
== State::S1
&& a
!= State::S1
)
522 log("Assumption %s.%s (%s) failed.\n", hiername().c_str(), log_id(cell
), label
.c_str());
524 if (cell
->type
== ID($
assert) && en
== State::S1
&& a
!= State::S1
)
525 log_warning("Assert %s.%s (%s) failed.\n", hiername().c_str(), log_id(cell
), label
.c_str());
528 for (auto it
: children
)
529 it
.second
->update_ph3();
532 void writeback(pool
<Module
*> &wbmods
)
534 if (wbmods
.count(module
))
535 log_error("Instance %s of module %s is not unique: Writeback not possible. (Fix by running 'uniquify'.)\n", hiername().c_str(), log_id(module
));
537 wbmods
.insert(module
);
539 for (auto wire
: module
->wires())
540 wire
->attributes
.erase(ID::init
);
542 for (auto &it
: ff_database
)
544 Cell
*cell
= it
.first
;
545 SigSpec sig_q
= cell
->getPort(ID::Q
);
546 Const initval
= get_state(sig_q
);
548 for (int i
= 0; i
< GetSize(sig_q
); i
++)
550 Wire
*w
= sig_q
[i
].wire
;
552 if (w
->attributes
.count(ID::init
) == 0)
553 w
->attributes
[ID::init
] = Const(State::Sx
, GetSize(w
));
555 w
->attributes
[ID::init
][sig_q
[i
].offset
] = initval
[i
];
559 for (auto &it
: mem_database
)
561 mem_state_t
&mem
= it
.second
;
562 mem
.mem
->clear_inits();
564 minit
.addr
= mem
.mem
->start_offset
;
565 minit
.data
= mem
.data
;
566 minit
.en
= Const(State::S1
, mem
.mem
->width
);
567 mem
.mem
->inits
.push_back(minit
);
571 for (auto it
: children
)
572 it
.second
->writeback(wbmods
);
575 void write_vcd_header(std::ofstream
&f
, int &id
)
577 f
<< stringf("$scope module %s $end\n", log_id(name()));
579 for (auto wire
: module
->wires())
581 if (shared
->hide_internal
&& wire
->name
[0] == '$')
584 f
<< stringf("$var wire %d n%d %s%s $end\n", GetSize(wire
), id
, wire
->name
[0] == '$' ? "\\" : "", log_id(wire
));
585 vcd_database
[wire
] = make_pair(id
++, Const());
588 for (auto child
: children
)
589 child
.second
->write_vcd_header(f
, id
);
591 f
<< stringf("$upscope $end\n");
594 void write_vcd_step(std::ofstream
&f
)
596 for (auto &it
: vcd_database
)
598 Wire
*wire
= it
.first
;
599 Const value
= get_state(wire
);
600 int id
= it
.second
.first
;
602 if (it
.second
.second
== value
)
605 it
.second
.second
= value
;
608 for (int i
= GetSize(value
)-1; i
>= 0; i
--) {
610 case State::S0
: f
<< "0"; break;
611 case State::S1
: f
<< "1"; break;
612 case State::Sx
: f
<< "x"; break;
617 f
<< stringf(" n%d\n", id
);
620 for (auto child
: children
)
621 child
.second
->write_vcd_step(f
);
624 void write_fst_header(struct fstContext
*f
)
626 fstWriterSetScope(f
, FST_ST_VCD_MODULE
, stringf("%s",log_id(name())).c_str(), nullptr);
627 for (auto wire
: module
->wires())
629 if (shared
->hide_internal
&& wire
->name
[0] == '$')
632 fstHandle id
= fstWriterCreateVar(f
, FST_VT_VCD_WIRE
, FST_VD_IMPLICIT
, GetSize(wire
),
633 stringf("%s%s", wire
->name
[0] == '$' ? "\\" : "", log_id(wire
)).c_str(), 0);
634 fst_database
[wire
] = make_pair(id
, Const());
637 for (auto child
: children
)
638 child
.second
->write_fst_header(f
);
640 fstWriterSetUpscope(f
);
643 void write_fst_step(struct fstContext
*f
)
645 for (auto &it
: fst_database
)
647 Wire
*wire
= it
.first
;
648 Const value
= get_state(wire
);
649 fstHandle id
= it
.second
.first
;
651 if (it
.second
.second
== value
)
654 it
.second
.second
= value
;
655 std::stringstream ss
;
656 for (int i
= GetSize(value
)-1; i
>= 0; i
--) {
658 case State::S0
: ss
<< "0"; break;
659 case State::S1
: ss
<< "1"; break;
660 case State::Sx
: ss
<< "x"; break;
664 fstWriterEmitValueChange(f
, id
, ss
.str().c_str());
667 for (auto child
: children
)
668 child
.second
->write_fst_step(f
);
672 struct SimWorker
: SimShared
674 SimInstance
*top
= nullptr;
675 std::ofstream vcdfile
;
676 struct fstContext
*fstfile
= nullptr;
677 pool
<IdString
> clock
, clockn
, reset
, resetn
;
678 std::string timescale
;
679 std::string sim_filename
;
687 void write_vcd_header()
689 vcdfile
<< stringf("$version %s $end\n", yosys_version_str
);
691 std::time_t t
= std::time(nullptr);
693 if (std::strftime(mbstr
, sizeof(mbstr
), "%c", std::localtime(&t
))) {
694 vcdfile
<< stringf("$date ") << mbstr
<< stringf(" $end\n");
697 if (!timescale
.empty())
698 vcdfile
<< stringf("$timescale %s $end\n", timescale
.c_str());
701 top
->write_vcd_header(vcdfile
, id
);
703 vcdfile
<< stringf("$enddefinitions $end\n");
706 void write_vcd_step(int t
)
708 vcdfile
<< stringf("#%d\n", t
);
709 top
->write_vcd_step(vcdfile
);
712 void write_fst_header()
714 std::time_t t
= std::time(nullptr);
715 fstWriterSetDate(fstfile
, asctime(std::localtime(&t
)));
716 fstWriterSetVersion(fstfile
, yosys_version_str
);
717 if (!timescale
.empty())
718 fstWriterSetTimescaleFromString(fstfile
, timescale
.c_str());
720 fstWriterSetPackType(fstfile
, FST_WR_PT_FASTLZ
);
721 fstWriterSetRepackOnClose(fstfile
, 1);
723 top
->write_fst_header(fstfile
);
726 void write_fst_step(int t
)
728 fstWriterEmitTimeChange(fstfile
, t
);
730 top
->write_fst_step(fstfile
);
733 void write_output_header()
735 if (vcdfile
.is_open())
741 void write_output_step(int t
)
743 if (vcdfile
.is_open())
749 void write_output_end()
752 fstWriterClose(fstfile
);
760 log("\n-- ph1 --\n");
765 log("\n-- ph2 --\n");
767 if (!top
->update_ph2())
772 log("\n-- ph3 --\n");
777 void set_inports(pool
<IdString
> ports
, State value
)
779 for (auto portname
: ports
)
781 Wire
*w
= top
->module
->wire(portname
);
784 log_error("Can't find port %s on module %s.\n", log_id(portname
), log_id(top
->module
));
786 top
->set_state(w
, value
);
790 void run(Module
*topmod
, int numcycles
)
792 log_assert(top
== nullptr);
793 top
= new SimInstance(this, scope
, topmod
);
796 log("\n===== 0 =====\n");
798 log("Simulating cycle 0.\n");
800 set_inports(reset
, State::S1
);
801 set_inports(resetn
, State::S0
);
803 set_inports(clock
, State::Sx
);
804 set_inports(clockn
, State::Sx
);
808 write_output_header();
809 write_output_step(0);
811 for (int cycle
= 0; cycle
< numcycles
; cycle
++)
814 log("\n===== %d =====\n", 10*cycle
+ 5);
816 set_inports(clock
, State::S0
);
817 set_inports(clockn
, State::S1
);
820 write_output_step(10*cycle
+ 5);
823 log("\n===== %d =====\n", 10*cycle
+ 10);
825 log("Simulating cycle %d.\n", cycle
+1);
827 set_inports(clock
, State::S1
);
828 set_inports(clockn
, State::S0
);
830 if (cycle
+1 == rstlen
) {
831 set_inports(reset
, State::S0
);
832 set_inports(resetn
, State::S1
);
836 write_output_step(10*cycle
+ 10);
839 write_output_step(10*numcycles
+ 2);
844 pool
<Module
*> wbmods
;
845 top
->writeback(wbmods
);
849 void run_cosim(Module
*topmod
, int numcycles
)
851 log_assert(top
== nullptr);
852 top
= new SimInstance(this, scope
, topmod
);
854 fst
= new FstData(sim_filename
);
856 std::vector
<fstHandle
> fst_clock
;
858 for (auto portname
: clock
)
860 Wire
*w
= topmod
->wire(portname
);
862 log_error("Can't find port %s on module %s.\n", log_id(portname
), log_id(top
->module
));
864 log_error("Clock port %s on module %s is not input.\n", log_id(portname
), log_id(top
->module
));
865 fstHandle id
= fst
->getHandle(scope
+ "." + RTLIL::unescape_id(portname
));
867 log_error("Can't find port %s.%s in FST.\n", scope
.c_str(), log_id(portname
));
868 fst_clock
.push_back(id
);
870 for (auto portname
: clockn
)
872 Wire
*w
= topmod
->wire(portname
);
874 log_error("Can't find port %s on module %s.\n", log_id(portname
), log_id(top
->module
));
876 log_error("Clock port %s on module %s is not input.\n", log_id(portname
), log_id(top
->module
));
877 fstHandle id
= fst
->getHandle(scope
+ "." + RTLIL::unescape_id(portname
));
879 log_error("Can't find port %s.%s in FST.\n", scope
.c_str(), log_id(portname
));
880 fst_clock
.push_back(id
);
882 if (fst_clock
.size()==0)
883 log_error("No clock signals defined for input file\n");
885 SigMap
sigmap(topmod
);
886 log ("Get inputs\n");
887 std::map
<Wire
*,fstHandle
> inputs
;
889 for (auto wire
: topmod
->wires()) {
890 if (wire
->port_input
) {
891 fstHandle id
= fst
->getHandle(scope
+ "." + RTLIL::unescape_id(wire
->name
));
892 log("Input %s\n",log_id(wire
));
897 fst
->reconstruct(fst_clock
);
898 auto edges
= fst
->edges(fst_clock
.back(), true, true);
899 fst
->reconstructAllAtTimes(edges
);
900 for(auto &time
: edges
) {
901 for(auto &item
: inputs
) {
902 std::string v
= fst
->valueAt(item
.second
, time
);
903 top
->set_state(item
.first
, Const::from_string(v
));
907 /*Wire *wire = topmod->wire("\\cnt");
908 Const value = top->get_state(wire);
909 std::stringstream ss;
910 for (int i = GetSize(value)-1; i >= 0; i--) {
912 case State::S0: ss << "0"; break;
913 case State::S1: ss << "1"; break;
914 case State::Sx: ss << "x"; break;
918 log("%s\n",ss.str().c_str());*/
923 struct SimPass
: public Pass
{
924 SimPass() : Pass("sim", "simulate the circuit") { }
927 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
929 log(" sim [options] [top-level]\n");
931 log("This command simulates the circuit using the given top-level module.\n");
933 log(" -vcd <filename>\n");
934 log(" write the simulation results to the given VCD file\n");
936 log(" -fst <filename>\n");
937 log(" write the simulation results to the given FST file\n");
939 log(" -clock <portname>\n");
940 log(" name of top-level clock input\n");
942 log(" -clockn <portname>\n");
943 log(" name of top-level clock input (inverse polarity)\n");
945 log(" -reset <portname>\n");
946 log(" name of top-level reset input (active high)\n");
948 log(" -resetn <portname>\n");
949 log(" name of top-level inverted reset input (active low)\n");
951 log(" -rstlen <integer>\n");
952 log(" number of cycles reset should stay active (default: 1)\n");
955 log(" zero-initialize all uninitialized regs and memories\n");
957 log(" -timescale <string>\n");
958 log(" include the specified timescale declaration in the vcd\n");
960 log(" -n <integer>\n");
961 log(" number of cycles to simulate (default: 20)\n");
964 log(" include all nets in VCD output, not just those with public names\n");
967 log(" writeback mode: use final simulation state as new init state\n");
970 log(" read simulation results file (file formats supported: FST)\n");
973 log(" scope of simulation top model\n");
976 log(" enable debug output\n");
979 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) override
984 log_header(design
, "Executing SIM pass (simulate the circuit).\n");
987 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
988 if (args
[argidx
] == "-vcd" && argidx
+1 < args
.size()) {
989 std::string vcd_filename
= args
[++argidx
];
990 rewrite_filename(vcd_filename
);
991 worker
.vcdfile
.open(vcd_filename
.c_str());
994 if (args
[argidx
] == "-fst" && argidx
+1 < args
.size()) {
995 std::string fst_filename
= args
[++argidx
];
996 rewrite_filename(fst_filename
);
997 worker
.fstfile
= (struct fstContext
*)fstWriterCreate(fst_filename
.c_str(),1);
1000 if (args
[argidx
] == "-n" && argidx
+1 < args
.size()) {
1001 numcycles
= atoi(args
[++argidx
].c_str());
1004 if (args
[argidx
] == "-rstlen" && argidx
+1 < args
.size()) {
1005 worker
.rstlen
= atoi(args
[++argidx
].c_str());
1008 if (args
[argidx
] == "-clock" && argidx
+1 < args
.size()) {
1009 worker
.clock
.insert(RTLIL::escape_id(args
[++argidx
]));
1012 if (args
[argidx
] == "-clockn" && argidx
+1 < args
.size()) {
1013 worker
.clockn
.insert(RTLIL::escape_id(args
[++argidx
]));
1016 if (args
[argidx
] == "-reset" && argidx
+1 < args
.size()) {
1017 worker
.reset
.insert(RTLIL::escape_id(args
[++argidx
]));
1020 if (args
[argidx
] == "-resetn" && argidx
+1 < args
.size()) {
1021 worker
.resetn
.insert(RTLIL::escape_id(args
[++argidx
]));
1024 if (args
[argidx
] == "-timescale" && argidx
+1 < args
.size()) {
1025 worker
.timescale
= args
[++argidx
];
1028 if (args
[argidx
] == "-a") {
1029 worker
.hide_internal
= false;
1032 if (args
[argidx
] == "-d") {
1033 worker
.debug
= true;
1036 if (args
[argidx
] == "-w") {
1037 worker
.writeback
= true;
1040 if (args
[argidx
] == "-zinit") {
1041 worker
.zinit
= true;
1044 if (args
[argidx
] == "-r" && argidx
+1 < args
.size()) {
1045 std::string sim_filename
= args
[++argidx
];
1046 rewrite_filename(sim_filename
);
1047 worker
.sim_filename
= sim_filename
;
1050 if (args
[argidx
] == "-scope" && argidx
+1 < args
.size()) {
1051 worker
.scope
= args
[++argidx
];
1056 extra_args(args
, argidx
, design
);
1058 Module
*top_mod
= nullptr;
1060 if (design
->full_selection()) {
1061 top_mod
= design
->top_module();
1064 log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n");
1066 auto mods
= design
->selected_whole_modules();
1067 if (GetSize(mods
) != 1)
1068 log_cmd_error("Only one top module must be selected.\n");
1069 top_mod
= mods
.front();
1072 if (worker
.sim_filename
.empty())
1073 worker
.run(top_mod
, numcycles
);
1075 worker
.run_cosim(top_mod
, numcycles
);
1079 PRIVATE_NAMESPACE_END