aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/bitstream.cc
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-08-03 09:26:37 +0200
committerDavid Shah <davey1576@gmail.com>2018-08-03 09:26:37 +0200
commit35bc80e13057aeaad15c06f8c6bf0686328532e6 (patch)
treeb7883be95336ea6b13bb18b5c350c06bf08354a6 /ice40/bitstream.cc
parent36009645ced93d87278de2097843f8586e6ef937 (diff)
downloadnextpnr-35bc80e13057aeaad15c06f8c6bf0686328532e6.tar.gz
nextpnr-35bc80e13057aeaad15c06f8c6bf0686328532e6.tar.bz2
nextpnr-35bc80e13057aeaad15c06f8c6bf0686328532e6.zip
ice40: Add bitstream gen for routethru LUTs
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ice40/bitstream.cc')
-rw-r--r--ice40/bitstream.cc67
1 files changed, 58 insertions, 9 deletions
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index d0d6b205..8b00e878 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -221,8 +221,21 @@ std::string tagTileType(TileType &tile)
NPNR_ASSERT(false);
}
}
+
+static BelPin get_one_bel_pin(const Context *ctx, WireId wire)
+{
+ auto pins = ctx->getWireBelPins(wire);
+ NPNR_ASSERT(pins.begin() != pins.end());
+ return *pins.begin();
+}
+
void write_asc(const Context *ctx, std::ostream &out)
{
+
+ static const std::vector<int> lut_perm = {
+ 4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0,
+ };
+
// [y][x][row][col]
const ChipInfoPOD &ci = *ctx->chip_info;
const BitstreamInfoPOD &bi = *ci.bits_info;
@@ -262,12 +275,50 @@ void write_asc(const Context *ctx, std::ostream &out)
if (ctx->pip_to_net[pip.index] != IdString()) {
const PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
- for (int i = 0; i < swi.num_bits; i++) {
- bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
- int8_t &cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col);
- if (bool(cbit) != 0)
- NPNR_ASSERT(false);
- cbit = val;
+ int sw_bel_idx = swi.bel;
+ if (sw_bel_idx >= 0) {
+ const BelInfoPOD &beli = ci.bel_data[sw_bel_idx];
+ const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
+ BelId sw_bel;
+ sw_bel.index = sw_bel_idx;
+ NPNR_ASSERT(ctx->getBelType(sw_bel) == TYPE_ICESTORM_LC);
+ BelPin input = get_one_bel_pin(ctx, ctx->getPipSrcWire(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);
+ unsigned lut_init;
+ switch (input.pin) {
+ case PIN_I0:
+ lut_init = 2;
+ break;
+ case PIN_I1:
+ lut_init = 4;
+ break;
+ case PIN_I2:
+ lut_init = 16;
+ break;
+ case PIN_I3:
+ lut_init = 256;
+ break;
+ default:
+ NPNR_ASSERT_FALSE("bad feedthru LUT input");
+ }
+ std::vector<bool> lc(20, false);
+ for (int i = 0; i < 16; i++) {
+ if ((lut_init >> i) & 0x1)
+ lc.at(lut_perm.at(i)) = true;
+ }
+
+ for (int i = 0; i < 20; i++)
+ set_config(ti, config.at(beli.y).at(beli.x), "LC_" + std::to_string(beli.z), lc.at(i), i);
+ } else {
+ for (int i = 0; i < swi.num_bits; i++) {
+ bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
+ int8_t &cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col);
+ if (bool(cbit) != 0)
+ NPNR_ASSERT(false);
+ cbit = val;
+ }
}
}
}
@@ -295,9 +346,7 @@ void write_asc(const Context *ctx, std::ostream &out)
bool carry_enable = get_param_or_def(cell.second.get(), ctx->id("CARRY_ENABLE"));
std::vector<bool> lc(20, false);
// From arachne-pnr
- static std::vector<int> lut_perm = {
- 4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0,
- };
+
for (int i = 0; i < 16; i++) {
if ((lut_init >> i) & 0x1)
lc.at(lut_perm.at(i)) = true;