ice40: Bitstream gen for LUT permutation
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
8aaf845670
commit
67347573c2
@ -229,6 +229,24 @@ static BelPin get_one_bel_pin(const Context *ctx, WireId wire)
|
|||||||
return *pins.begin();
|
return *pins.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permute LUT init value given map (LUT input -> ext input)
|
||||||
|
unsigned permute_lut(unsigned orig_init, const std::unordered_map<int, int> &input_permute) {
|
||||||
|
unsigned new_init = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int permute_address = 0;
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
if ((i >> j) & 0x1)
|
||||||
|
permute_address |= (1 << input_permute.at(j));
|
||||||
|
}
|
||||||
|
if ((orig_init >> i) & 0x1) {
|
||||||
|
new_init |= (1 << permute_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_init;
|
||||||
|
}
|
||||||
|
|
||||||
void write_asc(const Context *ctx, std::ostream &out)
|
void write_asc(const Context *ctx, std::ostream &out)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -282,22 +300,33 @@ void write_asc(const Context *ctx, std::ostream &out)
|
|||||||
BelId sw_bel;
|
BelId sw_bel;
|
||||||
sw_bel.index = sw_bel_idx;
|
sw_bel.index = sw_bel_idx;
|
||||||
NPNR_ASSERT(ctx->getBelType(sw_bel) == TYPE_ICESTORM_LC);
|
NPNR_ASSERT(ctx->getBelType(sw_bel) == TYPE_ICESTORM_LC);
|
||||||
BelPin input = get_one_bel_pin(ctx, ctx->getPipSrcWire(pip));
|
|
||||||
|
if (ci.wire_data[ctx->getPipDstWire(pip).index].type == WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT)
|
||||||
|
continue; // Permutation pips
|
||||||
BelPin output = get_one_bel_pin(ctx, ctx->getPipDstWire(pip));
|
BelPin output = get_one_bel_pin(ctx, ctx->getPipDstWire(pip));
|
||||||
NPNR_ASSERT(input.bel == sw_bel);
|
|
||||||
NPNR_ASSERT(output.bel == sw_bel && output.pin == PIN_O);
|
NPNR_ASSERT(output.bel == sw_bel && output.pin == PIN_O);
|
||||||
unsigned lut_init;
|
unsigned lut_init;
|
||||||
switch (input.pin) {
|
|
||||||
case PIN_I0:
|
WireId permWire;
|
||||||
|
for (auto permPip : ctx->getPipsUphill(ctx->getPipSrcWire(pip))) {
|
||||||
|
if (ctx->getBoundPipNet(permPip) != IdString()) {
|
||||||
|
permWire = ctx->getPipSrcWire(permPip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NPNR_ASSERT(permWire != WireId());
|
||||||
|
std::string dName = ci.wire_data[permWire.index].name.get();
|
||||||
|
|
||||||
|
switch (dName.back()) {
|
||||||
|
case '0':
|
||||||
lut_init = 2;
|
lut_init = 2;
|
||||||
break;
|
break;
|
||||||
case PIN_I1:
|
case '1':
|
||||||
lut_init = 4;
|
lut_init = 4;
|
||||||
break;
|
break;
|
||||||
case PIN_I2:
|
case '2':
|
||||||
lut_init = 16;
|
lut_init = 16;
|
||||||
break;
|
break;
|
||||||
case PIN_I3:
|
case '3':
|
||||||
lut_init = 256;
|
lut_init = 256;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -345,8 +374,49 @@ void write_asc(const Context *ctx, std::ostream &out)
|
|||||||
bool set_noreset = get_param_or_def(cell.second.get(), ctx->id("SET_NORESET"));
|
bool set_noreset = get_param_or_def(cell.second.get(), ctx->id("SET_NORESET"));
|
||||||
bool carry_enable = get_param_or_def(cell.second.get(), ctx->id("CARRY_ENABLE"));
|
bool carry_enable = get_param_or_def(cell.second.get(), ctx->id("CARRY_ENABLE"));
|
||||||
std::vector<bool> lc(20, false);
|
std::vector<bool> lc(20, false);
|
||||||
// From arachne-pnr
|
|
||||||
|
|
||||||
|
// Discover permutation
|
||||||
|
std::unordered_map<int, int> input_perm;
|
||||||
|
std::set<int> unused;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
unused.insert(i);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
WireId lut_wire = ctx->getBelPinWire(bel, PortPin(PIN_I0+i));
|
||||||
|
for (auto pip : ctx->getPipsUphill(lut_wire)) {
|
||||||
|
if (ctx->getBoundPipNet(pip) != IdString()) {
|
||||||
|
std::string name = ci.wire_data[ctx->getPipSrcWire(pip).index].name.get();
|
||||||
|
switch(name.back()) {
|
||||||
|
case '0':
|
||||||
|
input_perm[i] = 0;
|
||||||
|
unused.erase(0);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
input_perm[i] = 1;
|
||||||
|
unused.erase(1);
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
input_perm[i] = 2;
|
||||||
|
unused.erase(2);
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
input_perm[i] = 3;
|
||||||
|
unused.erase(3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NPNR_ASSERT_FALSE("failed to determine LUT permutation");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (!input_perm.count(i)) {
|
||||||
|
NPNR_ASSERT(!unused.empty());
|
||||||
|
input_perm[i] = *(unused.begin());
|
||||||
|
unused.erase(input_perm[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lut_init = permute_lut(lut_init, input_perm);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
if ((lut_init >> i) & 0x1)
|
if ((lut_init >> i) & 0x1)
|
||||||
lc.at(lut_perm.at(i)) = true;
|
lc.at(lut_perm.at(i)) = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user