ice40: Packer and bitstream gen support for MAC16s
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
6c38df7295
commit
bff7d673ed
@ -90,12 +90,79 @@ std::string get_param_str_or_def(const CellInfo *cell, const IdString param, std
|
|||||||
|
|
||||||
char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); }
|
char get_hexdigit(int i) { return std::string("0123456789ABCDEF").at(i); }
|
||||||
|
|
||||||
|
static const BelConfigPOD &get_ec_config(const ChipInfoPOD *chip, BelId bel)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < chip->num_belcfgs; i++) {
|
||||||
|
if (chip->bel_config[i].bel_index == bel.index)
|
||||||
|
return chip->bel_config[i];
|
||||||
|
}
|
||||||
|
NPNR_ASSERT_FALSE("failed to find bel config");
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::vector<std::vector<std::vector<std::vector<int8_t>>>> chipconfig_t;
|
||||||
|
|
||||||
|
static void set_ec_cbit(chipconfig_t &config, const Context *ctx, const BelConfigPOD &cell_cbits, std::string name,
|
||||||
|
bool value)
|
||||||
|
{
|
||||||
|
const ChipInfoPOD *chip = ctx->chip_info;
|
||||||
|
|
||||||
|
for (int i = 0; i < cell_cbits.num_entries; i++) {
|
||||||
|
const auto &cbit = cell_cbits.entries[i];
|
||||||
|
if (cbit.entry_name.get() == name) {
|
||||||
|
const auto &ti = chip->bits_info->tiles_nonrouting[tile_at(ctx, cbit.x, cbit.y)];
|
||||||
|
set_config(ti, config.at(cbit.y).at(cbit.x), std::string("IpConfig.") + cbit.cbit_name.get(), value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NPNR_ASSERT_FALSE_STR("failed to config extra cell config bit " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configure_extra_cell(chipconfig_t &config, const Context *ctx, CellInfo *cell,
|
||||||
|
const std::vector<std::pair<std::string, int>> ¶ms, bool string_style)
|
||||||
|
{
|
||||||
|
const ChipInfoPOD *chip = ctx->chip_info;
|
||||||
|
const auto &bc = get_ec_config(chip, cell->bel);
|
||||||
|
for (auto p : params) {
|
||||||
|
std::vector<bool> value;
|
||||||
|
if (string_style) {
|
||||||
|
// Lattice's weird string style params, not sure if
|
||||||
|
// prefixes other than 0b should be supported, only 0b features in docs
|
||||||
|
std::string raw = get_param_str_or_def(cell, ctx->id(p.first), "0b0");
|
||||||
|
assert(raw.substr(0, 2) == "0b");
|
||||||
|
raw = raw.substr(2);
|
||||||
|
value.resize(raw.length());
|
||||||
|
for (int i = 0; i < (int)raw.length(); i++) {
|
||||||
|
if (raw[i] == '1') {
|
||||||
|
value[(raw.length() - 1) - i] = 1;
|
||||||
|
} else {
|
||||||
|
assert(raw[i] == '0');
|
||||||
|
value[(raw.length() - 1) - i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int ival = get_param_or_def(cell, ctx->id(p.first), 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < p.second; i++)
|
||||||
|
value.push_back((ival >> i) & 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
value.resize(p.second);
|
||||||
|
if (p.second == 1) {
|
||||||
|
set_ec_cbit(config, ctx, bc, p.first, value.at(0));
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < p.second; i++) {
|
||||||
|
set_ec_cbit(config, ctx, bc, p.first + "_" + std::to_string(i), value.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void write_asc(const Context *ctx, std::ostream &out)
|
void write_asc(const Context *ctx, std::ostream &out)
|
||||||
{
|
{
|
||||||
// [y][x][row][col]
|
// [y][x][row][col]
|
||||||
const ChipInfoPOD &ci = *ctx->chip_info;
|
const ChipInfoPOD &ci = *ctx->chip_info;
|
||||||
const BitstreamInfoPOD &bi = *ci.bits_info;
|
const BitstreamInfoPOD &bi = *ci.bits_info;
|
||||||
std::vector<std::vector<std::vector<std::vector<int8_t>>>> config;
|
chipconfig_t config;
|
||||||
config.resize(ci.height);
|
config.resize(ci.height);
|
||||||
for (int y = 0; y < ci.height; y++) {
|
for (int y = 0; y < ci.height; y++) {
|
||||||
config.at(y).resize(ci.width);
|
config.at(y).resize(ci.width);
|
||||||
@ -265,6 +332,27 @@ void write_asc(const Context *ctx, std::ostream &out)
|
|||||||
NPNR_ASSERT(false);
|
NPNR_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (cell.second->type == ctx->id("ICESTORM_DSP")) {
|
||||||
|
const std::vector<std::pair<std::string, int>> mac16_params = {{"C_REG", 1},
|
||||||
|
{"A_REG", 1},
|
||||||
|
{"B_REG", 1},
|
||||||
|
{"D_REG", 1},
|
||||||
|
{"TOP_8x8_MULT_REG", 1},
|
||||||
|
{"BOT_8x8_MULT_REG", 1},
|
||||||
|
{"PIPELINE_16x16_MULT_REG1", 1},
|
||||||
|
{"PIPELINE_16x16_MULT_REG2", 1},
|
||||||
|
{"TOPOUTPUT_SELECT", 2},
|
||||||
|
{"TOPADDSUB_LOWERINPUT", 2},
|
||||||
|
{"TOPADDSUB_UPPERINPUT", 1},
|
||||||
|
{"TOPADDSUB_CARRYSELECT", 2},
|
||||||
|
{"BOTOUTPUT_SELECT", 2},
|
||||||
|
{"BOTADDSUB_LOWERINPUT", 2},
|
||||||
|
{"BOTADDSUB_UPPERINPUT", 1},
|
||||||
|
{"BOTADDSUB_CARRYSELECT", 2},
|
||||||
|
{"MODE_8x8", 1},
|
||||||
|
{"A_SIGNED", 1},
|
||||||
|
{"B_SIGNED", 1}};
|
||||||
|
configure_extra_cell(config, ctx, cell.second.get(), mac16_params, false);
|
||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT(false);
|
NPNR_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
@ -350,8 +350,9 @@ bool is_enable_port(const BaseCtx *ctx, const PortRef &port)
|
|||||||
return port.port == ctx->id("E");
|
return port.port == ctx->id("E");
|
||||||
if (port.cell->type == ctx->id("ICESTORM_LC"))
|
if (port.cell->type == ctx->id("ICESTORM_LC"))
|
||||||
return port.port == ctx->id("CEN");
|
return port.port == ctx->id("CEN");
|
||||||
if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP"))
|
// FIXME
|
||||||
return port.port == ctx->id("CE");
|
// if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP"))
|
||||||
|
// return port.port == ctx->id("CE");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,6 +568,25 @@ static void pack_special(Context *ctx)
|
|||||||
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
|
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
|
||||||
}
|
}
|
||||||
new_cells.push_back(std::move(packed));
|
new_cells.push_back(std::move(packed));
|
||||||
|
} else if (is_sb_mac16(ctx, ci)) {
|
||||||
|
std::unique_ptr<CellInfo> packed =
|
||||||
|
create_ice_cell(ctx, ctx->id("ICESTORM_DSP"), ci->name.str(ctx) + "_DSP");
|
||||||
|
packed_cells.insert(ci->name);
|
||||||
|
for (auto attr : ci->attrs)
|
||||||
|
packed->attrs[attr.first] = attr.second;
|
||||||
|
for (auto param : ci->params)
|
||||||
|
packed->params[param.first] = param.second;
|
||||||
|
|
||||||
|
for (auto port : ci->ports) {
|
||||||
|
PortInfo &pi = port.second;
|
||||||
|
std::string newname = pi.name.str(ctx);
|
||||||
|
size_t bpos = newname.find('[');
|
||||||
|
if (bpos != std::string::npos) {
|
||||||
|
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2);
|
||||||
|
}
|
||||||
|
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
|
||||||
|
}
|
||||||
|
new_cells.push_back(std::move(packed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user