Populate LUT masks
This commit is contained in:
parent
a7ccc01c45
commit
07fb4702ce
@ -44,7 +44,7 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
||||
new_cell->type = type;
|
||||
if (type == ctx->id("XC7_LC")) {
|
||||
new_cell->type = id_SLICE_LUT6;
|
||||
new_cell->params[ctx->id("LUT_INIT")] = "0";
|
||||
new_cell->params[ctx->id("INIT")] = "0";
|
||||
new_cell->params[ctx->id("NEG_CLK")] = "0";
|
||||
new_cell->params[ctx->id("CARRY_ENABLE")] = "0";
|
||||
new_cell->params[ctx->id("DFF_ENABLE")] = "0";
|
||||
@ -258,7 +258,7 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
||||
|
||||
void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
|
||||
{
|
||||
lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")];
|
||||
lc->params[ctx->id("INIT")] = lut->params[ctx->id("INIT")];
|
||||
replace_port(lut, ctx->id("I0"), lc, id_I1);
|
||||
if (get_net_or_empty(lut, id_I1))
|
||||
replace_port(lut, id_I1, lc, id_I2);
|
||||
@ -317,7 +317,7 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
|
||||
NPNR_ASSERT(citer == config.end());
|
||||
|
||||
if (pass_thru_lut) {
|
||||
lc->params[ctx->id("LUT_INIT")] = "2";
|
||||
lc->params[ctx->id("INIT")] = "1";
|
||||
replace_port(dff, ctx->id("D"), lc, id_I1);
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ static void pack_constants(Context *ctx)
|
||||
log_info("Packing constants..\n");
|
||||
|
||||
std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, ctx->id("XC7_LC"), "$PACKER_GND");
|
||||
gnd_cell->params[ctx->id("LUT_INIT")] = "0";
|
||||
gnd_cell->params[ctx->id("INIT")] = "0";
|
||||
std::unique_ptr<NetInfo> gnd_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||
gnd_net->name = ctx->id("$PACKER_GND_NET");
|
||||
gnd_net->driver.cell = gnd_cell.get();
|
||||
@ -340,7 +340,7 @@ static void pack_constants(Context *ctx)
|
||||
gnd_cell->ports.at(id_O).net = gnd_net.get();
|
||||
|
||||
std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, ctx->id("XC7_LC"), "$PACKER_VCC");
|
||||
vcc_cell->params[ctx->id("LUT_INIT")] = "1";
|
||||
vcc_cell->params[ctx->id("INIT")] = "1";
|
||||
std::unique_ptr<NetInfo> vcc_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||
vcc_net->name = ctx->id("$PACKER_VCC_NET");
|
||||
vcc_net->driver.cell = vcc_cell.get();
|
||||
@ -585,7 +585,7 @@ static std::unique_ptr<CellInfo> spliceLUT(Context *ctx, CellInfo *ci, IdString
|
||||
// Create pass-through LUT.
|
||||
std::unique_ptr<CellInfo> pt = create_ice_cell(ctx, ctx->id("XC7_LC"),
|
||||
ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through");
|
||||
pt->params[ctx->id("LUT_INIT")] = "65280"; // output is always I3
|
||||
pt->params[ctx->id("INIT")] = "65280"; // output is always I3
|
||||
|
||||
// Create LUT output net.
|
||||
std::unique_ptr<NetInfo> out_net = std::unique_ptr<NetInfo>(new NetInfo);
|
||||
|
73
xc7/xdl.cc
73
xc7/xdl.cc
@ -38,6 +38,8 @@ void write_xdl(const Context *ctx, std::ostream &out)
|
||||
auto designPtr = Factory::newDesignPtr("name", torc_info->ddb->getDeviceName(), "clg484", "", "");
|
||||
|
||||
std::unordered_map<int32_t,InstanceSharedPtr> site_to_instance;
|
||||
std::vector<std::pair<std::string,std::string>> lut_inputs;
|
||||
lut_inputs.reserve(6);
|
||||
|
||||
for (const auto& cell : ctx->cells) {
|
||||
const char* type;
|
||||
@ -63,16 +65,73 @@ void write_xdl(const Context *ctx, std::ostream &out)
|
||||
instPtr = ret.first->second;
|
||||
|
||||
if (cell.second->type == id_SLICE_LUT6) {
|
||||
std::string config;
|
||||
std::string setting, value;
|
||||
std::string lut;
|
||||
switch (torc_info->bel_to_z[cell.second->bel.index]) {
|
||||
case 0: case 4: config += 'A'; break;
|
||||
case 1: case 5: config += 'B'; break;
|
||||
case 2: case 6: config += 'C'; break;
|
||||
case 3: case 7: config += 'D'; break;
|
||||
case 0: case 4: lut = 'A'; break;
|
||||
case 1: case 5: lut = 'B'; break;
|
||||
case 2: case 6: lut = 'C'; break;
|
||||
case 3: case 7: lut = 'D'; break;
|
||||
default: throw;
|
||||
}
|
||||
config += "6LUT";
|
||||
instPtr->setConfig(config, cell.second->name.str(ctx), "#LUT:O6=");
|
||||
|
||||
setting = lut + "6LUT";
|
||||
value = "#LUT:O6=";
|
||||
lut_inputs.clear();
|
||||
if (get_net_or_empty(cell.second.get(), id_I1)) lut_inputs.emplace_back(lut + "1", "~" + lut + "1");
|
||||
if (get_net_or_empty(cell.second.get(), id_I2)) lut_inputs.emplace_back(lut + "2", "~" + lut + "2");
|
||||
if (get_net_or_empty(cell.second.get(), id_I3)) lut_inputs.emplace_back(lut + "3", "~" + lut + "3");
|
||||
if (get_net_or_empty(cell.second.get(), id_I4)) lut_inputs.emplace_back(lut + "4", "~" + lut + "4");
|
||||
if (get_net_or_empty(cell.second.get(), id_I5)) lut_inputs.emplace_back(lut + "5", "~" + lut + "5");
|
||||
if (get_net_or_empty(cell.second.get(), id_I6)) lut_inputs.emplace_back(lut + "6", "~" + lut + "6");
|
||||
const auto& init = cell.second->params[ctx->id("INIT")];
|
||||
// Assume from Yosys that INIT masks of less than 32 bits are output as uint32_t
|
||||
if (lut_inputs.size() < 6) {
|
||||
auto init_as_uint = boost::lexical_cast<uint32_t>(init);
|
||||
NPNR_ASSERT(init_as_uint < (1ull << (1u << lut_inputs.size())));
|
||||
if (lut_inputs.empty())
|
||||
value += init;
|
||||
else
|
||||
for (unsigned o = 0; o < (1u << lut_inputs.size()); ++o) {
|
||||
if ((init_as_uint >> o) & 0x1) continue;
|
||||
if (o > 0) value += "+";
|
||||
value += "(";
|
||||
value += (o & 1) ? lut_inputs[0].first : lut_inputs[0].second;
|
||||
for (unsigned i = 1; i < lut_inputs.size(); ++i) {
|
||||
value += "*";
|
||||
value += o & (1 << i) ? lut_inputs[i].first : lut_inputs[i].second;
|
||||
}
|
||||
value += ")";
|
||||
}
|
||||
}
|
||||
// Otherwise as a bit string
|
||||
else {
|
||||
NPNR_ASSERT(init.size() == (1u << lut_inputs.size()));
|
||||
for (unsigned i = 0; i < (1u << lut_inputs.size()); ++i) {
|
||||
if (init[i] == '0') continue;
|
||||
if (i > 0) value += "+";
|
||||
value += "(";
|
||||
value += (i & 1) ? lut_inputs[0].first : lut_inputs[0].second;
|
||||
for (unsigned i = 1; i < lut_inputs.size(); ++i) {
|
||||
value += "*";
|
||||
value += i & (1 << i) ? lut_inputs[i].first : lut_inputs[i].second;
|
||||
}
|
||||
value += ")";
|
||||
}
|
||||
}
|
||||
|
||||
auto O = get_net_or_empty(cell.second.get(), id_O);
|
||||
if (O)
|
||||
instPtr->setConfig(setting, O->name.str(ctx), value);
|
||||
else
|
||||
instPtr->setConfig(setting, cell.second->name.str(ctx), value);
|
||||
|
||||
auto OQ = get_net_or_empty(cell.second.get(), id_OQ);
|
||||
if (OQ) {
|
||||
setting = lut;
|
||||
setting += "FF";
|
||||
instPtr->setConfig(setting, OQ->name.c_str(ctx), "#FF");
|
||||
}
|
||||
}
|
||||
else if (cell.second->type == id_IOB33S) {
|
||||
if (get_net_or_empty(cell.second.get(), id_I)) {
|
||||
|
Loading…
Reference in New Issue
Block a user