ecp5: Improve handling of constant CCU2C inputs
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
e7c8818424
commit
931c78b1bb
74
ecp5/pack.cc
74
ecp5/pack.cc
@ -637,14 +637,12 @@ class Ecp5Packer
|
|||||||
flush_cells();
|
flush_cells();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_lut_input_constant(CellInfo *cell, IdString input, bool value)
|
int make_init_with_const_input(int init, int input, bool value)
|
||||||
{
|
{
|
||||||
int index = std::string("ABCD").find(input.str(ctx));
|
|
||||||
int init = int_or_default(cell->params, ctx->id("INIT"));
|
|
||||||
int new_init = 0;
|
int new_init = 0;
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
if (((i >> index) & 0x1) != value) {
|
if (((i >> input) & 0x1) != value) {
|
||||||
int other_i = (i & (~(1 << index))) | (value << index);
|
int other_i = (i & (~(1 << input))) | (value << input);
|
||||||
if ((init >> other_i) & 0x1)
|
if ((init >> other_i) & 0x1)
|
||||||
new_init |= (1 << i);
|
new_init |= (1 << i);
|
||||||
} else {
|
} else {
|
||||||
@ -652,10 +650,41 @@ class Ecp5Packer
|
|||||||
new_init |= (1 << i);
|
new_init |= (1 << i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_lut_input_constant(CellInfo *cell, IdString input, bool value)
|
||||||
|
{
|
||||||
|
int index = std::string("ABCD").find(input.str(ctx));
|
||||||
|
int init = int_or_default(cell->params, ctx->id("INIT"));
|
||||||
|
int new_init = make_init_with_const_input(init, index, value);
|
||||||
cell->params[ctx->id("INIT")] = std::to_string(new_init);
|
cell->params[ctx->id("INIT")] = std::to_string(new_init);
|
||||||
cell->ports.at(input).net = nullptr;
|
cell->ports.at(input).net = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_ccu2c_input_constant(CellInfo *cell, IdString input, bool value)
|
||||||
|
{
|
||||||
|
std::string input_str = input.str(ctx);
|
||||||
|
int lut = std::stoi(input_str.substr(1));
|
||||||
|
int index = std::string("ABCD").find(input_str[0]);
|
||||||
|
int init = int_or_default(cell->params, ctx->id("INIT" + std::to_string(lut)));
|
||||||
|
int new_init = make_init_with_const_input(init, index, value);
|
||||||
|
cell->params[ctx->id("INIT" + std::to_string(lut))] = std::to_string(new_init);
|
||||||
|
cell->ports.at(input).net = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ccu2c_port_high(CellInfo *cell, IdString input)
|
||||||
|
{
|
||||||
|
if (!cell->ports.count(input))
|
||||||
|
return true; // disconnected port is high
|
||||||
|
if (cell->ports.at(input).net == nullptr || cell->ports.at(input).net->name == ctx->id("$PACKER_VCC_NET"))
|
||||||
|
return true; // disconnected or tied-high port
|
||||||
|
if (cell->ports.at(input).net->driver.cell != nullptr &&
|
||||||
|
cell->ports.at(input).net->driver.cell->type == ctx->id("VCC"))
|
||||||
|
return true; // pre-pack high
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Merge a net into a constant net
|
// Merge a net into a constant net
|
||||||
void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval)
|
void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constnet, bool constval)
|
||||||
{
|
{
|
||||||
@ -670,10 +699,37 @@ class Ecp5Packer
|
|||||||
} else if (is_ff(ctx, uc) && user.port == ctx->id("CE")) {
|
} else if (is_ff(ctx, uc) && user.port == ctx->id("CE")) {
|
||||||
uc->params[ctx->id("CEMUX")] = constval ? "1" : "0";
|
uc->params[ctx->id("CEMUX")] = constval ? "1" : "0";
|
||||||
uc->ports[user.port].net = nullptr;
|
uc->ports[user.port].net = nullptr;
|
||||||
} else if (is_carry(ctx, uc) && constval &&
|
} else if (is_carry(ctx, uc)) {
|
||||||
(user.port == id_A0 || user.port == id_A1 || user.port == id_B0 || user.port == id_B1 ||
|
if (constval &&
|
||||||
user.port == id_C0 || user.port == id_C1 || user.port == id_D0 || user.port == id_D1)) {
|
(user.port == id_A0 || user.port == id_A1 || user.port == id_B0 || user.port == id_B1 ||
|
||||||
uc->ports[user.port].net = nullptr;
|
user.port == id_C0 || user.port == id_C1 || user.port == id_D0 || user.port == id_D1)) {
|
||||||
|
// Input tied high, nothing special to do (bitstream gen will auto-enable tie-high)
|
||||||
|
uc->ports[user.port].net = nullptr;
|
||||||
|
} else if (!constval) {
|
||||||
|
if (user.port == id_A0 || user.port == id_A1 || user.port == id_B0 || user.port == id_B1) {
|
||||||
|
// These inputs can be switched to tie-high without consequence
|
||||||
|
set_ccu2c_input_constant(uc, user.port, constval);
|
||||||
|
} else if (user.port == id_C0 && is_ccu2c_port_high(uc, id_D0)) {
|
||||||
|
// Partner must be tied high
|
||||||
|
set_ccu2c_input_constant(uc, user.port, constval);
|
||||||
|
} else if (user.port == id_D0 && is_ccu2c_port_high(uc, id_C0)) {
|
||||||
|
// Partner must be tied high
|
||||||
|
set_ccu2c_input_constant(uc, user.port, constval);
|
||||||
|
} else if (user.port == id_C1 && is_ccu2c_port_high(uc, id_D1)) {
|
||||||
|
// Partner must be tied high
|
||||||
|
set_ccu2c_input_constant(uc, user.port, constval);
|
||||||
|
} else if (user.port == id_D1 && is_ccu2c_port_high(uc, id_C1)) {
|
||||||
|
// Partner must be tied high
|
||||||
|
set_ccu2c_input_constant(uc, user.port, constval);
|
||||||
|
} else {
|
||||||
|
// Not allowed to change to a tie-high
|
||||||
|
uc->ports[user.port].net = constnet;
|
||||||
|
constnet->users.push_back(user);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uc->ports[user.port].net = constnet;
|
||||||
|
constnet->users.push_back(user);
|
||||||
|
}
|
||||||
} else if (is_ff(ctx, uc) && user.port == ctx->id("LSR") &&
|
} else if (is_ff(ctx, uc) && user.port == ctx->id("LSR") &&
|
||||||
((!constval && str_or_default(uc->params, ctx->id("LSRMUX"), "LSR") == "LSR") ||
|
((!constval && str_or_default(uc->params, ctx->id("LSRMUX"), "LSR") == "LSR") ||
|
||||||
(constval && str_or_default(uc->params, ctx->id("LSRMUX"), "LSR") == "INV"))) {
|
(constval && str_or_default(uc->params, ctx->id("LSRMUX"), "LSR") == "INV"))) {
|
||||||
|
Loading…
Reference in New Issue
Block a user