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"
30 static void fm_set_fsm_print(RTLIL::Cell
*cell
, RTLIL::Module
*module
, FsmData
&fsm_data
, const char *prefix
, FILE *f
)
32 std::string name
= cell
->parameters
["\\NAME"].decode_string();
34 fprintf(f
, "set_fsm_state_vector {");
35 for (int i
= fsm_data
.state_bits
-1; i
>= 0; i
--)
36 fprintf(f
, " %s_reg[%d]", name
[0] == '\\' ? name
.substr(1).c_str() : name
.c_str(), i
);
37 fprintf(f
, " } -name {%s_%s} {%s:/WORK/%s}\n", prefix
, RTLIL::unescape_id(name
).c_str(),
38 prefix
, RTLIL::unescape_id(module
->name
).c_str());
40 fprintf(f
, "set_fsm_encoding {");
41 for (size_t i
= 0; i
< fsm_data
.state_table
.size(); i
++) {
42 fprintf(f
, " s%zd=2#", i
);
43 for (int j
= int(fsm_data
.state_table
[i
].bits
.size())-1; j
>= 0; j
--)
44 fprintf(f
, "%c", fsm_data
.state_table
[i
].bits
[j
] == RTLIL::State::S1
? '1' : '0');
46 fprintf(f
, " } -name {%s_%s} {%s:/WORK/%s}\n",
47 prefix
, RTLIL::unescape_id(name
).c_str(),
48 prefix
, RTLIL::unescape_id(module
->name
).c_str());
51 static void fsm_recode(RTLIL::Cell
*cell
, RTLIL::Module
*module
, FILE *fm_set_fsm_file
, std::string default_encoding
)
53 std::string encoding
= cell
->attributes
.count("\\fsm_encoding") ? cell
->attributes
.at("\\fsm_encoding").decode_string() : "auto";
55 log("Recoding FSM `%s' from module `%s' using `%s' encoding:\n", cell
->name
.c_str(), module
->name
.c_str(), encoding
.c_str());
56 if (encoding
!= "none" && encoding
!= "one-hot" && encoding
!= "binary") {
57 if (encoding
!= "auto")
58 log(" unkown encoding `%s': using auto (%s) instead.\n", encoding
.c_str(), default_encoding
.c_str());
59 encoding
= default_encoding
;
62 if (encoding
== "none") {
63 log(" nothing to do for encoding `none'.\n");
68 fsm_data
.copy_from_cell(cell
);
70 if (fm_set_fsm_file
!= NULL
)
71 fm_set_fsm_print(cell
, module
, fsm_data
, "r", fm_set_fsm_file
);
73 if (encoding
== "one-hot") {
74 fsm_data
.state_bits
= fsm_data
.state_table
.size();
76 if (encoding
== "auto" || encoding
== "binary") {
77 fsm_data
.state_bits
= ceil(log2(fsm_data
.state_table
.size()));
79 log_error("FSM encoding `%s' is not supported!\n", encoding
.c_str());
81 int state_idx_counter
= fsm_data
.reset_state
>= 0 ? 1 : 0;
82 for (int i
= 0; i
< int(fsm_data
.state_table
.size()); i
++)
84 int state_idx
= fsm_data
.reset_state
== i
? 0 : state_idx_counter
++;
85 RTLIL::Const new_code
;
87 if (encoding
== "one-hot") {
88 new_code
= RTLIL::Const(RTLIL::State::Sa
, fsm_data
.state_bits
);
89 new_code
.bits
[state_idx
] = RTLIL::State::S1
;
91 if (encoding
== "auto" || encoding
== "binary") {
92 new_code
= RTLIL::Const(state_idx
, fsm_data
.state_bits
);
96 log(" %s -> %s\n", fsm_data
.state_table
[i
].as_string().c_str(), new_code
.as_string().c_str());
97 fsm_data
.state_table
[i
] = new_code
;
100 if (fm_set_fsm_file
!= NULL
)
101 fm_set_fsm_print(cell
, module
, fsm_data
, "i", fm_set_fsm_file
);
103 fsm_data
.copy_to_cell(cell
);
106 struct FsmRecodePass
: public Pass
{
107 FsmRecodePass() : Pass("fsm_recode", "recoding finite state machines") { }
110 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
112 log(" fsm_recode [-encoding type] [-fm_set_fsm_file file] [selection]\n");
114 log("This pass reassign the state encodings for FSM cells. At the moment only\n");
115 log("one-hot encoding and binary encoding is supported. The option -encoding\n");
116 log("can be used to specify the encoding scheme used for FSMs without the\n");
117 log("`fsm_encoding' attribute (or with the attribute set to `auto'.\n");
119 log("The option -fm_set_fsm_file can be used to generate a file containing the\n");
120 log("mapping from old to new FSM encoding in form of Synopsys Formality set_fsm_*\n");
124 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
126 FILE *fm_set_fsm_file
= NULL
;
127 std::string default_encoding
= "one-hot";
129 log_header("Executing FSM_RECODE pass (re-assigning FSM state encoding).\n");
131 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
132 std::string arg
= args
[argidx
];
133 if (arg
== "-fm_set_fsm_file" && argidx
+1 < args
.size() && fm_set_fsm_file
== NULL
) {
134 fm_set_fsm_file
= fopen(args
[++argidx
].c_str(), "w");
135 if (fm_set_fsm_file
== NULL
)
136 log_error("Can't open fm_set_fsm_file `%s' for writing: %s\n", args
[argidx
].c_str(), strerror(errno
));
139 if (arg
== "-encoding" && argidx
+1 < args
.size() && fm_set_fsm_file
== NULL
) {
140 default_encoding
= args
[++argidx
];
145 extra_args(args
, argidx
, design
);
147 for (auto &mod_it
: design
->modules
)
148 if (design
->selected(mod_it
.second
))
149 for (auto &cell_it
: mod_it
.second
->cells
)
150 if (cell_it
.second
->type
== "$fsm" && design
->selected(mod_it
.second
, cell_it
.second
))
151 fsm_recode(cell_it
.second
, mod_it
.second
, fm_set_fsm_file
, default_encoding
);
153 if (fm_set_fsm_file
!= NULL
)
154 fclose(fm_set_fsm_file
);