aboutsummaryrefslogtreecommitdiffstats
path: root/passes/fsm/fsm_map.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/fsm/fsm_map.cc')
-rw-r--r--passes/fsm/fsm_map.cc304
1 files changed, 138 insertions, 166 deletions
diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc
index c30cf1fe7..ab6d5671d 100644
--- a/passes/fsm/fsm_map.cc
+++ b/passes/fsm/fsm_map.cc
@@ -25,12 +25,26 @@
#include "fsmdata.h"
#include <string.h>
+static bool pattern_is_subset(const RTLIL::Const &super_pattern, const RTLIL::Const &sub_pattern)
+{
+ log_assert(SIZE(super_pattern.bits) == SIZE(sub_pattern.bits));
+ for (int i = 0; i < SIZE(super_pattern.bits); i++)
+ if (sub_pattern.bits[i] == RTLIL::State::S0 || sub_pattern.bits[i] == RTLIL::State::S1) {
+ if (super_pattern.bits[i] == RTLIL::State::S0 || super_pattern.bits[i] == RTLIL::State::S1) {
+ if (super_pattern.bits[i] != sub_pattern.bits[i])
+ return false;
+ } else
+ return false;
+ }
+ return true;
+}
+
static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const, std::set<int>> &pattern_cache, std::set<int> &fullstate_cache, int num_states, RTLIL::Wire *state_onehot, RTLIL::SigSpec &ctrl_in, RTLIL::SigSpec output)
{
RTLIL::SigSpec cases_vector;
for (int in_state : fullstate_cache)
- cases_vector.append(RTLIL::SigSpec(state_onehot, 1, in_state));
+ cases_vector.append(RTLIL::SigSpec(state_onehot, in_state));
for (auto &it : pattern_cache)
{
@@ -42,89 +56,74 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const
eq_sig_a.append(ctrl_in.extract(j, 1));
eq_sig_b.append(RTLIL::SigSpec(pattern.bits[j]));
}
- eq_sig_a.optimize();
- eq_sig_b.optimize();
for (int in_state : it.second)
if (fullstate_cache.count(in_state) == 0)
- or_sig.append(RTLIL::SigSpec(state_onehot, 1, in_state));
- or_sig.optimize();
+ or_sig.append(RTLIL::SigSpec(state_onehot, in_state));
- if (or_sig.width == 0)
+ if (or_sig.size() == 0)
continue;
RTLIL::SigSpec and_sig;
- if (eq_sig_a.width > 0)
+ if (eq_sig_a.size() > 0)
{
- RTLIL::Wire *eq_wire = new RTLIL::Wire;
- eq_wire->name = NEW_ID;
- module->add(eq_wire);
-
- RTLIL::Cell *eq_cell = new RTLIL::Cell;
- eq_cell->name = NEW_ID;
- eq_cell->type = "$eq";
- eq_cell->connections["\\A"] = eq_sig_a;
- eq_cell->connections["\\B"] = eq_sig_b;
- eq_cell->connections["\\Y"] = RTLIL::SigSpec(eq_wire);
+ RTLIL::Wire *eq_wire = module->addWire(NEW_ID);
+ and_sig.append(RTLIL::SigSpec(eq_wire));
+
+ RTLIL::Cell *eq_cell = module->addCell(NEW_ID, "$eq");
+ eq_cell->setPort("\\A", eq_sig_a);
+ eq_cell->setPort("\\B", eq_sig_b);
+ eq_cell->setPort("\\Y", RTLIL::SigSpec(eq_wire));
eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false);
eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(false);
- eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(eq_sig_a.width);
- eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(eq_sig_b.width);
+ eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(eq_sig_a.size());
+ eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(eq_sig_b.size());
eq_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
- module->add(eq_cell);
-
- and_sig.append(RTLIL::SigSpec(eq_wire));
}
- if (or_sig.width < num_states-int(fullstate_cache.size()))
+ std::set<int> complete_in_state_cache = it.second;
+
+ for (auto &it2 : pattern_cache)
+ if (pattern_is_subset(pattern, it2.first))
+ complete_in_state_cache.insert(it2.second.begin(), it2.second.end());
+
+ if (SIZE(complete_in_state_cache) < num_states)
{
- if (or_sig.width == 1)
+ if (or_sig.size() == 1)
{
and_sig.append(or_sig);
}
else
{
- RTLIL::Wire *or_wire = new RTLIL::Wire;
- or_wire->name = NEW_ID;
- module->add(or_wire);
-
- RTLIL::Cell *or_cell = new RTLIL::Cell;
- or_cell->name = NEW_ID;
- or_cell->type = "$reduce_or";
- or_cell->connections["\\A"] = or_sig;
- or_cell->connections["\\Y"] = RTLIL::SigSpec(or_wire);
+ RTLIL::Wire *or_wire = module->addWire(NEW_ID);
+ and_sig.append(RTLIL::SigSpec(or_wire));
+
+ RTLIL::Cell *or_cell = module->addCell(NEW_ID, "$reduce_or");
+ or_cell->setPort("\\A", or_sig);
+ or_cell->setPort("\\Y", RTLIL::SigSpec(or_wire));
or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false);
- or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(or_sig.width);
+ or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(or_sig.size());
or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
- module->add(or_cell);
-
- and_sig.append(RTLIL::SigSpec(or_wire));
}
}
- switch (and_sig.width)
+ switch (and_sig.size())
{
case 2:
{
- RTLIL::Wire *and_wire = new RTLIL::Wire;
- and_wire->name = NEW_ID;
- module->add(and_wire);
-
- RTLIL::Cell *and_cell = new RTLIL::Cell;
- and_cell->name = NEW_ID;
- and_cell->type = "$and";
- and_cell->connections["\\A"] = and_sig.extract(0, 1);
- and_cell->connections["\\B"] = and_sig.extract(1, 1);
- and_cell->connections["\\Y"] = RTLIL::SigSpec(and_wire);
+ RTLIL::Wire *and_wire = module->addWire(NEW_ID);
+ cases_vector.append(RTLIL::SigSpec(and_wire));
+
+ RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$and");
+ and_cell->setPort("\\A", and_sig.extract(0, 1));
+ and_cell->setPort("\\B", and_sig.extract(1, 1));
+ and_cell->setPort("\\Y", RTLIL::SigSpec(and_wire));
and_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false);
and_cell->parameters["\\B_SIGNED"] = RTLIL::Const(false);
and_cell->parameters["\\A_WIDTH"] = RTLIL::Const(1);
and_cell->parameters["\\B_WIDTH"] = RTLIL::Const(1);
and_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
- module->add(and_cell);
-
- cases_vector.append(RTLIL::SigSpec(and_wire));
break;
}
case 1:
@@ -138,20 +137,17 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const
}
}
- if (cases_vector.width > 1) {
- RTLIL::Cell *or_cell = new RTLIL::Cell;
- or_cell->name = NEW_ID;
- or_cell->type = "$reduce_or";
- or_cell->connections["\\A"] = cases_vector;
- or_cell->connections["\\Y"] = output;
+ if (cases_vector.size() > 1) {
+ RTLIL::Cell *or_cell = module->addCell(NEW_ID, "$reduce_or");
+ or_cell->setPort("\\A", cases_vector);
+ or_cell->setPort("\\Y", output);
or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false);
- or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cases_vector.width);
+ or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cases_vector.size());
or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
- module->add(or_cell);
- } else if (cases_vector.width == 1) {
- module->connections.push_back(RTLIL::SigSig(output, cases_vector));
+ } else if (cases_vector.size() == 1) {
+ module->connect(RTLIL::SigSig(output, cases_vector));
} else {
- module->connections.push_back(RTLIL::SigSig(output, RTLIL::SigSpec(0, 1)));
+ module->connect(RTLIL::SigSig(output, RTLIL::SigSpec(0, 1)));
}
}
@@ -162,26 +158,16 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
FsmData fsm_data;
fsm_data.copy_from_cell(fsm_cell);
- RTLIL::SigSpec ctrl_in = fsm_cell->connections["\\CTRL_IN"];
- RTLIL::SigSpec ctrl_out = fsm_cell->connections["\\CTRL_OUT"];
+ RTLIL::SigSpec ctrl_in = fsm_cell->getPort("\\CTRL_IN");
+ RTLIL::SigSpec ctrl_out = fsm_cell->getPort("\\CTRL_OUT");
// create state register
- RTLIL::Wire *state_wire = new RTLIL::Wire;
- state_wire->name = fsm_cell->parameters["\\NAME"].decode_string();
- while (module->count_id(state_wire->name) > 0)
- state_wire->name += "_";
- state_wire->width = fsm_data.state_bits;
- module->add(state_wire);
-
- RTLIL::Wire *next_state_wire = new RTLIL::Wire;
- next_state_wire->name = NEW_ID;
- next_state_wire->width = fsm_data.state_bits;
- module->add(next_state_wire);
-
- RTLIL::Cell *state_dff = new RTLIL::Cell;
- state_dff->name = NEW_ID;
- if (fsm_cell->connections["\\ARST"].is_fully_const()) {
+ RTLIL::Wire *state_wire = module->addWire(module->uniquify(fsm_cell->parameters["\\NAME"].decode_string()), fsm_data.state_bits);
+ RTLIL::Wire *next_state_wire = module->addWire(NEW_ID, fsm_data.state_bits);
+
+ RTLIL::Cell *state_dff = module->addCell(NEW_ID, "");
+ if (fsm_cell->getPort("\\ARST").is_fully_const()) {
state_dff->type = "$dff";
} else {
state_dff->type = "$adff";
@@ -190,23 +176,19 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
for (auto &bit : state_dff->parameters["\\ARST_VALUE"].bits)
if (bit != RTLIL::State::S1)
bit = RTLIL::State::S0;
- state_dff->connections["\\ARST"] = fsm_cell->connections["\\ARST"];
+ state_dff->setPort("\\ARST", fsm_cell->getPort("\\ARST"));
}
state_dff->parameters["\\WIDTH"] = RTLIL::Const(fsm_data.state_bits);
state_dff->parameters["\\CLK_POLARITY"] = fsm_cell->parameters["\\CLK_POLARITY"];
- state_dff->connections["\\CLK"] = fsm_cell->connections["\\CLK"];
- state_dff->connections["\\D"] = RTLIL::SigSpec(next_state_wire);
- state_dff->connections["\\Q"] = RTLIL::SigSpec(state_wire);
- module->add(state_dff);
+ state_dff->setPort("\\CLK", fsm_cell->getPort("\\CLK"));
+ state_dff->setPort("\\D", RTLIL::SigSpec(next_state_wire));
+ state_dff->setPort("\\Q", RTLIL::SigSpec(state_wire));
// decode state register
bool encoding_is_onehot = true;
- RTLIL::Wire *state_onehot = new RTLIL::Wire;
- state_onehot->name = NEW_ID;
- state_onehot->width = fsm_data.state_table.size();
- module->add(state_onehot);
+ RTLIL::Wire *state_onehot = module->addWire(NEW_ID, fsm_data.state_table.size());
for (size_t i = 0; i < fsm_data.state_table.size(); i++)
{
@@ -215,111 +197,102 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
for (size_t j = 0; j < state.bits.size(); j++)
if (state.bits[j] == RTLIL::State::S0 || state.bits[j] == RTLIL::State::S1) {
- sig_a.append(RTLIL::SigSpec(state_wire, 1, j));
+ sig_a.append(RTLIL::SigSpec(state_wire, j));
sig_b.append(RTLIL::SigSpec(state.bits[j]));
}
- sig_a.optimize();
- sig_b.optimize();
if (sig_b == RTLIL::SigSpec(RTLIL::State::S1))
{
- module->connections.push_back(RTLIL::SigSig(RTLIL::SigSpec(state_onehot, 1, i), sig_a));
+ module->connect(RTLIL::SigSig(RTLIL::SigSpec(state_onehot, i), sig_a));
}
else
{
encoding_is_onehot = false;
- RTLIL::Cell *eq_cell = new RTLIL::Cell;
- eq_cell->name = NEW_ID;
- eq_cell->type = "$eq";
- eq_cell->connections["\\A"] = sig_a;
- eq_cell->connections["\\B"] = sig_b;
- eq_cell->connections["\\Y"] = RTLIL::SigSpec(state_onehot, 1, i);
+ RTLIL::Cell *eq_cell = module->addCell(NEW_ID, "$eq");
+ eq_cell->setPort("\\A", sig_a);
+ eq_cell->setPort("\\B", sig_b);
+ eq_cell->setPort("\\Y", RTLIL::SigSpec(state_onehot, i));
eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(false);
eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(false);
- eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig_a.width);
- eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(sig_b.width);
+ eq_cell->parameters["\\A_WIDTH"] = RTLIL::Const(sig_a.size());
+ eq_cell->parameters["\\B_WIDTH"] = RTLIL::Const(sig_b.size());
eq_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
- module->add(eq_cell);
}
}
// generate next_state signal
- RTLIL::Wire *next_state_onehot = new RTLIL::Wire;
- next_state_onehot->name = NEW_ID;
- next_state_onehot->width = fsm_data.state_table.size();
- module->add(next_state_onehot);
-
- for (size_t i = 0; i < fsm_data.state_table.size(); i++)
+ if (SIZE(fsm_data.state_table) == 1)
{
- std::map<RTLIL::Const, std::set<int>> pattern_cache;
- std::set<int> fullstate_cache;
+ module->connect(next_state_wire, fsm_data.state_table.front());
+ }
+ else
+ {
+ RTLIL::Wire *next_state_onehot = module->addWire(NEW_ID, fsm_data.state_table.size());
- for (size_t j = 0; j < fsm_data.state_table.size(); j++)
- fullstate_cache.insert(j);
+ for (size_t i = 0; i < fsm_data.state_table.size(); i++)
+ {
+ std::map<RTLIL::Const, std::set<int>> pattern_cache;
+ std::set<int> fullstate_cache;
- for (auto &tr : fsm_data.transition_table) {
- if (tr.state_out == int(i))
- pattern_cache[tr.ctrl_in].insert(tr.state_in);
- else
- fullstate_cache.erase(tr.state_in);
- }
+ for (size_t j = 0; j < fsm_data.state_table.size(); j++)
+ fullstate_cache.insert(j);
- implement_pattern_cache(module, pattern_cache, fullstate_cache, fsm_data.state_table.size(), state_onehot, ctrl_in, RTLIL::SigSpec(next_state_onehot, 1, i));
- }
+ for (auto &tr : fsm_data.transition_table) {
+ if (tr.state_out == int(i))
+ pattern_cache[tr.ctrl_in].insert(tr.state_in);
+ else
+ fullstate_cache.erase(tr.state_in);
+ }
- if (encoding_is_onehot)
- {
- RTLIL::SigSpec next_state_sig(RTLIL::State::Sm, next_state_wire->width);
- for (size_t i = 0; i < fsm_data.state_table.size(); i++) {
- RTLIL::Const state = fsm_data.state_table[i];
- int bit_idx = -1;
- for (size_t j = 0; j < state.bits.size(); j++)
- if (state.bits[j] == RTLIL::State::S1)
- bit_idx = j;
- if (bit_idx >= 0)
- next_state_sig.replace(bit_idx, RTLIL::SigSpec(next_state_onehot, 1, i));
+ implement_pattern_cache(module, pattern_cache, fullstate_cache, fsm_data.state_table.size(), state_onehot, ctrl_in, RTLIL::SigSpec(next_state_onehot, i));
}
- log_assert(!next_state_sig.has_marked_bits());
- module->connections.push_back(RTLIL::SigSig(next_state_wire, next_state_sig));
- }
- else
- {
- RTLIL::SigSpec sig_a, sig_b, sig_s;
- int reset_state = fsm_data.reset_state;
- if (reset_state < 0)
- reset_state = 0;
-
- for (size_t i = 0; i < fsm_data.state_table.size(); i++) {
- RTLIL::Const state = fsm_data.state_table[i];
- if (int(i) == fsm_data.reset_state) {
- sig_a = RTLIL::SigSpec(state);
- } else {
- sig_b.append(RTLIL::SigSpec(state));
- sig_s.append(RTLIL::SigSpec(next_state_onehot, 1, i));
+
+ if (encoding_is_onehot)
+ {
+ RTLIL::SigSpec next_state_sig(RTLIL::State::Sm, next_state_wire->width);
+ for (size_t i = 0; i < fsm_data.state_table.size(); i++) {
+ RTLIL::Const state = fsm_data.state_table[i];
+ int bit_idx = -1;
+ for (size_t j = 0; j < state.bits.size(); j++)
+ if (state.bits[j] == RTLIL::State::S1)
+ bit_idx = j;
+ if (bit_idx >= 0)
+ next_state_sig.replace(bit_idx, RTLIL::SigSpec(next_state_onehot, i));
}
+ log_assert(!next_state_sig.has_marked_bits());
+ module->connect(RTLIL::SigSig(next_state_wire, next_state_sig));
}
+ else
+ {
+ RTLIL::SigSpec sig_a, sig_b, sig_s;
+ int reset_state = fsm_data.reset_state;
+ if (reset_state < 0)
+ reset_state = 0;
+
+ for (size_t i = 0; i < fsm_data.state_table.size(); i++) {
+ RTLIL::Const state = fsm_data.state_table[i];
+ if (int(i) == fsm_data.reset_state) {
+ sig_a = RTLIL::SigSpec(state);
+ } else {
+ sig_b.append(RTLIL::SigSpec(state));
+ sig_s.append(RTLIL::SigSpec(next_state_onehot, i));
+ }
+ }
- RTLIL::Cell *mux_cell = new RTLIL::Cell;
- mux_cell->name = NEW_ID;
- mux_cell->type = "$safe_pmux";
- mux_cell->connections["\\A"] = sig_a;
- mux_cell->connections["\\B"] = sig_b;
- mux_cell->connections["\\S"] = sig_s;
- mux_cell->connections["\\Y"] = RTLIL::SigSpec(next_state_wire);
- mux_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_a.width);
- mux_cell->parameters["\\S_WIDTH"] = RTLIL::Const(sig_s.width);
- module->add(mux_cell);
+ RTLIL::Cell *mux_cell = module->addCell(NEW_ID, "$pmux");
+ mux_cell->setPort("\\A", sig_a);
+ mux_cell->setPort("\\B", sig_b);
+ mux_cell->setPort("\\S", sig_s);
+ mux_cell->setPort("\\Y", RTLIL::SigSpec(next_state_wire));
+ mux_cell->parameters["\\WIDTH"] = RTLIL::Const(sig_a.size());
+ mux_cell->parameters["\\S_WIDTH"] = RTLIL::Const(sig_s.size());
+ }
}
// Generate ctrl_out signal
- RTLIL::Wire *ctrl_out_wire = new RTLIL::Wire;
- ctrl_out_wire->name = NEW_ID;
- ctrl_out_wire->width = fsm_data.num_outputs;
- module->add(ctrl_out_wire);
-
for (int i = 0; i < fsm_data.num_outputs; i++)
{
std::map<RTLIL::Const, std::set<int>> pattern_cache;
@@ -340,8 +313,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
// Remove FSM cell
- module->cells.erase(fsm_cell->name);
- delete fsm_cell;
+ module->remove(fsm_cell);
}
struct FsmMapPass : public Pass {
@@ -360,11 +332,11 @@ struct FsmMapPass : public Pass {
log_header("Executing FSM_MAP pass (mapping FSMs to basic logic).\n");
extra_args(args, 1, design);
- for (auto &mod_it : design->modules) {
+ for (auto &mod_it : design->modules_) {
if (!design->selected(mod_it.second))
continue;
std::vector<RTLIL::Cell*> fsm_cells;
- for (auto &cell_it : mod_it.second->cells)
+ for (auto &cell_it : mod_it.second->cells_)
if (cell_it.second->type == "$fsm" && design->selected(mod_it.second, cell_it.second))
fsm_cells.push_back(cell_it.second);
for (auto cell : fsm_cells)