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"
31 PRIVATE_NAMESPACE_BEGIN
33 static void fm_set_fsm_print(RTLIL::Cell
*cell
, RTLIL::Module
*module
, FsmData
&fsm_data
, const char *prefix
, FILE *f
)
35 std::string name
= cell
->parameters
["\\NAME"].decode_string();
37 fprintf(f
, "set_fsm_state_vector {");
38 for (int i
= fsm_data
.state_bits
-1; i
>= 0; i
--)
39 fprintf(f
, " %s_reg[%d]", name
[0] == '\\' ? name
.substr(1).c_str() : name
.c_str(), i
);
40 fprintf(f
, " } -name {%s_%s} {%s:/WORK/%s}\n", prefix
, RTLIL::unescape_id(name
).c_str(),
41 prefix
, RTLIL::unescape_id(module
->name
).c_str());
43 fprintf(f
, "set_fsm_encoding {");
44 for (int i
= 0; i
< GetSize(fsm_data
.state_table
); i
++) {
45 fprintf(f
, " s%d=2#", i
);
46 for (int j
= GetSize(fsm_data
.state_table
[i
].bits
)-1; j
>= 0; j
--)
47 fprintf(f
, "%c", fsm_data
.state_table
[i
].bits
[j
] == RTLIL::State::S1
? '1' : '0');
49 fprintf(f
, " } -name {%s_%s} {%s:/WORK/%s}\n",
50 prefix
, RTLIL::unescape_id(name
).c_str(),
51 prefix
, RTLIL::unescape_id(module
->name
).c_str());
54 static void fsm_recode(RTLIL::Cell
*cell
, RTLIL::Module
*module
, FILE *fm_set_fsm_file
, FILE *encfile
, std::string default_encoding
)
56 std::string encoding
= cell
->attributes
.count(ID::fsm_encoding
) ? cell
->attributes
.at(ID::fsm_encoding
).decode_string() : "auto";
58 log("Recoding FSM `%s' from module `%s' using `%s' encoding:\n", cell
->name
.c_str(), module
->name
.c_str(), encoding
.c_str());
60 if (encoding
!= "none" && encoding
!= "user" && encoding
!= "one-hot" && encoding
!= "binary" && encoding
!= "auto") {
61 log(" unknown encoding `%s': using auto instead.\n", encoding
.c_str());
65 if (encoding
== "none" || encoding
== "user") {
66 log(" nothing to do for encoding `%s'.\n", encoding
.c_str());
71 fsm_data
.copy_from_cell(cell
);
73 if (fm_set_fsm_file
!= NULL
)
74 fm_set_fsm_print(cell
, module
, fsm_data
, "r", fm_set_fsm_file
);
76 if (encoding
== "auto") {
77 if (!default_encoding
.empty())
78 encoding
= default_encoding
;
80 encoding
= GetSize(fsm_data
.state_table
) < 32 ? "one-hot" : "binary";
81 log(" mapping auto encoding to `%s` for this FSM.\n", encoding
.c_str());
84 if (encoding
== "one-hot") {
85 fsm_data
.state_bits
= fsm_data
.state_table
.size();
87 if (encoding
== "binary") {
88 int new_num_state_bits
= ceil_log2(fsm_data
.state_table
.size());
89 if (fsm_data
.state_bits
== new_num_state_bits
) {
90 log(" existing encoding is already a packed binary encoding.\n");
93 fsm_data
.state_bits
= new_num_state_bits
;
95 log_error("FSM encoding `%s' is not supported!\n", encoding
.c_str());
98 fprintf(encfile
, ".fsm %s %s\n", log_id(module
), RTLIL::unescape_id(cell
->parameters
["\\NAME"].decode_string()).c_str());
100 int state_idx_counter
= fsm_data
.reset_state
>= 0 ? 1 : 0;
101 for (int i
= 0; i
< int(fsm_data
.state_table
.size()); i
++)
103 int state_idx
= fsm_data
.reset_state
== i
? 0 : state_idx_counter
++;
104 RTLIL::Const new_code
;
106 if (encoding
== "one-hot") {
107 new_code
= RTLIL::Const(RTLIL::State::Sa
, fsm_data
.state_bits
);
108 new_code
.bits
[state_idx
] = RTLIL::State::S1
;
110 if (encoding
== "binary") {
111 new_code
= RTLIL::Const(state_idx
, fsm_data
.state_bits
);
115 log(" %s -> %s\n", fsm_data
.state_table
[i
].as_string().c_str(), new_code
.as_string().c_str());
117 fprintf(encfile
, ".map %s %s\n", fsm_data
.state_table
[i
].as_string().c_str(), new_code
.as_string().c_str());
118 fsm_data
.state_table
[i
] = new_code
;
121 if (fm_set_fsm_file
!= NULL
)
122 fm_set_fsm_print(cell
, module
, fsm_data
, "i", fm_set_fsm_file
);
124 fsm_data
.copy_to_cell(cell
);
127 struct FsmRecodePass
: public Pass
{
128 FsmRecodePass() : Pass("fsm_recode", "recoding finite state machines") { }
129 void help() YS_OVERRIDE
131 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
133 log(" fsm_recode [options] [selection]\n");
135 log("This pass reassign the state encodings for FSM cells. At the moment only\n");
136 log("one-hot encoding and binary encoding is supported.\n");
138 log(" -encoding <type>\n");
139 log(" specify the encoding scheme used for FSMs without the\n");
140 log(" 'fsm_encoding' attribute or with the attribute set to `auto'.\n");
142 log(" -fm_set_fsm_file <file>\n");
143 log(" generate a file containing the mapping from old to new FSM encoding\n");
144 log(" in form of Synopsys Formality set_fsm_* commands.\n");
146 log(" -encfile <file>\n");
147 log(" write the mappings from old to new FSM encoding to a file in the\n");
148 log(" following format:\n");
150 log(" .fsm <module_name> <state_signal>\n");
151 log(" .map <old_bitpattern> <new_bitpattern>\n");
154 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
156 FILE *fm_set_fsm_file
= NULL
;
157 FILE *encfile
= NULL
;
158 std::string default_encoding
;
160 log_header(design
, "Executing FSM_RECODE pass (re-assigning FSM state encoding).\n");
162 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
163 std::string arg
= args
[argidx
];
164 if (arg
== "-fm_set_fsm_file" && argidx
+1 < args
.size() && fm_set_fsm_file
== NULL
) {
165 fm_set_fsm_file
= fopen(args
[++argidx
].c_str(), "w");
166 if (fm_set_fsm_file
== NULL
)
167 log_error("Can't open fm_set_fsm_file `%s' for writing: %s\n", args
[argidx
].c_str(), strerror(errno
));
170 if (arg
== "-encfile" && argidx
+1 < args
.size() && encfile
== NULL
) {
171 encfile
= fopen(args
[++argidx
].c_str(), "w");
173 log_error("Can't open encfile `%s' for writing: %s\n", args
[argidx
].c_str(), strerror(errno
));
176 if (arg
== "-encoding" && argidx
+1 < args
.size() && default_encoding
.empty()) {
177 default_encoding
= args
[++argidx
];
182 extra_args(args
, argidx
, design
);
184 for (auto &mod_it
: design
->modules_
)
185 if (design
->selected(mod_it
.second
))
186 for (auto &cell_it
: mod_it
.second
->cells_
)
187 if (cell_it
.second
->type
== "$fsm" && design
->selected(mod_it
.second
, cell_it
.second
))
188 fsm_recode(cell_it
.second
, mod_it
.second
, fm_set_fsm_file
, encfile
, default_encoding
);
190 if (fm_set_fsm_file
!= NULL
)
191 fclose(fm_set_fsm_file
);
197 PRIVATE_NAMESPACE_END