48 assign_map.
apply(sig);
57 std::set<sig2driver_entry_t> cellport_list;
58 sig2driver.
find(sig, cellport_list);
59 for (
auto &cellport : cellport_list)
62 if ((cell->
type !=
"$mux" && cell->
type !=
"$pmux") || cellport.second !=
"\\Y") {
63 log(
" unexpected cell type %s (%s) found in state selection tree.\n", cell->
type.
c_str(), cell->
name.
c_str());
84 if (sig_aa.is_fully_def())
85 *reset_state = sig_aa.as_const();
90 log(
" found reset state: %s (guessed from mux tree)\n",
log_signal(*reset_state));
112 if (dont_care.size() > 0) {
113 for (
int i = 0; i <
GetSize(sig); i++)
114 if (dont_care.extract(sig[i]).size() > 0)
115 sig[i] = noconst_state;
121 for (
int i = 0; i <
GetSize(sig); i++)
122 if (sig[i].wire !=
NULL)
123 sig[i] = noconst_state;
130 bool undef_bit_in_next_state_mode =
false;
133 if (ce.
eval(ctrl_out, undef) && ce.
eval(dff_in, undef))
136 undef_bit_in_next_state:
137 for (
auto &bit : dff_in)
138 if (bit.wire !=
nullptr) bit =
RTLIL::Sm;
139 for (
auto &bit : ctrl_out)
140 if (bit.wire !=
nullptr) bit =
RTLIL::Sm;
141 undef_bit_in_next_state_mode =
true;
150 std::map<RTLIL::SigBit, int> ctrl_in_bit_indices;
151 for (
int i = 0; i <
GetSize(ctrl_in); i++)
152 ctrl_in_bit_indices[ctrl_in[i]] = i;
154 for (
auto &it : ctrl_in_bit_indices)
157 if (ctrl_in_bit_indices.count(dc_bit))
165 log(
" transition: %10s %s -> INVALID_STATE(%s) %s <ignored invalid transistion!>%s\n",
168 undef_bit_in_next_state_mode ?
" SHORTENED" :
"");
172 tr.state_in = state_in;
177 log(
" transition: %10s %s -> %10s %s\n",
181 log(
" transition: %10s %s -> %10s %s <ignored undef transistion!>\n",
188 for (
auto &bit : dff_in)
190 goto undef_bit_in_next_state;
198 if (ce_nostop.
eval(constval))
207 goto found_contradiction_1;
211 find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
212 found_contradiction_1:
220 find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
221 ce.
pop(), ce_nostop.
pop();
230 goto found_contradiction_2;
234 find_transitions(ce, ce_nostop, fsm_data, states, state_in, ctrl_in, ctrl_out, dff_in, dont_care);
235 found_contradiction_2:
236 ce.
pop(), ce_nostop.
pop();
253 bool arst_polarity =
true;
255 std::set<sig2driver_entry_t> cellport_list;
256 sig2driver.
find(dff_out, cellport_list);
257 for (
auto &cellport : cellport_list) {
259 if ((cell->
type !=
"$dff" && cell->
type !=
"$adff") || cellport.second !=
"\\Q")
265 clk_polarity = cell->
parameters[
"\\CLK_POLARITY"].as_bool();
266 if (cell->
type ==
"$adff") {
267 arst = cell->
getPort(
"\\ARST");
268 arst_polarity = cell->
parameters[
"\\ARST_POLARITY"].as_bool();
269 reset_state = cell->
parameters[
"\\ARST_VALUE"];
271 sig_q.replace(dff_out, sig_d, &dff_in);
275 log(
" root of input selection tree: %s\n",
log_signal(dff_in));
277 log(
" fsm extraction failed: incomplete input selection tree root.\n");
284 std::map<RTLIL::Const, int>
states;
286 log(
" found reset state: %s (from async reset)\n",
log_signal(reset_state));
287 states[reset_state] = -1;
289 if (!
find_states(dff_in, dff_out, ctrl_in, states, &reset_state)) {
290 log(
" fsm extraction failed: state selection tree is not closed.\n");
294 log(
" fsm extraction failed: at least two states are required.\n");
303 cellport_list.clear();
304 sig2trigger.
find(dff_out, cellport_list);
305 for (
auto &cellport : cellport_list) {
310 if (cellport.second ==
"\\A" && !sig_b.is_fully_const())
332 for (
auto &it : states) {
343 for (
int state_idx = 0; state_idx < int(fsm_data.
state_table.size()); state_idx++) {
344 ce.
push(), ce_nostop.push();
346 ce_nostop.set(dff_out, fsm_data.
state_table[state_idx]);
348 ce.
pop(), ce_nostop.pop();
354 fsm_cell->
setPort(
"\\CLK", clk);
355 fsm_cell->
setPort(
"\\ARST", arst);
358 fsm_cell->
setPort(
"\\CTRL_IN", ctrl_in);
359 fsm_cell->
setPort(
"\\CTRL_OUT", ctrl_out);
361 fsm_cell->attributes = wire->attributes;
367 wire->attributes.erase(
"\\fsm_encoding");
373 cellport_list.clear();
374 sig2driver.
find(ctrl_out, cellport_list);
375 for (
auto &cellport : cellport_list) {
390 log(
" fsm_extract [selection]\n");
392 log(
"This pass operates on all signals marked as FSM state signals using the\n");
393 log(
"'fsm_encoding' attribute. It consumes the logic that creates the state signal\n");
394 log(
"and uses the state signal to generate control signal and replaces it with an\n");
397 log(
"The generated FSM cell still generates the original state signal with its\n");
398 log(
"original encoding. The 'fsm_opt' pass can be used in combination with the\n");
399 log(
"'opt_clean' pass to eliminate this signal.\n");
404 log_header(
"Executing FSM_EXTRACT pass (extracting FSM from design).\n");
413 for (
auto &mod_it : design->
modules_)
415 if (!design->
selected(mod_it.second))
418 module = mod_it.second;
419 assign_map.
set(module);
424 for (
auto cell : module->
cells()) {
425 for (
auto &conn_it : cell->connections()) {
428 assign_map.
apply(sig);
431 if (ct.
cell_input(cell->type, conn_it.first) && cell->hasPort(
"\\Y") &&
432 cell->getPort(
"\\Y").size() == 1 && (conn_it.first ==
"\\A" || conn_it.first ==
"\\B")) {
434 assign_map.
apply(sig);
438 if (cell->type ==
"$pmux") {
440 for (
auto &bit1 : sel_sig)
441 for (
auto &bit2 : sel_sig)
447 std::vector<RTLIL::Wire*> wire_list;
448 for (
auto &wire_it : module->
wires_)
449 if (wire_it.second->attributes.count(
"\\fsm_encoding") > 0 && wire_it.second->attributes[
"\\fsm_encoding"].decode_string() !=
"none")
450 if (design->
selected(module, wire_it.second))
451 wire_list.push_back(wire_it.second);
452 for (
auto wire : wire_list)
const char * c_str() const
bool selected(T1 *module) const
bool is_fully_def() const
bool is_fully_undef() const
std::vector< transition_t > transition_table
std::string stringf(const char *fmt,...)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void setup_internals_mem()
void log_header(const char *format,...)
RTLIL::Const as_const() const
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
void copy_to_cell(RTLIL::Cell *cell)
std::map< RTLIL::IdString, RTLIL::Const > parameters
void remove(const RTLIL::SigSpec &pattern)
void apply(RTLIL::SigBit &bit) const
void set(RTLIL::Module *module)
bool cell_known(RTLIL::IdString type)
#define PRIVATE_NAMESPACE_BEGIN
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
int GetSize(RTLIL::Wire *wire)
#define log_assert(_assert_expr_)
bool is_fully_const() const
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
void stop(RTLIL::SigSpec sig)
#define PRIVATE_NAMESPACE_END
bool check_all(RTLIL::SigSpec sig)
#define USING_YOSYS_NAMESPACE
RTLIL::ObjRange< RTLIL::Cell * > cells()
std::map< RTLIL::IdString, RTLIL::Module * > modules_
void replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
std::vector< RTLIL::Const > state_table
void log(const char *format,...)
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
void append(const RTLIL::SigSpec &signal)
void setup_stdcells_mem()
void extend(int width, bool is_signed=false)
bool cell_input(RTLIL::IdString type, RTLIL::IdString port)
std::map< RTLIL::IdString, RTLIL::SigSpec > connections_
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
void set(RTLIL::SigSpec sig, RTLIL::Const value)
bool has_marked_bits() const
void find(RTLIL::SigSpec sig, std::set< T > &result)
void insert(RTLIL::SigSpec sig, T data)
YOSYS_NAMESPACE_BEGIN int autoidx