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/rtlil.h"
21 #include "kernel/log.h"
25 int RTLIL::autoidx
= 1;
27 RTLIL::Const::Const(std::string str
) : str(str
)
29 for (size_t i
= 0; i
< str
.size(); i
++) {
30 unsigned char ch
= str
[i
];
31 for (int j
= 0; j
< 8; j
++) {
32 bits
.push_back((ch
& 1) != 0 ? RTLIL::S1
: RTLIL::S0
);
38 RTLIL::Const::Const(int val
, int width
)
40 for (int i
= 0; i
< width
; i
++) {
41 bits
.push_back((val
& 1) != 0 ? RTLIL::S1
: RTLIL::S0
);
46 RTLIL::Const::Const(RTLIL::State bit
, int width
)
48 for (int i
= 0; i
< width
; i
++)
52 bool RTLIL::Const::operator <(const RTLIL::Const
&other
) const
54 if (bits
.size() != other
.bits
.size())
55 return bits
.size() < other
.bits
.size();
56 for (size_t i
= 0; i
< bits
.size(); i
++)
57 if (bits
[i
] != other
.bits
[i
])
58 return bits
[i
] < other
.bits
[i
];
62 bool RTLIL::Const::operator ==(const RTLIL::Const
&other
) const
64 return bits
== other
.bits
;
67 bool RTLIL::Const::operator !=(const RTLIL::Const
&other
) const
69 return bits
!= other
.bits
;
72 bool RTLIL::Const::as_bool() const
74 for (size_t i
= 0; i
< bits
.size(); i
++)
75 if (bits
[i
] == RTLIL::S1
)
80 int RTLIL::Const::as_int() const
83 for (size_t i
= 0; i
< bits
.size() && i
< 32; i
++)
84 if (bits
[i
] == RTLIL::S1
)
89 std::string
RTLIL::Const::as_string() const
92 for (size_t i
= bits
.size(); i
> 0; i
--)
94 case S0
: ret
+= "0"; break;
95 case S1
: ret
+= "1"; break;
96 case Sx
: ret
+= "x"; break;
97 case Sz
: ret
+= "z"; break;
98 case Sa
: ret
+= "-"; break;
99 case Sm
: ret
+= "m"; break;
104 bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name
) const
108 if (selected_modules
.count(mod_name
) > 0)
110 if (selected_members
.count(mod_name
) > 0)
115 bool RTLIL::Selection::selected_whole_module(RTLIL::IdString mod_name
) const
119 if (selected_modules
.count(mod_name
) > 0)
124 bool RTLIL::Selection::selected_member(RTLIL::IdString mod_name
, RTLIL::IdString memb_name
) const
128 if (selected_modules
.count(mod_name
) > 0)
130 if (selected_members
.count(mod_name
) > 0)
131 if (selected_members
.at(mod_name
).count(memb_name
) > 0)
136 void RTLIL::Selection::optimize(RTLIL::Design
*design
)
138 if (full_selection
) {
139 selected_modules
.clear();
140 selected_members
.clear();
144 std::vector
<RTLIL::IdString
> del_list
, add_list
;
147 for (auto mod_name
: selected_modules
) {
148 if (design
->modules
.count(mod_name
) == 0)
149 del_list
.push_back(mod_name
);
150 selected_members
.erase(mod_name
);
152 for (auto mod_name
: del_list
)
153 selected_modules
.erase(mod_name
);
156 for (auto &it
: selected_members
)
157 if (design
->modules
.count(it
.first
) == 0)
158 del_list
.push_back(it
.first
);
159 for (auto mod_name
: del_list
)
160 selected_members
.erase(mod_name
);
162 for (auto &it
: selected_members
) {
164 for (auto memb_name
: it
.second
)
165 if (design
->modules
[it
.first
]->count_id(memb_name
) == 0)
166 del_list
.push_back(memb_name
);
167 for (auto memb_name
: del_list
)
168 it
.second
.erase(memb_name
);
173 for (auto &it
: selected_members
)
174 if (it
.second
.size() == 0)
175 del_list
.push_back(it
.first
);
176 else if (it
.second
.size() == design
->modules
[it
.first
]->wires
.size() + design
->modules
[it
.first
]->memories
.size() +
177 design
->modules
[it
.first
]->cells
.size() + design
->modules
[it
.first
]->processes
.size())
178 add_list
.push_back(it
.first
);
179 for (auto mod_name
: del_list
)
180 selected_members
.erase(mod_name
);
181 for (auto mod_name
: add_list
) {
182 selected_members
.erase(mod_name
);
183 selected_modules
.insert(mod_name
);
186 if (selected_modules
.size() == design
->modules
.size()) {
187 full_selection
= true;
188 selected_modules
.clear();
189 selected_members
.clear();
193 RTLIL::Design::~Design()
195 for (auto it
= modules
.begin(); it
!= modules
.end(); it
++)
199 void RTLIL::Design::check()
202 for (auto &it
: modules
) {
203 assert(it
.first
== it
.second
->name
);
204 assert(it
.first
.size() > 0 && (it
.first
[0] == '\\' || it
.first
[0] == '$'));
210 void RTLIL::Design::optimize()
212 for (auto &it
: modules
)
213 it
.second
->optimize();
214 for (auto &it
: selection_stack
)
216 for (auto &it
: selection_vars
)
217 it
.second
.optimize(this);
220 bool RTLIL::Design::selected_module(RTLIL::IdString mod_name
) const
222 if (!selected_active_module
.empty() && mod_name
!= selected_active_module
)
224 if (selection_stack
.size() == 0)
226 return selection_stack
.back().selected_module(mod_name
);
229 bool RTLIL::Design::selected_whole_module(RTLIL::IdString mod_name
) const
231 if (!selected_active_module
.empty() && mod_name
!= selected_active_module
)
233 if (selection_stack
.size() == 0)
235 return selection_stack
.back().selected_whole_module(mod_name
);
238 bool RTLIL::Design::selected_member(RTLIL::IdString mod_name
, RTLIL::IdString memb_name
) const
240 if (!selected_active_module
.empty() && mod_name
!= selected_active_module
)
242 if (selection_stack
.size() == 0)
244 return selection_stack
.back().selected_member(mod_name
, memb_name
);
247 RTLIL::Module::~Module()
249 for (auto it
= wires
.begin(); it
!= wires
.end(); it
++)
251 for (auto it
= memories
.begin(); it
!= memories
.end(); it
++)
253 for (auto it
= cells
.begin(); it
!= cells
.end(); it
++)
255 for (auto it
= processes
.begin(); it
!= processes
.end(); it
++)
259 RTLIL::IdString
RTLIL::Module::derive(RTLIL::Design
*, std::map
<RTLIL::IdString
, RTLIL::Const
>)
261 log_error("Module `%s' is used with parameters but is not parametric!\n", id2cstr(name
));
264 void RTLIL::Module::update_auto_wires(std::map
<RTLIL::IdString
, int>)
266 log_error("Module `%s' has automatic wires bu no HDL backend to handle it!\n", id2cstr(name
));
269 size_t RTLIL::Module::count_id(RTLIL::IdString id
)
271 return wires
.count(id
) + memories
.count(id
) + cells
.count(id
) + processes
.count(id
);
274 void RTLIL::Module::check()
277 for (auto &it
: wires
) {
278 assert(it
.first
== it
.second
->name
);
279 assert(it
.first
.size() > 0 && (it
.first
[0] == '\\' || it
.first
[0] == '$'));
280 assert(it
.second
->width
>= 0);
281 assert(it
.second
->port_id
>= 0);
282 for (auto &it2
: it
.second
->attributes
) {
283 assert(it2
.first
.size() > 0 && (it2
.first
[0] == '\\' || it2
.first
[0] == '$'));
287 for (auto &it
: memories
) {
288 assert(it
.first
== it
.second
->name
);
289 assert(it
.first
.size() > 0 && (it
.first
[0] == '\\' || it
.first
[0] == '$'));
290 assert(it
.second
->width
>= 0);
291 assert(it
.second
->size
>= 0);
292 for (auto &it2
: it
.second
->attributes
) {
293 assert(it2
.first
.size() > 0 && (it2
.first
[0] == '\\' || it2
.first
[0] == '$'));
297 for (auto &it
: cells
) {
298 assert(it
.first
== it
.second
->name
);
299 assert(it
.first
.size() > 0 && (it
.first
[0] == '\\' || it
.first
[0] == '$'));
300 assert(it
.second
->type
.size() > 0 && (it
.second
->type
[0] == '\\' || it
.second
->type
[0] == '$'));
301 for (auto &it2
: it
.second
->connections
) {
302 assert(it2
.first
.size() > 0 && (it2
.first
[0] == '\\' || it2
.first
[0] == '$'));
305 for (auto &it2
: it
.second
->attributes
) {
306 assert(it2
.first
.size() > 0 && (it2
.first
[0] == '\\' || it2
.first
[0] == '$'));
308 for (auto &it2
: it
.second
->parameters
) {
309 assert(it2
.first
.size() > 0 && (it2
.first
[0] == '\\' || it2
.first
[0] == '$'));
313 for (auto &it
: processes
) {
314 assert(it
.first
== it
.second
->name
);
315 assert(it
.first
.size() > 0 && (it
.first
[0] == '\\' || it
.first
[0] == '$'));
316 // FIXME: More checks here..
319 for (auto &it
: connections
) {
320 assert(it
.first
.width
== it
.second
.width
);
325 for (auto &it
: attributes
) {
326 assert(it
.first
.size() > 0 && (it
.first
[0] == '\\' || it
.first
[0] == '$'));
331 void RTLIL::Module::optimize()
333 for (auto &it
: cells
)
334 it
.second
->optimize();
335 for (auto &it
: processes
)
336 it
.second
->optimize();
337 for (auto &it
: connections
) {
339 it
.second
.optimize();
343 void RTLIL::Module::add(RTLIL::Wire
*wire
) {
344 assert(!wire
->name
.empty());
345 assert(count_id(wire
->name
) == 0);
346 wires
[wire
->name
] = wire
;
349 void RTLIL::Module::add(RTLIL::Cell
*cell
) {
350 assert(!cell
->name
.empty());
351 assert(count_id(cell
->name
) == 0);
352 cells
[cell
->name
] = cell
;
365 RTLIL::Memory::Memory()
371 void RTLIL::Cell::optimize()
373 for (auto &it
: connections
)
374 it
.second
.optimize();
377 RTLIL::SigChunk::SigChunk()
384 RTLIL::SigChunk::SigChunk(const RTLIL::Const
&data
)
388 width
= data
.bits
.size();
392 RTLIL::SigChunk::SigChunk(RTLIL::Wire
*wire
, int width
, int offset
)
395 this->width
= width
>= 0 ? width
: wire
->width
;
396 this->offset
= offset
;
399 RTLIL::SigChunk::SigChunk(const std::string
&str
)
402 data
= RTLIL::Const(str
);
403 width
= data
.bits
.size();
407 RTLIL::SigChunk::SigChunk(int val
, int width
)
410 data
= RTLIL::Const(val
, width
);
411 this->width
= data
.bits
.size();
415 RTLIL::SigChunk::SigChunk(RTLIL::State bit
, int width
)
418 data
= RTLIL::Const(bit
, width
);
419 this->width
= data
.bits
.size();
423 RTLIL::SigChunk
RTLIL::SigChunk::extract(int offset
, int length
) const
428 ret
.offset
= this->offset
+ offset
;
431 for (int i
= 0; i
< length
; i
++)
432 ret
.data
.bits
.push_back(data
.bits
[offset
+i
]);
438 bool RTLIL::SigChunk::operator <(const RTLIL::SigChunk
&other
) const
440 if (wire
&& other
.wire
)
441 if (wire
->name
!= other
.wire
->name
)
442 return wire
->name
< other
.wire
->name
;
443 if (wire
!= other
.wire
)
444 return wire
< other
.wire
;
446 if (offset
!= other
.offset
)
447 return offset
< other
.offset
;
449 if (width
!= other
.width
)
450 return width
< other
.width
;
452 if (data
.bits
!= other
.data
.bits
)
453 return data
.bits
< other
.data
.bits
;
458 bool RTLIL::SigChunk::operator ==(const RTLIL::SigChunk
&other
) const
460 if (wire
!= other
.wire
|| width
!= other
.width
|| offset
!= other
.offset
)
462 if (data
.bits
!= other
.data
.bits
)
467 bool RTLIL::SigChunk::operator !=(const RTLIL::SigChunk
&other
) const
474 RTLIL::SigSpec::SigSpec()
479 RTLIL::SigSpec::SigSpec(const RTLIL::Const
&data
)
481 chunks
.push_back(RTLIL::SigChunk(data
));
482 width
= chunks
.back().width
;
486 RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk
&chunk
)
488 chunks
.push_back(chunk
);
489 width
= chunks
.back().width
;
493 RTLIL::SigSpec::SigSpec(RTLIL::Wire
*wire
, int width
, int offset
)
495 chunks
.push_back(RTLIL::SigChunk(wire
, width
, offset
));
496 this->width
= chunks
.back().width
;
500 RTLIL::SigSpec::SigSpec(const std::string
&str
)
502 chunks
.push_back(RTLIL::SigChunk(str
));
503 width
= chunks
.back().width
;
507 RTLIL::SigSpec::SigSpec(int val
, int width
)
509 chunks
.push_back(RTLIL::SigChunk(val
, width
));
510 this->width
= chunks
.back().width
;
514 RTLIL::SigSpec::SigSpec(RTLIL::State bit
, int width
)
516 chunks
.push_back(RTLIL::SigChunk(bit
, width
));
517 this->width
= chunks
.back().width
;
521 void RTLIL::SigSpec::expand()
523 std::vector
<RTLIL::SigChunk
> new_chunks
;
524 for (size_t i
= 0; i
< chunks
.size(); i
++) {
525 assert(chunks
[i
].data
.str
.empty());
526 for (int j
= 0; j
< chunks
[i
].width
; j
++)
527 new_chunks
.push_back(chunks
[i
].extract(j
, 1));
529 chunks
.swap(new_chunks
);
533 void RTLIL::SigSpec::optimize()
535 for (size_t i
= 0; i
< chunks
.size(); i
++) {
536 if (chunks
[i
].wire
&& chunks
[i
].wire
->auto_width
)
538 if (chunks
[i
].width
== 0)
539 chunks
.erase(chunks
.begin()+i
--);
541 for (size_t i
= 1; i
< chunks
.size(); i
++) {
542 RTLIL::SigChunk
&ch1
= chunks
[i
-1];
543 RTLIL::SigChunk
&ch2
= chunks
[i
];
544 if (ch1
.wire
&& ch1
.wire
->auto_width
)
546 if (ch2
.wire
&& ch2
.wire
->auto_width
)
548 if (ch1
.wire
== ch2
.wire
) {
549 if (ch1
.wire
!= NULL
&& ch1
.offset
+ch1
.width
== ch2
.offset
) {
550 ch1
.width
+= ch2
.width
;
551 goto merged_with_next_chunk
;
553 if (ch1
.wire
== NULL
&& ch1
.data
.str
.empty() == ch2
.data
.str
.empty()) {
554 ch1
.data
.str
= ch2
.data
.str
+ ch1
.data
.str
;
555 ch1
.data
.bits
.insert(ch1
.data
.bits
.end(), ch2
.data
.bits
.begin(), ch2
.data
.bits
.end());
556 ch1
.width
+= ch2
.width
;
557 goto merged_with_next_chunk
;
561 merged_with_next_chunk
:
562 chunks
.erase(chunks
.begin()+i
);
569 bool RTLIL::SigChunk::compare(const RTLIL::SigChunk
&a
, const RTLIL::SigChunk
&b
)
571 if (a
.wire
!= b
.wire
) {
572 if (a
.wire
== NULL
|| b
.wire
== NULL
)
573 return a
.wire
< b
.wire
;
574 else if (a
.wire
->name
!= b
.wire
->name
)
575 return a
.wire
->name
< b
.wire
->name
;
577 return a
.wire
< b
.wire
;
579 if (a
.offset
!= b
.offset
)
580 return a
.offset
< b
.offset
;
581 if (a
.width
!= b
.width
)
582 return a
.width
< b
.width
;
583 return a
.data
.bits
< b
.data
.bits
;
586 void RTLIL::SigSpec::sort()
589 std::sort(chunks
.begin(), chunks
.end(), RTLIL::SigChunk::compare
);
593 void RTLIL::SigSpec::sort_and_unify()
596 std::sort(chunks
.begin(), chunks
.end(), RTLIL::SigChunk::compare
);
597 for (size_t i
= 1; i
< chunks
.size(); i
++) {
598 RTLIL::SigChunk
&ch1
= chunks
[i
-1];
599 RTLIL::SigChunk
&ch2
= chunks
[i
];
600 if (!RTLIL::SigChunk::compare(ch1
, ch2
) && !RTLIL::SigChunk::compare(ch2
, ch1
)) {
601 chunks
.erase(chunks
.begin()+i
);
602 width
-= chunks
[i
].width
;
609 void RTLIL::SigSpec::replace(const RTLIL::SigSpec
&pattern
, const RTLIL::SigSpec
&with
)
611 replace(pattern
, with
, this);
614 void RTLIL::SigSpec::replace(const RTLIL::SigSpec
&pattern
, const RTLIL::SigSpec
&with
, RTLIL::SigSpec
*other
) const
616 int pos
= 0, restart_pos
= 0;
617 assert(other
== NULL
|| width
== other
->width
);
618 for (size_t i
= 0; i
< chunks
.size(); i
++) {
620 const RTLIL::SigChunk
&ch1
= chunks
[i
];
621 if (chunks
[i
].wire
!= NULL
&& pos
>= restart_pos
)
622 for (size_t j
= 0, poff
= 0; j
< pattern
.chunks
.size(); j
++) {
623 const RTLIL::SigChunk
&ch2
= pattern
.chunks
[j
];
624 assert(ch2
.wire
!= NULL
);
625 if (ch1
.wire
== ch2
.wire
) {
626 int lower
= std::max(ch1
.offset
, ch2
.offset
);
627 int upper
= std::min(ch1
.offset
+ ch1
.width
, ch2
.offset
+ ch2
.width
);
629 restart_pos
= pos
+upper
-ch1
.offset
;
630 other
->replace(pos
+lower
-ch1
.offset
, with
.extract(poff
+lower
-ch2
.offset
, upper
-lower
));
636 pos
+= chunks
[i
].width
;
641 void RTLIL::SigSpec::remove(const RTLIL::SigSpec
&pattern
)
643 remove2(pattern
, NULL
);
646 void RTLIL::SigSpec::remove(const RTLIL::SigSpec
&pattern
, RTLIL::SigSpec
*other
) const
648 RTLIL::SigSpec tmp
= *this;
649 tmp
.remove2(pattern
, other
);
652 void RTLIL::SigSpec::remove2(const RTLIL::SigSpec
&pattern
, RTLIL::SigSpec
*other
)
655 assert(other
== NULL
|| width
== other
->width
);
656 for (size_t i
= 0; i
< chunks
.size(); i
++) {
658 const RTLIL::SigChunk
&ch1
= chunks
[i
];
659 if (chunks
[i
].wire
!= NULL
)
660 for (size_t j
= 0; j
< pattern
.chunks
.size(); j
++) {
661 const RTLIL::SigChunk
&ch2
= pattern
.chunks
[j
];
662 assert(ch2
.wire
!= NULL
);
663 if (ch1
.wire
== ch2
.wire
) {
664 int lower
= std::max(ch1
.offset
, ch2
.offset
);
665 int upper
= std::min(ch1
.offset
+ ch1
.width
, ch2
.offset
+ ch2
.width
);
668 other
->remove(pos
+lower
-ch1
.offset
, upper
-lower
);
669 remove(pos
+lower
-ch1
.offset
, upper
-lower
);
670 if (i
== chunks
.size())
676 pos
+= chunks
[i
].width
;
681 RTLIL::SigSpec
RTLIL::SigSpec::extract(RTLIL::SigSpec pattern
, RTLIL::SigSpec
*other
) const
685 pattern
.sort_and_unify();
686 assert(other
== NULL
|| width
== other
->width
);
687 for (size_t i
= 0; i
< chunks
.size(); i
++) {
688 const RTLIL::SigChunk
&ch1
= chunks
[i
];
689 if (chunks
[i
].wire
!= NULL
)
690 for (size_t j
= 0; j
< pattern
.chunks
.size(); j
++) {
691 RTLIL::SigChunk
&ch2
= pattern
.chunks
[j
];
692 assert(ch2
.wire
!= NULL
);
693 if (ch1
.wire
== ch2
.wire
) {
694 int lower
= std::max(ch1
.offset
, ch2
.offset
);
695 int upper
= std::min(ch1
.offset
+ ch1
.width
, ch2
.offset
+ ch2
.width
);
698 ret
.append(other
->extract(pos
+lower
-ch1
.offset
, upper
-lower
));
700 ret
.append(extract(pos
+lower
-ch1
.offset
, upper
-lower
));
704 pos
+= chunks
[i
].width
;
710 void RTLIL::SigSpec::replace(int offset
, const RTLIL::SigSpec
&with
)
714 assert(with
.width
>= 0);
715 assert(offset
+with
.width
<= width
);
716 remove(offset
, with
.width
);
717 for (size_t i
= 0; i
< chunks
.size(); i
++) {
719 chunks
.insert(chunks
.begin()+i
, with
.chunks
.begin(), with
.chunks
.end());
724 pos
+= chunks
[i
].width
;
726 assert(pos
== offset
);
727 chunks
.insert(chunks
.end(), with
.chunks
.begin(), with
.chunks
.end());
732 void RTLIL::SigSpec::remove_const()
734 for (size_t i
= 0; i
< chunks
.size(); i
++) {
735 if (chunks
[i
].wire
!= NULL
)
737 width
-= chunks
[i
].width
;
738 chunks
.erase(chunks
.begin() + (i
--));
743 void RTLIL::SigSpec::remove(int offset
, int length
)
748 assert(offset
+length
<= width
);
749 for (size_t i
= 0; i
< chunks
.size(); i
++) {
750 int orig_width
= chunks
[i
].width
;
751 if (pos
+chunks
[i
].width
> offset
&& pos
< offset
+length
) {
752 int off
= offset
- pos
;
758 if (len
> chunks
[i
].width
-off
)
759 len
= chunks
[i
].width
-off
;
760 RTLIL::SigChunk lsb_chunk
= chunks
[i
].extract(0, off
);
761 RTLIL::SigChunk msb_chunk
= chunks
[i
].extract(off
+len
, chunks
[i
].width
-off
-len
);
762 if (lsb_chunk
.width
== 0 && msb_chunk
.width
== 0) {
763 chunks
.erase(chunks
.begin()+i
);
765 } else if (lsb_chunk
.width
== 0 && msb_chunk
.width
!= 0) {
766 chunks
[i
] = msb_chunk
;
767 } else if (lsb_chunk
.width
!= 0 && msb_chunk
.width
== 0) {
768 chunks
[i
] = lsb_chunk
;
769 } else if (lsb_chunk
.width
!= 0 && msb_chunk
.width
!= 0) {
770 chunks
[i
] = lsb_chunk
;
771 chunks
.insert(chunks
.begin()+i
+1, msb_chunk
);
782 RTLIL::SigSpec
RTLIL::SigSpec::extract(int offset
, int length
) const
788 assert(offset
+length
<= width
);
789 for (size_t i
= 0; i
< chunks
.size(); i
++) {
790 if (pos
+chunks
[i
].width
> offset
&& pos
< offset
+length
) {
791 int off
= offset
- pos
;
797 if (len
> chunks
[i
].width
-off
)
798 len
= chunks
[i
].width
-off
;
799 ret
.chunks
.push_back(chunks
[i
].extract(off
, len
));
804 pos
+= chunks
[i
].width
;
811 void RTLIL::SigSpec::append(const RTLIL::SigSpec
&signal
)
813 for (size_t i
= 0; i
< signal
.chunks
.size(); i
++) {
814 chunks
.push_back(signal
.chunks
[i
]);
815 width
+= signal
.chunks
[i
].width
;
820 bool RTLIL::SigSpec::combine(RTLIL::SigSpec signal
, RTLIL::State freeState
, bool override
)
822 bool no_collisions
= true;
824 assert(width
== signal
.width
);
828 for (size_t i
= 0; i
< chunks
.size(); i
++) {
829 bool self_free
= chunks
[i
].wire
== NULL
&& chunks
[i
].data
.bits
[0] == freeState
;
830 bool other_free
= signal
.chunks
[i
].wire
== NULL
&& signal
.chunks
[i
].data
.bits
[0] == freeState
;
831 if (!self_free
&& !other_free
) {
833 chunks
[i
] = signal
.chunks
[i
];
835 chunks
[i
] = RTLIL::SigChunk(RTLIL::State::Sx
, 1);
836 no_collisions
= false;
838 if (self_free
&& !other_free
)
839 chunks
[i
] = signal
.chunks
[i
];
843 return no_collisions
;
846 void RTLIL::SigSpec::extend(int width
, bool is_signed
)
848 if (this->width
> width
)
849 remove(width
, this->width
- width
);
851 if (this->width
< width
) {
852 RTLIL::SigSpec padding
= this->width
> 0 ? extract(this->width
- 1, 1) : RTLIL::SigSpec(RTLIL::State::S0
);
853 if (!is_signed
&& padding
!= RTLIL::SigSpec(RTLIL::State::Sx
) && padding
!= RTLIL::SigSpec(RTLIL::State::Sz
) &&
854 padding
!= RTLIL::SigSpec(RTLIL::State::Sa
) && padding
!= RTLIL::SigSpec(RTLIL::State::Sm
))
855 padding
= RTLIL::SigSpec(RTLIL::State::S0
);
856 while (this->width
< width
)
863 void RTLIL::SigSpec::check() const
866 for (size_t i
= 0; i
< chunks
.size(); i
++) {
867 const RTLIL::SigChunk chunk
= chunks
[i
];
868 if (chunk
.wire
== NULL
) {
869 assert(chunk
.offset
== 0);
870 assert(chunk
.data
.bits
.size() == (size_t)chunk
.width
);
871 assert(chunk
.data
.str
.size() == 0 || chunk
.data
.str
.size()*8 == chunk
.data
.bits
.size());
873 assert(chunk
.offset
>= 0);
874 assert(chunk
.width
>= 0);
875 assert(chunk
.offset
+ chunk
.width
<= chunk
.wire
->width
);
876 assert(chunk
.data
.bits
.size() == 0);
877 assert(chunk
.data
.str
.size() == 0);
884 bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec
&other
) const
886 if (width
!= other
.width
)
887 return width
< other
.width
;
889 RTLIL::SigSpec a
= *this, b
= other
;
893 if (a
.chunks
.size() != b
.chunks
.size())
894 return a
.chunks
.size() < b
.chunks
.size();
896 for (size_t i
= 0; i
< a
.chunks
.size(); i
++)
897 if (a
.chunks
[i
] != b
.chunks
[i
])
898 return a
.chunks
[i
] < b
.chunks
[i
];
903 bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec
&other
) const
905 if (width
!= other
.width
)
908 RTLIL::SigSpec a
= *this, b
= other
;
912 if (a
.chunks
.size() != b
.chunks
.size())
915 for (size_t i
= 0; i
< a
.chunks
.size(); i
++)
916 if (a
.chunks
[i
] != b
.chunks
[i
])
922 bool RTLIL::SigSpec::operator !=(const RTLIL::SigSpec
&other
) const
929 bool RTLIL::SigSpec::is_fully_const() const
931 for (auto it
= chunks
.begin(); it
!= chunks
.end(); it
++)
932 if (it
->width
> 0 && it
->wire
!= NULL
)
937 bool RTLIL::SigSpec::is_fully_def() const
939 for (auto it
= chunks
.begin(); it
!= chunks
.end(); it
++) {
940 if (it
->width
> 0 && it
->wire
!= NULL
)
942 for (size_t i
= 0; i
< it
->data
.bits
.size(); i
++)
943 if (it
->data
.bits
[i
] != RTLIL::State::S0
&& it
->data
.bits
[i
] != RTLIL::State::S1
)
949 bool RTLIL::SigSpec::is_fully_undef() const
951 for (auto it
= chunks
.begin(); it
!= chunks
.end(); it
++) {
952 if (it
->width
> 0 && it
->wire
!= NULL
)
954 for (size_t i
= 0; i
< it
->data
.bits
.size(); i
++)
955 if (it
->data
.bits
[i
] != RTLIL::State::Sx
&& it
->data
.bits
[i
] != RTLIL::State::Sz
)
961 bool RTLIL::SigSpec::has_marked_bits() const
963 for (auto it
= chunks
.begin(); it
!= chunks
.end(); it
++)
964 if (it
->width
> 0 && it
->wire
== NULL
) {
965 for (size_t i
= 0; i
< it
->data
.bits
.size(); i
++)
966 if (it
->data
.bits
[i
] == RTLIL::State::Sm
)
972 bool RTLIL::SigSpec::as_bool() const
974 assert(is_fully_const());
978 return sig
.chunks
[0].data
.as_bool();
982 int RTLIL::SigSpec::as_int() const
984 assert(is_fully_const());
988 return sig
.chunks
[0].data
.as_int();
992 std::string
RTLIL::SigSpec::as_string() const
995 for (size_t i
= chunks
.size(); i
> 0; i
--) {
996 const RTLIL::SigChunk
&chunk
= chunks
[i
-1];
997 if (chunk
.wire
!= NULL
)
998 for (int j
= 0; j
< chunk
.width
; j
++)
1001 str
+= chunk
.data
.as_string();
1006 RTLIL::Const
RTLIL::SigSpec::as_const() const
1008 assert(is_fully_const());
1009 SigSpec sig
= *this;
1012 return sig
.chunks
[0].data
;
1013 return RTLIL::Const();
1016 bool RTLIL::SigSpec::match(std::string pattern
) const
1018 std::string str
= as_string();
1019 assert(pattern
.size() == str
.size());
1021 for (size_t i
= 0; i
< pattern
.size(); i
++) {
1022 if (pattern
[i
] == ' ')
1024 if (pattern
[i
] == '*') {
1025 if (str
[i
] != 'z' && str
[i
] != 'x')
1029 if (pattern
[i
] != str
[i
])
1036 RTLIL::CaseRule::~CaseRule()
1038 for (auto it
= switches
.begin(); it
!= switches
.end(); it
++)
1042 void RTLIL::CaseRule::optimize()
1044 for (auto it
: switches
)
1046 for (auto &it
: compare
)
1048 for (auto &it
: actions
) {
1049 it
.first
.optimize();
1050 it
.second
.optimize();
1054 RTLIL::SwitchRule::~SwitchRule()
1056 for (auto it
= cases
.begin(); it
!= cases
.end(); it
++)
1060 void RTLIL::SwitchRule::optimize()
1063 for (auto it
: cases
)
1067 void RTLIL::SyncRule::optimize()
1070 for (auto &it
: actions
) {
1071 it
.first
.optimize();
1072 it
.second
.optimize();
1076 RTLIL::Process::~Process()
1078 for (auto it
= syncs
.begin(); it
!= syncs
.end(); it
++)
1082 void RTLIL::Process::optimize()
1084 root_case
.optimize();
1085 for (auto it
: syncs
)