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/log.h"
21 #include "kernel/register.h"
22 #include "kernel/sigtools.h"
23 #include "kernel/consteval.h"
24 #include "kernel/celltypes.h"
29 static void fm_set_fsm_print(RTLIL::Cell
*cell
, RTLIL::Module
*module
, FsmData
&fsm_data
, const char *prefix
, FILE *f
)
31 fprintf(f
, "set_fsm_state_vector {");
32 for (int i
= fsm_data
.state_bits
-1; i
>= 0; i
--)
33 fprintf(f
, " %s_reg[%d]", cell
->parameters
["\\NAME"].str
[0] == '\\' ?
34 cell
->parameters
["\\NAME"].str
.substr(1).c_str() : cell
->parameters
["\\NAME"].str
.c_str(), i
);
35 fprintf(f
, " } -name {%s_%s} {%s:/WORK/%s}\n",
36 prefix
, RTLIL::unescape_id(cell
->parameters
["\\NAME"].str
).c_str(),
37 prefix
, RTLIL::unescape_id(module
->name
).c_str());
39 fprintf(f
, "set_fsm_encoding {");
40 for (size_t i
= 0; i
< fsm_data
.state_table
.size(); i
++) {
41 fprintf(f
, " s%zd=2#", i
);
42 for (int j
= int(fsm_data
.state_table
[i
].bits
.size())-1; j
>= 0; j
--)
43 fprintf(f
, "%c", fsm_data
.state_table
[i
].bits
[j
] == RTLIL::State::S1
? '1' : '0');
45 fprintf(f
, " } -name {%s_%s} {%s:/WORK/%s}\n",
46 prefix
, RTLIL::unescape_id(cell
->parameters
["\\NAME"].str
).c_str(),
47 prefix
, RTLIL::unescape_id(module
->name
).c_str());
50 static void fsm_recode(RTLIL::Cell
*cell
, RTLIL::Module
*module
, FILE *fm_set_fsm_file
, std::string default_encoding
)
52 std::string encoding
= cell
->attributes
.count("\\fsm_encoding") ? cell
->attributes
.at("\\fsm_encoding").str
: "auto";
54 log("Recoding FSM `%s' from module `%s' using `%s' encoding:\n", cell
->name
.c_str(), module
->name
.c_str(), encoding
.c_str());
55 if (encoding
!= "none" && encoding
!= "one-hot" && encoding
!= "binary") {
56 if (encoding
!= "auto")
57 log(" unkown encoding `%s': using auto (%s) instead.\n", encoding
.c_str(), default_encoding
.c_str());
58 encoding
= default_encoding
;
61 if (encoding
== "none") {
62 log(" nothing to do for encoding `none'.\n");
67 fsm_data
.copy_from_cell(cell
);
69 if (fm_set_fsm_file
!= NULL
)
70 fm_set_fsm_print(cell
, module
, fsm_data
, "r", fm_set_fsm_file
);
72 if (encoding
== "one-hot") {
73 fsm_data
.state_bits
= fsm_data
.state_table
.size();
75 if (encoding
== "auto" || encoding
== "binary") {
76 fsm_data
.state_bits
= ceil(log2(fsm_data
.state_table
.size()));
78 log_error("FSM encoding `%s' is not supported!\n", encoding
.c_str());
80 int state_idx_counter
= fsm_data
.reset_state
>= 0 ? 1 : 0;
81 for (int i
= 0; i
< int(fsm_data
.state_table
.size()); i
++)
83 int state_idx
= fsm_data
.reset_state
== i
? 0 : state_idx_counter
++;
84 RTLIL::Const new_code
;
86 if (encoding
== "one-hot") {
87 new_code
= RTLIL::Const(RTLIL::State::Sa
, fsm_data
.state_bits
);
88 new_code
.bits
[state_idx
] = RTLIL::State::S1
;
90 if (encoding
== "auto" || encoding
== "binary") {
91 new_code
= RTLIL::Const(state_idx
, fsm_data
.state_bits
);
95 log(" %s -> %s\n", fsm_data
.state_table
[i
].as_string().c_str(), new_code
.as_string().c_str());
96 fsm_data
.state_table
[i
] = new_code
;
99 if (fm_set_fsm_file
!= NULL
)
100 fm_set_fsm_print(cell
, module
, fsm_data
, "i", fm_set_fsm_file
);
102 fsm_data
.copy_to_cell(cell
);
105 struct FsmRecodePass
: public Pass
{
106 FsmRecodePass() : Pass("fsm_recode", "recoding finite state machines") { }
109 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
111 log(" fsm_recode [-encoding type] [-fm_set_fsm_file file] [selection]\n");
113 log("This pass reassign the state encodings for FSM cells. At the moment only\n");
114 log("one-hot encoding and binary encoding is supported. The option -encoding\n");
115 log("can be used to specify the encoding scheme used for FSMs without the\n");
116 log("`fsm_encoding' attribute (or with the attribute set to `auto'.\n");
118 log("The option -fm_set_fsm_file can be used to generate a file containing the\n");
119 log("mapping from old to new FSM encoding in form of Synopsys Formality set_fsm_*\n");
123 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
125 FILE *fm_set_fsm_file
= NULL
;
126 std::string default_encoding
= "one-hot";
128 log_header("Executing FSM_RECODE pass (re-assigning FSM state encoding).\n");
130 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
131 std::string arg
= args
[argidx
];
132 if (arg
== "-fm_set_fsm_file" && argidx
+1 < args
.size() && fm_set_fsm_file
== NULL
) {
133 fm_set_fsm_file
= fopen(args
[++argidx
].c_str(), "w");
134 if (fm_set_fsm_file
== NULL
)
135 log_error("Can't open fm_set_fsm_file `%s' for writing: %s\n", args
[argidx
].c_str(), strerror(errno
));
138 if (arg
== "-encoding" && argidx
+1 < args
.size() && fm_set_fsm_file
== NULL
) {
139 default_encoding
= args
[++argidx
];
144 extra_args(args
, argidx
, design
);
146 for (auto &mod_it
: design
->modules
)
147 if (design
->selected(mod_it
.second
))
148 for (auto &cell_it
: mod_it
.second
->cells
)
149 if (cell_it
.second
->type
== "$fsm" && design
->selected(mod_it
.second
, cell_it
.second
))
150 fsm_recode(cell_it
.second
, mod_it
.second
, fm_set_fsm_file
, default_encoding
);
152 if (fm_set_fsm_file
!= NULL
)
153 fclose(fm_set_fsm_file
);