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/utils.h"
25 PRIVATE_NAMESPACE_BEGIN
27 struct HierDirtyFlags
;
29 static pool
<string
> reserved_cids
;
30 static dict
<IdString
, string
> id2cid
;
32 static string
cid(IdString id
)
34 if (id2cid
.count(id
) == 0)
37 if (GetSize(s
) < 2) log_abort();
42 if ('0' <= s
[0] && s
[0] <= '9') {
46 for (int i
= 0; i
< GetSize(s
); i
++) {
47 if ('0' <= s
[i
] && s
[i
] <= '9') continue;
48 if ('A' <= s
[i
] && s
[i
] <= 'Z') continue;
49 if ('a' <= s
[i
] && s
[i
] <= 'z') continue;
53 while (reserved_cids
.count(s
))
56 reserved_cids
.insert(s
);
68 HierDirtyFlags
*parent
;
69 pool
<SigBit
> dirty_bits
;
70 pool
<Cell
*> dirty_cells
;
71 pool
<SigBit
> sticky_dirty_bits
;
72 dict
<IdString
, HierDirtyFlags
*> children
;
73 string prefix
, log_prefix
;
75 HierDirtyFlags(Module
*module
, IdString hiername
, HierDirtyFlags
*parent
, const string
&prefix
, const string
&log_prefix
) :
76 dirty(0), module(module
), hiername(hiername
), parent(parent
), prefix(prefix
), log_prefix(log_prefix
)
78 for (Cell
*cell
: module
->cells()) {
79 Module
*mod
= module
->design
->module(cell
->type
);
80 if (mod
) children
[cell
->name
] = new HierDirtyFlags(mod
, cell
->name
, this,
81 prefix
+ cid(cell
->name
) + ".", log_prefix
+ "." + prefix
+ log_id(cell
->name
));
87 for (auto &child
: children
)
91 void set_dirty(SigBit bit
)
93 if (dirty_bits
.count(bit
))
96 dirty_bits
.insert(bit
);
97 sticky_dirty_bits
.insert(bit
);
99 HierDirtyFlags
*p
= this;
100 while (p
!= nullptr) {
106 void unset_dirty(SigBit bit
)
108 if (dirty_bits
.count(bit
) == 0)
111 dirty_bits
.erase(bit
);
113 HierDirtyFlags
*p
= this;
114 while (p
!= nullptr) {
116 log_assert(p
->dirty
>= 0);
121 void set_dirty(Cell
*cell
)
123 if (dirty_cells
.count(cell
))
126 dirty_cells
.insert(cell
);
128 HierDirtyFlags
*p
= this;
129 while (p
!= nullptr) {
135 void unset_dirty(Cell
*cell
)
137 if (dirty_cells
.count(cell
) == 0)
140 dirty_cells
.erase(cell
);
142 HierDirtyFlags
*p
= this;
143 while (p
!= nullptr) {
145 log_assert(p
->dirty
>= 0);
153 bool verbose
= false;
154 int max_uintsize
= 32;
157 dict
<Module
*, SigMap
> sigmaps
;
159 vector
<string
> signal_declarations
;
160 pool
<int> generated_sigtypes
;
162 vector
<string
> util_declarations
;
163 pool
<string
> generated_utils
;
165 vector
<string
> struct_declarations
;
166 pool
<IdString
> generated_structs
;
168 vector
<string
> funct_declarations
;
170 dict
<Module
*, dict
<SigBit
, pool
<tuple
<Cell
*, IdString
, int>>>> bit2cell
;
171 dict
<Module
*, dict
<SigBit
, pool
<SigBit
>>> bit2output
;
172 dict
<Module
*, pool
<SigBit
>> driven_bits
;
174 dict
<Cell
*, int> topoidx
;
176 pool
<string
> activated_cells
;
177 pool
<string
> reactivated_cells
;
179 SimplecWorker(Design
*design
) : design(design
)
183 string
sigtype(int n
)
185 string struct_name
= stringf("signal%d_t", n
);
187 if (generated_sigtypes
.count(n
) == 0)
189 signal_declarations
.push_back("");
190 signal_declarations
.push_back(stringf("#ifndef YOSYS_SIMPLEC_SIGNAL%d_T", n
));
191 signal_declarations
.push_back(stringf("#define YOSYS_SIMPLEC_SIGNAL%d_T", n
));
192 signal_declarations
.push_back(stringf("typedef struct {"));
194 for (int k
= 8; k
<= max_uintsize
; k
= 2*k
)
195 if (n
<= k
&& k
<= max_uintsize
) {
196 signal_declarations
.push_back(stringf(" uint%d_t value_%d_0 : %d;", k
, n
-1, n
));
200 for (int k
= 0; k
< n
; k
+= max_uintsize
) {
201 int bits
= std::min(max_uintsize
, n
-k
);
202 signal_declarations
.push_back(stringf(" uint%d_t value_%d_%d : %d;", max_uintsize
, k
+bits
-1, k
, bits
));
206 signal_declarations
.push_back(stringf("} signal%d_t;", n
));
207 signal_declarations
.push_back(stringf("#endif"));
208 generated_sigtypes
.insert(n
);
214 void util_ifdef_guard(string s
)
216 for (int i
= 0; i
< GetSize(s
); i
++)
217 if ('a' <= s
[i
] && s
[i
] <= 'z')
220 util_declarations
.push_back("");
221 util_declarations
.push_back(stringf("#ifndef %s", s
.c_str()));
222 util_declarations
.push_back(stringf("#define %s", s
.c_str()));
225 string
util_get_bit(const string
&signame
, int n
, int idx
)
227 if (n
== 1 && idx
== 0)
228 return signame
+ ".value_0_0";
230 string util_name
= stringf("yosys_simplec_get_bit_%d_of_%d", idx
, n
);
232 if (generated_utils
.count(util_name
) == 0)
234 util_ifdef_guard(util_name
);
235 util_declarations
.push_back(stringf("static inline bool %s(const %s *sig)", util_name
.c_str(), sigtype(n
).c_str()));
236 util_declarations
.push_back(stringf("{"));
238 int word_idx
= idx
/ max_uintsize
, word_offset
= idx
% max_uintsize
;
239 string value_name
= stringf("value_%d_%d", std::min(n
-1, (word_idx
+1)*max_uintsize
-1), word_idx
*max_uintsize
);
241 util_declarations
.push_back(stringf(" return (sig->%s >> %d) & 1;", value_name
.c_str(), word_offset
));
243 util_declarations
.push_back(stringf("}"));
244 util_declarations
.push_back(stringf("#endif"));
245 generated_utils
.insert(util_name
);
248 return stringf("%s(&%s)", util_name
.c_str(), signame
.c_str());
251 string
util_set_bit(const string
&signame
, int n
, int idx
, const string
&expr
)
253 if (n
== 1 && idx
== 0)
254 return stringf(" %s.value_0_0 = %s;", signame
.c_str(), expr
.c_str());
256 string util_name
= stringf("yosys_simplec_set_bit_%d_of_%d", idx
, n
);
258 if (generated_utils
.count(util_name
) == 0)
260 util_ifdef_guard(util_name
);
261 util_declarations
.push_back(stringf("static inline void %s(%s *sig, bool value)", util_name
.c_str(), sigtype(n
).c_str()));
262 util_declarations
.push_back(stringf("{"));
264 int word_idx
= idx
/ max_uintsize
, word_offset
= idx
% max_uintsize
;
265 string value_name
= stringf("value_%d_%d", std::min(n
-1, (word_idx
+1)*max_uintsize
-1), word_idx
*max_uintsize
);
268 util_declarations
.push_back(stringf(" if (value)"));
269 util_declarations
.push_back(stringf(" sig->%s |= 1UL << %d;", value_name
.c_str(), word_offset
));
270 util_declarations
.push_back(stringf(" else"));
271 util_declarations
.push_back(stringf(" sig->%s &= ~(1UL << %d);", value_name
.c_str(), word_offset
));
273 util_declarations
.push_back(stringf(" sig->%s = (sig->%s & ~((uint%d_t)1 << %d)) | ((uint%d_t)value << %d);",
274 value_name
.c_str(), value_name
.c_str(), max_uintsize
, word_offset
, max_uintsize
, word_offset
));
277 util_declarations
.push_back(stringf("}"));
278 util_declarations
.push_back(stringf("#endif"));
279 generated_utils
.insert(util_name
);
282 return stringf(" %s(&%s, %s);", util_name
.c_str(), signame
.c_str(), expr
.c_str());
285 void create_module_struct(Module
*mod
)
287 if (generated_structs
.count(mod
->name
))
290 generated_structs
.insert(mod
->name
);
291 sigmaps
[mod
].set(mod
);
293 for (Wire
*w
: mod
->wires())
296 for (auto bit
: SigSpec(w
))
297 bit2output
[mod
][sigmaps
.at(mod
)(bit
)].insert(bit
);
300 for (Cell
*c
: mod
->cells())
302 for (auto &conn
: c
->connections())
304 if (!c
->input(conn
.first
)) {
305 for (auto bit
: sigmaps
.at(mod
)(conn
.second
))
306 driven_bits
[mod
].insert(bit
);
311 for (auto bit
: sigmaps
.at(mod
)(conn
.second
))
312 bit2cell
[mod
][bit
].insert(tuple
<Cell
*, IdString
, int>(c
, conn
.first
, idx
++));
315 if (design
->module(c
->type
))
316 create_module_struct(design
->module(c
->type
));
319 TopoSort
<IdString
> topo
;
321 for (Cell
*c
: mod
->cells())
325 for (auto &conn
: c
->connections())
327 if (!c
->input(conn
.first
))
330 for (auto bit
: sigmaps
.at(mod
)(conn
.second
))
331 for (auto &it
: bit2cell
[mod
][bit
])
332 topo
.edge(c
->name
, std::get
<0>(it
)->name
);
336 topo
.analyze_loops
= false;
339 for (int i
= 0; i
< GetSize(topo
.sorted
); i
++)
340 topoidx
[mod
->cell(topo
.sorted
[i
])] = i
;
342 string ifdef_name
= stringf("yosys_simplec_%s_state_t", cid(mod
->name
).c_str());
344 for (int i
= 0; i
< GetSize(ifdef_name
); i
++)
345 if ('a' <= ifdef_name
[i
] && ifdef_name
[i
] <= 'z')
346 ifdef_name
[i
] -= 'a' - 'A';
348 struct_declarations
.push_back("");
349 struct_declarations
.push_back(stringf("#ifndef %s", ifdef_name
.c_str()));
350 struct_declarations
.push_back(stringf("#define %s", ifdef_name
.c_str()));
351 struct_declarations
.push_back(stringf("struct %s_state_t", cid(mod
->name
).c_str()));
352 struct_declarations
.push_back("{");
354 struct_declarations
.push_back(" // Input Ports");
355 for (Wire
*w
: mod
->wires())
357 struct_declarations
.push_back(stringf(" %s %s; // %s", sigtype(w
->width
).c_str(), cid(w
->name
).c_str(), log_id(w
)));
359 struct_declarations
.push_back("");
360 struct_declarations
.push_back(" // Output Ports");
361 for (Wire
*w
: mod
->wires())
362 if (!w
->port_input
&& w
->port_output
)
363 struct_declarations
.push_back(stringf(" %s %s; // %s", sigtype(w
->width
).c_str(), cid(w
->name
).c_str(), log_id(w
)));
365 struct_declarations
.push_back("");
366 struct_declarations
.push_back(" // Internal Wires");
367 for (Wire
*w
: mod
->wires())
368 if (!w
->port_input
&& !w
->port_output
)
369 struct_declarations
.push_back(stringf(" %s %s; // %s", sigtype(w
->width
).c_str(), cid(w
->name
).c_str(), log_id(w
)));
371 for (Cell
*c
: mod
->cells())
372 if (design
->module(c
->type
))
373 struct_declarations
.push_back(stringf(" struct %s_state_t %s; // %s", cid(c
->type
).c_str(), cid(c
->name
).c_str(), log_id(c
)));
375 struct_declarations
.push_back(stringf("};"));
376 struct_declarations
.push_back("#endif");
379 void eval_cell(HierDirtyFlags
*work
, Cell
*cell
)
381 if (cell
->type
.in(ID($_BUF_
), ID($_NOT_
)))
383 SigBit a
= sigmaps
.at(work
->module
)(cell
->getPort(ID::A
));
384 SigBit y
= sigmaps
.at(work
->module
)(cell
->getPort(ID::Y
));
386 string a_expr
= a
.wire
? util_get_bit(work
->prefix
+ cid(a
.wire
->name
), a
.wire
->width
, a
.offset
) : a
.data
? "1" : "0";
389 if (cell
->type
== ID($_BUF_
)) expr
= a_expr
;
390 if (cell
->type
== ID($_NOT_
)) expr
= "!" + a_expr
;
393 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(y
.wire
->name
), y
.wire
->width
, y
.offset
, expr
) +
394 stringf(" // %s (%s)", log_id(cell
), log_id(cell
->type
)));
400 if (cell
->type
.in(ID($_AND_
), ID($_NAND_
), ID($_OR_
), ID($_NOR_
), ID($_XOR_
), ID($_XNOR_
), ID($_ANDNOT_
), ID($_ORNOT_
)))
402 SigBit a
= sigmaps
.at(work
->module
)(cell
->getPort(ID::A
));
403 SigBit b
= sigmaps
.at(work
->module
)(cell
->getPort(ID::B
));
404 SigBit y
= sigmaps
.at(work
->module
)(cell
->getPort(ID::Y
));
406 string a_expr
= a
.wire
? util_get_bit(work
->prefix
+ cid(a
.wire
->name
), a
.wire
->width
, a
.offset
) : a
.data
? "1" : "0";
407 string b_expr
= b
.wire
? util_get_bit(work
->prefix
+ cid(b
.wire
->name
), b
.wire
->width
, b
.offset
) : b
.data
? "1" : "0";
410 if (cell
->type
== ID($_AND_
)) expr
= stringf("%s & %s", a_expr
.c_str(), b_expr
.c_str());
411 if (cell
->type
== ID($_NAND_
)) expr
= stringf("!(%s & %s)", a_expr
.c_str(), b_expr
.c_str());
412 if (cell
->type
== ID($_OR_
)) expr
= stringf("%s | %s", a_expr
.c_str(), b_expr
.c_str());
413 if (cell
->type
== ID($_NOR_
)) expr
= stringf("!(%s | %s)", a_expr
.c_str(), b_expr
.c_str());
414 if (cell
->type
== ID($_XOR_
)) expr
= stringf("%s ^ %s", a_expr
.c_str(), b_expr
.c_str());
415 if (cell
->type
== ID($_XNOR_
)) expr
= stringf("!(%s ^ %s)", a_expr
.c_str(), b_expr
.c_str());
416 if (cell
->type
== ID($_ANDNOT_
)) expr
= stringf("%s & (!%s)", a_expr
.c_str(), b_expr
.c_str());
417 if (cell
->type
== ID($_ORNOT_
)) expr
= stringf("%s | (!%s)", a_expr
.c_str(), b_expr
.c_str());
420 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(y
.wire
->name
), y
.wire
->width
, y
.offset
, expr
) +
421 stringf(" // %s (%s)", log_id(cell
), log_id(cell
->type
)));
427 if (cell
->type
.in(ID($_AOI3_
), ID($_OAI3_
)))
429 SigBit a
= sigmaps
.at(work
->module
)(cell
->getPort(ID::A
));
430 SigBit b
= sigmaps
.at(work
->module
)(cell
->getPort(ID::B
));
431 SigBit c
= sigmaps
.at(work
->module
)(cell
->getPort(ID::C
));
432 SigBit y
= sigmaps
.at(work
->module
)(cell
->getPort(ID::Y
));
434 string a_expr
= a
.wire
? util_get_bit(work
->prefix
+ cid(a
.wire
->name
), a
.wire
->width
, a
.offset
) : a
.data
? "1" : "0";
435 string b_expr
= b
.wire
? util_get_bit(work
->prefix
+ cid(b
.wire
->name
), b
.wire
->width
, b
.offset
) : b
.data
? "1" : "0";
436 string c_expr
= c
.wire
? util_get_bit(work
->prefix
+ cid(c
.wire
->name
), c
.wire
->width
, c
.offset
) : c
.data
? "1" : "0";
439 if (cell
->type
== ID($_AOI3_
)) expr
= stringf("!((%s & %s) | %s)", a_expr
.c_str(), b_expr
.c_str(), c_expr
.c_str());
440 if (cell
->type
== ID($_OAI3_
)) expr
= stringf("!((%s | %s) & %s)", a_expr
.c_str(), b_expr
.c_str(), c_expr
.c_str());
443 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(y
.wire
->name
), y
.wire
->width
, y
.offset
, expr
) +
444 stringf(" // %s (%s)", log_id(cell
), log_id(cell
->type
)));
450 if (cell
->type
.in(ID($_AOI4_
), ID($_OAI4_
)))
452 SigBit a
= sigmaps
.at(work
->module
)(cell
->getPort(ID::A
));
453 SigBit b
= sigmaps
.at(work
->module
)(cell
->getPort(ID::B
));
454 SigBit c
= sigmaps
.at(work
->module
)(cell
->getPort(ID::C
));
455 SigBit d
= sigmaps
.at(work
->module
)(cell
->getPort(ID::D
));
456 SigBit y
= sigmaps
.at(work
->module
)(cell
->getPort(ID::Y
));
458 string a_expr
= a
.wire
? util_get_bit(work
->prefix
+ cid(a
.wire
->name
), a
.wire
->width
, a
.offset
) : a
.data
? "1" : "0";
459 string b_expr
= b
.wire
? util_get_bit(work
->prefix
+ cid(b
.wire
->name
), b
.wire
->width
, b
.offset
) : b
.data
? "1" : "0";
460 string c_expr
= c
.wire
? util_get_bit(work
->prefix
+ cid(c
.wire
->name
), c
.wire
->width
, c
.offset
) : c
.data
? "1" : "0";
461 string d_expr
= d
.wire
? util_get_bit(work
->prefix
+ cid(d
.wire
->name
), d
.wire
->width
, d
.offset
) : d
.data
? "1" : "0";
464 if (cell
->type
== ID($_AOI4_
)) expr
= stringf("!((%s & %s) | (%s & %s))", a_expr
.c_str(), b_expr
.c_str(), c_expr
.c_str(), d_expr
.c_str());
465 if (cell
->type
== ID($_OAI4_
)) expr
= stringf("!((%s | %s) & (%s | %s))", a_expr
.c_str(), b_expr
.c_str(), c_expr
.c_str(), d_expr
.c_str());
468 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(y
.wire
->name
), y
.wire
->width
, y
.offset
, expr
) +
469 stringf(" // %s (%s)", log_id(cell
), log_id(cell
->type
)));
475 if (cell
->type
.in(ID($_MUX_
), ID($_NMUX_
)))
477 SigBit a
= sigmaps
.at(work
->module
)(cell
->getPort(ID::A
));
478 SigBit b
= sigmaps
.at(work
->module
)(cell
->getPort(ID::B
));
479 SigBit s
= sigmaps
.at(work
->module
)(cell
->getPort(ID::S
));
480 SigBit y
= sigmaps
.at(work
->module
)(cell
->getPort(ID::Y
));
482 string a_expr
= a
.wire
? util_get_bit(work
->prefix
+ cid(a
.wire
->name
), a
.wire
->width
, a
.offset
) : a
.data
? "1" : "0";
483 string b_expr
= b
.wire
? util_get_bit(work
->prefix
+ cid(b
.wire
->name
), b
.wire
->width
, b
.offset
) : b
.data
? "1" : "0";
484 string s_expr
= s
.wire
? util_get_bit(work
->prefix
+ cid(s
.wire
->name
), s
.wire
->width
, s
.offset
) : s
.data
? "1" : "0";
486 // casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
487 string expr
= stringf("%s ? %s(bool)%s : %s(bool)%s", s_expr
.c_str(),
488 cell
->type
== ID($_NMUX_
) ? "!" : "", b_expr
.c_str(),
489 cell
->type
== ID($_NMUX_
) ? "!" : "", a_expr
.c_str());
492 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(y
.wire
->name
), y
.wire
->width
, y
.offset
, expr
) +
493 stringf(" // %s (%s)", log_id(cell
), log_id(cell
->type
)));
499 log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell
->type
));
502 void eval_dirty(HierDirtyFlags
*work
)
506 if (verbose
&& (!work
->dirty_bits
.empty() || !work
->dirty_cells
.empty()))
507 log(" In %s:\n", work
->log_prefix
.c_str());
509 while (!work
->dirty_bits
.empty() || !work
->dirty_cells
.empty())
511 if (!work
->dirty_bits
.empty())
513 SigSpec
dirtysig(work
->dirty_bits
);
514 dirtysig
.sort_and_unify();
516 for (SigChunk chunk
: dirtysig
.chunks()) {
517 if (chunk
.wire
== nullptr)
520 log(" Propagating %s.%s[%d:%d].\n", work
->log_prefix
.c_str(), log_id(chunk
.wire
), chunk
.offset
+chunk
.width
-1, chunk
.offset
);
521 funct_declarations
.push_back(stringf(" // Updated signal in %s: %s", work
->log_prefix
.c_str(), log_signal(chunk
)));
524 for (SigBit bit
: dirtysig
)
526 if (bit2output
[work
->module
].count(bit
) && work
->parent
)
527 for (auto outbit
: bit2output
[work
->module
][bit
])
529 Module
*parent_mod
= work
->parent
->module
;
530 Cell
*parent_cell
= parent_mod
->cell(work
->hiername
);
532 IdString port_name
= outbit
.wire
->name
;
533 int port_offset
= outbit
.offset
;
534 SigBit parent_bit
= sigmaps
.at(parent_mod
)(parent_cell
->getPort(port_name
)[port_offset
]);
536 log_assert(bit
.wire
&& parent_bit
.wire
);
537 funct_declarations
.push_back(util_set_bit(work
->parent
->prefix
+ cid(parent_bit
.wire
->name
), parent_bit
.wire
->width
, parent_bit
.offset
,
538 util_get_bit(work
->prefix
+ cid(bit
.wire
->name
), bit
.wire
->width
, bit
.offset
)));
539 work
->parent
->set_dirty(parent_bit
);
542 log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work
->log_prefix
.c_str(), log_id(bit
.wire
), bit
.offset
,
543 work
->parent
->log_prefix
.c_str(), log_id(parent_bit
.wire
), parent_bit
.offset
);
546 for (auto &port
: bit2cell
[work
->module
][bit
])
548 if (work
->children
.count(std::get
<0>(port
)->name
))
550 HierDirtyFlags
*child
= work
->children
.at(std::get
<0>(port
)->name
);
551 SigBit child_bit
= sigmaps
.at(child
->module
)(SigBit(child
->module
->wire(std::get
<1>(port
)), std::get
<2>(port
)));
552 log_assert(bit
.wire
&& child_bit
.wire
);
554 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(child
->hiername
) + "." + cid(child_bit
.wire
->name
),
555 child_bit
.wire
->width
, child_bit
.offset
, util_get_bit(work
->prefix
+ cid(bit
.wire
->name
), bit
.wire
->width
, bit
.offset
)));
556 child
->set_dirty(child_bit
);
559 log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work
->log_prefix
.c_str(), log_id(bit
.wire
), bit
.offset
,
560 work
->log_prefix
.c_str(), log_id(std::get
<0>(port
)), log_id(child_bit
.wire
), child_bit
.offset
);
563 log(" Marking cell %s.%s (via %s.%s[%d]).\n", work
->log_prefix
.c_str(), log_id(std::get
<0>(port
)),
564 work
->log_prefix
.c_str(), log_id(bit
.wire
), bit
.offset
);
565 work
->set_dirty(std::get
<0>(port
));
568 work
->unset_dirty(bit
);
572 if (!work
->dirty_cells
.empty())
574 Cell
*cell
= nullptr;
575 for (auto c
: work
->dirty_cells
)
576 if (cell
== nullptr || topoidx
.at(cell
) < topoidx
.at(c
))
579 string hiername
= work
->log_prefix
+ "." + log_id(cell
);
582 log(" Evaluating %s (%s, best of %d).\n", hiername
.c_str(), log_id(cell
->type
), GetSize(work
->dirty_cells
));
584 if (activated_cells
.count(hiername
))
585 reactivated_cells
.insert(hiername
);
586 activated_cells
.insert(hiername
);
588 eval_cell(work
, cell
);
589 work
->unset_dirty(cell
);
593 for (auto &child
: work
->children
)
594 eval_dirty(child
.second
);
598 void eval_sticky_dirty(HierDirtyFlags
*work
)
600 Module
*mod
= work
->module
;
602 for (Wire
*w
: mod
->wires())
603 for (SigBit bit
: SigSpec(w
))
605 SigBit canonical_bit
= sigmaps
.at(mod
)(bit
);
607 if (canonical_bit
== bit
)
610 if (work
->sticky_dirty_bits
.count(canonical_bit
) == 0)
613 if (bit
.wire
== nullptr || canonical_bit
.wire
== nullptr)
616 funct_declarations
.push_back(util_set_bit(work
->prefix
+ cid(bit
.wire
->name
), bit
.wire
->width
, bit
.offset
,
617 util_get_bit(work
->prefix
+ cid(canonical_bit
.wire
->name
), canonical_bit
.wire
->width
, canonical_bit
.offset
).c_str()));
620 log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
621 work
->log_prefix
.c_str(), log_id(canonical_bit
.wire
), canonical_bit
.offset
,
622 work
->log_prefix
.c_str(), log_id(bit
.wire
), bit
.offset
);
625 work
->sticky_dirty_bits
.clear();
627 for (auto &child
: work
->children
)
628 eval_sticky_dirty(child
.second
);
631 void make_func(HierDirtyFlags
*work
, const string
&func_name
, const vector
<string
> &preamble
)
633 log("Generating function %s():\n", func_name
.c_str());
635 activated_cells
.clear();
636 reactivated_cells
.clear();
638 funct_declarations
.push_back("");
639 funct_declarations
.push_back(stringf("static void %s(struct %s_state_t *state)", func_name
.c_str(), cid(work
->module
->name
).c_str()));
640 funct_declarations
.push_back("{");
641 for (auto &line
: preamble
)
642 funct_declarations
.push_back(line
);
644 eval_sticky_dirty(work
);
645 funct_declarations
.push_back("}");
647 log(" Activated %d cells (%d activated more than once).\n", GetSize(activated_cells
), GetSize(reactivated_cells
));
650 void eval_init(HierDirtyFlags
*work
, vector
<string
> &preamble
)
652 Module
*module
= work
->module
;
654 for (Wire
*w
: module
->wires())
656 if (w
->attributes
.count(ID::init
))
658 SigSpec sig
= sigmaps
.at(module
)(w
);
659 Const val
= w
->attributes
.at(ID::init
);
660 val
.bits
.resize(GetSize(sig
), State::Sx
);
662 for (int i
= 0; i
< GetSize(sig
); i
++)
663 if (val
[i
] == State::S0
|| val
[i
] == State::S1
) {
665 preamble
.push_back(util_set_bit(work
->prefix
+ cid(bit
.wire
->name
), bit
.wire
->width
, bit
.offset
, val
== State::S1
? "true" : "false"));
666 work
->set_dirty(bit
);
670 for (SigBit bit
: SigSpec(w
))
672 SigBit val
= sigmaps
.at(module
)(bit
);
674 if (val
== State::S0
|| val
== State::S1
)
675 preamble
.push_back(util_set_bit(work
->prefix
+ cid(bit
.wire
->name
), bit
.wire
->width
, bit
.offset
, val
== State::S1
? "true" : "false"));
677 if (driven_bits
.at(module
).count(val
) == 0)
678 work
->set_dirty(val
);
682 work
->set_dirty(State::S0
);
683 work
->set_dirty(State::S1
);
685 for (auto &child
: work
->children
)
686 eval_init(child
.second
, preamble
);
689 void make_init_func(HierDirtyFlags
*work
)
691 vector
<string
> preamble
;
692 eval_init(work
, preamble
);
693 make_func(work
, cid(work
->module
->name
) + "_init", preamble
);
696 void make_eval_func(HierDirtyFlags
*work
)
698 Module
*mod
= work
->module
;
699 vector
<string
> preamble
;
701 for (Wire
*w
: mod
->wires()) {
703 for (SigBit bit
: sigmaps
.at(mod
)(w
))
704 work
->set_dirty(bit
);
707 make_func(work
, cid(work
->module
->name
) + "_eval", preamble
);
710 void make_tick_func(HierDirtyFlags
* /* work */)
715 void run(Module
*mod
)
717 create_module_struct(mod
);
719 HierDirtyFlags
work(mod
, IdString(), nullptr, "state->", log_id(mod
->name
));
721 make_init_func(&work
);
722 make_eval_func(&work
);
723 make_tick_func(&work
);
726 void write(std::ostream
&f
)
728 f
<< "#include <stdint.h>" << std::endl
;
729 f
<< "#include <stdbool.h>" << std::endl
;
731 for (auto &line
: signal_declarations
)
732 f
<< line
<< std::endl
;
734 for (auto &line
: util_declarations
)
735 f
<< line
<< std::endl
;
737 for (auto &line
: struct_declarations
)
738 f
<< line
<< std::endl
;
740 for (auto &line
: funct_declarations
)
741 f
<< line
<< std::endl
;
745 struct SimplecBackend
: public Backend
{
746 SimplecBackend() : Backend("simplec", "convert design to simple C code") { }
747 void help() YS_OVERRIDE
749 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
751 log(" write_simplec [options] [filename]\n");
753 log("Write simple C code for simulating the design. The C code written can be used to\n");
754 log("simulate the design in a C environment, but the purpose of this command is to\n");
755 log("generate code that works well with C-based formal verification.\n");
758 log(" this will print the recursive walk used to export the modules.\n");
760 log(" -i8, -i16, -i32, -i64\n");
761 log(" set the maximum integer bit width to use in the generated code.\n");
763 log("THIS COMMAND IS UNDER CONSTRUCTION\n");
766 void execute(std::ostream
*&f
, std::string filename
, std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
768 reserved_cids
.clear();
771 SimplecWorker
worker(design
);
773 log_header(design
, "Executing SIMPLEC backend.\n");
776 for (argidx
= 1; argidx
< args
.size(); argidx
++)
778 if (args
[argidx
] == "-verbose") {
779 worker
.verbose
= true;
782 if (args
[argidx
] == "-i8") {
783 worker
.max_uintsize
= 8;
786 if (args
[argidx
] == "-i16") {
787 worker
.max_uintsize
= 16;
790 if (args
[argidx
] == "-i32") {
791 worker
.max_uintsize
= 32;
794 if (args
[argidx
] == "-i64") {
795 worker
.max_uintsize
= 64;
800 extra_args(f
, filename
, args
, argidx
);
802 Module
*topmod
= design
->top_module();
804 if (topmod
== nullptr)
805 log_error("Current design has no top module.\n");
812 PRIVATE_NAMESPACE_END