mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Added "shregmap -tech greenpak4"
This commit is contained in:
parent
779e2cc819
commit
7311be4028
|
@ -23,12 +23,20 @@
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct ShregmapTech
|
||||||
|
{
|
||||||
|
virtual ~ShregmapTech() { }
|
||||||
|
virtual bool check_taps(const dict<int, SigBit> &taps) = 0;
|
||||||
|
virtual bool fixup_shreg(Cell *cell, dict<int, SigBit> &taps) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct ShregmapOptions
|
struct ShregmapOptions
|
||||||
{
|
{
|
||||||
int minlen, maxlen;
|
int minlen, maxlen;
|
||||||
int keep_before, keep_after;
|
int keep_before, keep_after;
|
||||||
bool zinit, init, params, ffe;
|
bool zinit, init, params, ffe;
|
||||||
dict<IdString, pair<IdString, IdString>> ffcells;
|
dict<IdString, pair<IdString, IdString>> ffcells;
|
||||||
|
ShregmapTech *tech;
|
||||||
|
|
||||||
ShregmapOptions()
|
ShregmapOptions()
|
||||||
{
|
{
|
||||||
|
@ -40,6 +48,42 @@ struct ShregmapOptions
|
||||||
init = false;
|
init = false;
|
||||||
params = false;
|
params = false;
|
||||||
ffe = false;
|
ffe = false;
|
||||||
|
tech = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShregmapTechGreenpak4 : ShregmapTech
|
||||||
|
{
|
||||||
|
bool check_taps(const dict<int, SigBit> &taps)
|
||||||
|
{
|
||||||
|
if (GetSize(taps) > 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto tap : taps)
|
||||||
|
if (tap.first > 16) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fixup_shreg(Cell *cell, dict<int, SigBit> &taps)
|
||||||
|
{
|
||||||
|
auto D = cell->getPort("\\D");
|
||||||
|
auto C = cell->getPort("\\C");
|
||||||
|
|
||||||
|
auto newcell = cell->module->addCell(NEW_ID, "\\GP_SHREG");
|
||||||
|
newcell->setPort("\\nRST", State::S1);
|
||||||
|
newcell->setPort("\\CLK", C);
|
||||||
|
newcell->setPort("\\IN", D);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto tap : taps) {
|
||||||
|
newcell->setPort(i ? "\\OUTB" : "\\OUTA", tap.second);
|
||||||
|
newcell->setParam(i ? "\\OUTB_DELAY" : "\\OUTA_DELAY", tap.first + 1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell->setParam("\\OUTA_INVERT", 0);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +134,8 @@ struct ShregmapWorker
|
||||||
SigBit d_bit = sigmap(cell->getPort(d_port).as_bit());
|
SigBit d_bit = sigmap(cell->getPort(d_port).as_bit());
|
||||||
SigBit q_bit = sigmap(cell->getPort(q_port).as_bit());
|
SigBit q_bit = sigmap(cell->getPort(q_port).as_bit());
|
||||||
|
|
||||||
if (opts.init || sigbit_init.count(q_bit) == 0) {
|
if (opts.init || sigbit_init.count(q_bit) == 0)
|
||||||
|
{
|
||||||
if (sigbit_chain_next.count(d_bit)) {
|
if (sigbit_chain_next.count(d_bit)) {
|
||||||
sigbit_with_non_chain_users.insert(d_bit);
|
sigbit_with_non_chain_users.insert(d_bit);
|
||||||
} else
|
} else
|
||||||
|
@ -112,8 +157,8 @@ struct ShregmapWorker
|
||||||
{
|
{
|
||||||
for (auto it : sigbit_chain_next)
|
for (auto it : sigbit_chain_next)
|
||||||
{
|
{
|
||||||
if (sigbit_with_non_chain_users.count(it.first))
|
if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first))
|
||||||
continue;
|
goto start_cell;
|
||||||
|
|
||||||
if (sigbit_chain_prev.count(it.first) != 0)
|
if (sigbit_chain_prev.count(it.first) != 0)
|
||||||
{
|
{
|
||||||
|
@ -185,11 +230,36 @@ struct ShregmapWorker
|
||||||
if (opts.maxlen > 0)
|
if (opts.maxlen > 0)
|
||||||
depth = std::min(opts.maxlen, depth);
|
depth = std::min(opts.maxlen, depth);
|
||||||
|
|
||||||
Cell *first_cell = chain[cursor], *last_cell = chain[cursor+depth-1];
|
Cell *first_cell = chain[cursor];
|
||||||
|
IdString q_port = opts.ffcells.at(first_cell->type).second;
|
||||||
|
dict<int, SigBit> taps;
|
||||||
|
|
||||||
|
if (opts.tech)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < depth; i++)
|
||||||
|
{
|
||||||
|
Cell *cell = chain[cursor+i];
|
||||||
|
auto qbit = sigmap(cell->getPort(q_port));
|
||||||
|
|
||||||
|
if (sigbit_with_non_chain_users.count(qbit))
|
||||||
|
taps[i] = qbit;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (depth > 0)
|
||||||
|
{
|
||||||
|
Cell *last_cell = chain[cursor+depth-1];
|
||||||
|
taps[depth-1] = sigmap(last_cell->getPort(q_port));
|
||||||
|
if (opts.tech->check_taps(taps))
|
||||||
|
break;
|
||||||
|
taps.erase(--depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (depth < 2)
|
if (depth < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Cell *last_cell = chain[cursor+depth-1];
|
||||||
|
|
||||||
log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n",
|
log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n",
|
||||||
log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth);
|
log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth);
|
||||||
|
|
||||||
|
@ -205,8 +275,6 @@ struct ShregmapWorker
|
||||||
shreg_cell_type_str += first_cell->type.substr(1);
|
shreg_cell_type_str += first_cell->type.substr(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString q_port = opts.ffcells.at(first_cell->type).second;
|
|
||||||
|
|
||||||
if (opts.init) {
|
if (opts.init) {
|
||||||
vector<State> initval;
|
vector<State> initval;
|
||||||
for (int i = depth-1; i >= 0; i--) {
|
for (int i = depth-1; i >= 0; i--) {
|
||||||
|
@ -250,6 +318,9 @@ struct ShregmapWorker
|
||||||
first_cell->setPort(q_port, last_cell->getPort(q_port));
|
first_cell->setPort(q_port, last_cell->getPort(q_port));
|
||||||
first_cell->setParam("\\DEPTH", depth);
|
first_cell->setParam("\\DEPTH", depth);
|
||||||
|
|
||||||
|
if (opts.tech != nullptr && !opts.tech->fixup_shreg(first_cell, taps))
|
||||||
|
remove_cells.insert(first_cell);
|
||||||
|
|
||||||
for (int i = 1; i < depth; i++)
|
for (int i = 1; i < depth; i++)
|
||||||
remove_cells.insert(chain[cursor+i]);
|
remove_cells.insert(chain[cursor+i]);
|
||||||
cursor += depth;
|
cursor += depth;
|
||||||
|
@ -354,6 +425,9 @@ struct ShregmapPass : public Pass {
|
||||||
log(" generated cells with the initialization value. (first bit to shift out\n");
|
log(" generated cells with the initialization value. (first bit to shift out\n");
|
||||||
log(" in LSB position)\n");
|
log(" in LSB position)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -tech greenpak4\n");
|
||||||
|
log(" map to greenpak4 shift registers.\n");
|
||||||
|
log("\n");
|
||||||
}
|
}
|
||||||
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
|
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
|
||||||
{
|
{
|
||||||
|
@ -401,6 +475,18 @@ struct ShregmapPass : public Pass {
|
||||||
opts.keep_after = atoi(args[++argidx].c_str());
|
opts.keep_after = atoi(args[++argidx].c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-tech" && argidx+1 < args.size() && opts.tech == nullptr) {
|
||||||
|
string tech = args[++argidx];
|
||||||
|
if (tech == "greenpak4") {
|
||||||
|
clkpol = "pos";
|
||||||
|
opts.maxlen = 16;
|
||||||
|
opts.tech = new ShregmapTechGreenpak4;
|
||||||
|
} else {
|
||||||
|
argidx--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (args[argidx] == "-zinit") {
|
if (args[argidx] == "-zinit") {
|
||||||
opts.zinit = true;
|
opts.zinit = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -467,6 +553,11 @@ struct ShregmapPass : public Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
log("Converted %d dff cells into %d shift registers.\n", dff_count, shreg_count);
|
log("Converted %d dff cells into %d shift registers.\n", dff_count, shreg_count);
|
||||||
|
|
||||||
|
if (opts.tech != nullptr) {
|
||||||
|
delete opts.tech;
|
||||||
|
opts.tech = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} ShregmapPass;
|
} ShregmapPass;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue