clangformat

This commit is contained in:
Miodrag Milanovic 2024-11-29 09:45:16 +01:00
parent 858ff546d8
commit 96b073c001
11 changed files with 1812 additions and 1550 deletions

View File

@ -44,7 +44,7 @@ struct BitstreamJsonBackend
std::ostream &out; std::ostream &out;
bool first_instance; bool first_instance;
BitstreamJsonBackend(Context *ctx, NgUltraImpl *uarch, std::ostream &out) : ctx(ctx), uarch(uarch), out(out){}; BitstreamJsonBackend(Context *ctx, NgUltraImpl *uarch, std::ostream &out) : ctx(ctx), uarch(uarch), out(out) {};
std::string get_string(std::string str) std::string get_string(std::string str)
{ {
@ -59,40 +59,39 @@ struct BitstreamJsonBackend
std::string update_name(std::string tile, std::string name) std::string update_name(std::string tile, std::string name)
{ {
if (boost::starts_with(tile,"FENCE[")) { if (boost::starts_with(tile, "FENCE[")) {
char last = tile[tile.size()-2]; char last = tile[tile.size() - 2];
switch(last) switch (last) {
{ case 'T':
case 'T': case 'B':
case 'B': case 'U':
case 'U': case 'L':
case 'L': std::string loc = tile.substr(tile.find("[") + 1, tile.find("x") - tile.find("["));
std::string loc = tile.substr(tile.find("[")+1, tile.find("x")-tile.find("[")); boost::replace_all(name, "1x", loc);
boost::replace_all(name, "1x", loc); return name;
return name;
} }
} }
if (boost::starts_with(tile,"TILE[") && boost::algorithm::contains(name,".FE")) { if (boost::starts_with(tile, "TILE[") && boost::algorithm::contains(name, ".FE")) {
std::string last = name.substr(name.rfind('.') + 1); std::string last = name.substr(name.rfind('.') + 1);
if (last[0]=='D') { if (last[0] == 'D') {
boost::replace_all(name, ".D", "."); boost::replace_all(name, ".D", ".");
boost::replace_all(name, ".FE", ".DFF"); boost::replace_all(name, ".FE", ".DFF");
return name; return name;
} }
if (last=="L" || last=="R") { if (last == "L" || last == "R") {
boost::replace_all(name, ".FE", ".DFF"); boost::replace_all(name, ".FE", ".DFF");
return name; return name;
} }
if (last=="CK") { if (last == "CK") {
boost::replace_all(name, ".FE", ".DFF"); boost::replace_all(name, ".FE", ".DFF");
return name; return name;
} }
if (last[0]=='L') { if (last[0] == 'L') {
boost::replace_all(name, ".L", "."); boost::replace_all(name, ".L", ".");
boost::replace_all(name, ".FE", ".LUT"); boost::replace_all(name, ".FE", ".LUT");
return name; return name;
} }
if (last[0]=='P') { if (last[0] == 'P') {
boost::replace_all(name, ".PI", ".I"); boost::replace_all(name, ".PI", ".I");
boost::replace_all(name, ".FE", ".LUT"); boost::replace_all(name, ".FE", ".LUT");
return name; return name;
@ -101,10 +100,13 @@ struct BitstreamJsonBackend
return name; return name;
} }
void add_net(std::set<std::string> &nets, std::string src_tile, std::string src_name, std::string dst_tile, std::string dst_name, IdString src_type, IdString dst_type) void add_net(std::set<std::string> &nets, std::string src_tile, std::string src_name, std::string dst_tile,
std::string dst_name, IdString src_type, IdString dst_type)
{ {
if (src_type.in(ctx->id("LUT_PERMUTATION_WIRE"), ctx->id("MUX_WIRE"), ctx->id("INTERCONNECT_INPUT"))) return; if (src_type.in(ctx->id("LUT_PERMUTATION_WIRE"), ctx->id("MUX_WIRE"), ctx->id("INTERCONNECT_INPUT")))
if (boost::starts_with(src_type.c_str(ctx),"CROSSBAR_") && boost::ends_with(src_type.c_str(ctx),"INPUT_WIRE")) return; return;
if (boost::starts_with(src_type.c_str(ctx), "CROSSBAR_") && boost::ends_with(src_type.c_str(ctx), "INPUT_WIRE"))
return;
if (dst_type == ctx->id("MUX_WIRE")) if (dst_type == ctx->id("MUX_WIRE"))
dst_name = dst_name.substr(0, dst_name.rfind('.')); dst_name = dst_name.substr(0, dst_name.rfind('.'));
src_name = update_name(src_tile, src_name); src_name = update_name(src_tile, src_name);
@ -125,8 +127,10 @@ struct BitstreamJsonBackend
bool first_net = true; bool first_net = true;
for (auto &net : ctx->nets) { for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get(); NetInfo *ni = net.second.get();
if (ni->wires.empty()) continue; if (ni->wires.empty())
out << (first_net ? "" : ",\n"); first_net = false; continue;
out << (first_net ? "" : ",\n");
first_net = false;
out << stringf("\t\t%s: [\n", get_string(cleanup_name(ni->name.c_str(ctx))).c_str()); out << stringf("\t\t%s: [\n", get_string(cleanup_name(ni->name.c_str(ctx))).c_str());
std::set<std::string> nets; std::set<std::string> nets;
for (auto &w : ni->wires) { for (auto &w : ni->wires) {
@ -139,7 +143,8 @@ struct BitstreamJsonBackend
IdString src_type = ctx->getWireType(swire); IdString src_type = ctx->getWireType(swire);
IdString src_orig = IdString(chip_tile_info(ctx->chip_info, pip.tile).wires[pd.src_wire].name); IdString src_orig = IdString(chip_tile_info(ctx->chip_info, pip.tile).wires[pd.src_wire].name);
IdString src_orig_type = IdString(chip_tile_info(ctx->chip_info, pip.tile).wires[pd.src_wire].wire_type); IdString src_orig_type =
IdString(chip_tile_info(ctx->chip_info, pip.tile).wires[pd.src_wire].wire_type);
WireId dwire = ctx->getPipDstWire(pip); WireId dwire = ctx->getPipDstWire(pip);
IdString dst = ctx->getWireName(dwire)[1]; IdString dst = ctx->getWireName(dwire)[1];
@ -148,25 +153,30 @@ struct BitstreamJsonBackend
std::string s_tile_name = uarch->tile_name(swire.tile); std::string s_tile_name = uarch->tile_name(swire.tile);
std::string tile_name = uarch->tile_name(pip.tile); std::string tile_name = uarch->tile_name(pip.tile);
if (src_orig!=src) if (src_orig != src)
add_net(nets, s_tile_name, src.c_str(ctx), tile_name, src_orig.c_str(ctx), src_type, src_orig_type); add_net(nets, s_tile_name, src.c_str(ctx), tile_name, src_orig.c_str(ctx), src_type,
if (!extra_data.name || (extra_data.type != PipExtra::PIP_EXTRA_BYPASS && extra_data.type != PipExtra::PIP_EXTRA_VIRTUAL && extra_data.type != PipExtra::PIP_EXTRA_MUX)) src_orig_type);
add_net(nets, tile_name, src_orig.c_str(ctx), tile_name, dst.c_str(ctx), src_orig_type, dst_type); if (!extra_data.name ||
} else if (ni->wires.size()==1) { (extra_data.type != PipExtra::PIP_EXTRA_BYPASS &&
extra_data.type != PipExtra::PIP_EXTRA_VIRTUAL && extra_data.type != PipExtra::PIP_EXTRA_MUX))
add_net(nets, tile_name, src_orig.c_str(ctx), tile_name, dst.c_str(ctx), src_orig_type,
dst_type);
} else if (ni->wires.size() == 1) {
IdString src = ctx->getWireName(w.first)[1]; IdString src = ctx->getWireName(w.first)[1];
IdString src_type = ctx->getWireType(w.first); IdString src_type = ctx->getWireType(w.first);
std::string s_tile_name = uarch->tile_name(w.first.tile); std::string s_tile_name = uarch->tile_name(w.first.tile);
for (auto &u : ni->users){ for (auto &u : ni->users) {
std::string tile_name = uarch->tile_name(u.cell->bel.tile); std::string tile_name = uarch->tile_name(u.cell->bel.tile);
IdString bel_name = ctx->getBelName(u.cell->bel)[1]; IdString bel_name = ctx->getBelName(u.cell->bel)[1];
add_net(nets, s_tile_name, src.c_str(ctx), tile_name, stringf("%s.%s", bel_name.c_str(ctx), u.port.c_str(ctx)), src_type, src_type); add_net(nets, s_tile_name, src.c_str(ctx), tile_name,
stringf("%s.%s", bel_name.c_str(ctx), u.port.c_str(ctx)), src_type, src_type);
} }
} }
} }
bool first = true; bool first = true;
for (auto &str : nets) { for (auto &str : nets) {
out << (first ? "" : ",\n"); out << (first ? "" : ",\n");
out << stringf("\t\t\t%s",get_string(str).c_str()); out << stringf("\t\t\t%s", get_string(str).c_str());
first = false; first = false;
} }
out << "\n\t\t]"; out << "\n\t\t]";
@ -206,7 +216,8 @@ struct BitstreamJsonBackend
} }
}; };
template <typename KeyType> std::string extract_bits_or_default(const dict<KeyType, Property> &ct, const KeyType &key, int bits, int def = 0) template <typename KeyType>
std::string extract_bits_or_default(const dict<KeyType, Property> &ct, const KeyType &key, int bits, int def = 0)
{ {
Property extr = get_or_default(ct, key, Property()).extract(0, bits); Property extr = get_or_default(ct, key, Property()).extract(0, bits);
std::string str = extr.str; std::string str = extr.str;
@ -218,27 +229,30 @@ struct BitstreamJsonBackend
void open_instance(CellInfo *cell, std::string rename = "") void open_instance(CellInfo *cell, std::string rename = "")
{ {
out << stringf("%s", first_instance ? "" : ",\n"); first_instance = false; out << stringf("%s", first_instance ? "" : ",\n");
out << stringf("\t\t%s: {\n", get_string(cleanup_name(rename.empty() ? cell->name.c_str(ctx) : rename.c_str())).c_str()); first_instance = false;
out << stringf("\t\t%s: {\n",
get_string(cleanup_name(rename.empty() ? cell->name.c_str(ctx) : rename.c_str())).c_str());
std::string tile_name = uarch->tile_name(cell->bel.tile); std::string tile_name = uarch->tile_name(cell->bel.tile);
IdString idx = ctx->getBelName(cell->bel)[1]; IdString idx = ctx->getBelName(cell->bel)[1];
std::string belname = idx.c_str(ctx); std::string belname = idx.c_str(ctx);
config.clear(); config.clear();
out << stringf("\t\t\t\"location\": %s,\n",get_string(tile_name + ":" + belname).c_str()); out << stringf("\t\t\t\"location\": %s,\n", get_string(tile_name + ":" + belname).c_str());
out << stringf("\t\t\t\"type\": %s",get_string(cell->type.c_str(ctx)).c_str()); out << stringf("\t\t\t\"type\": %s", get_string(cell->type.c_str(ctx)).c_str());
} }
void open_instance_fe(CellInfo *cell, std::string type, std::string replace, std::string postfix = "") void open_instance_fe(CellInfo *cell, std::string type, std::string replace, std::string postfix = "")
{ {
out << stringf("%s", first_instance ? "" : ",\n"); first_instance = false; out << stringf("%s", first_instance ? "" : ",\n");
first_instance = false;
out << stringf("\t\t%s: {\n", get_string(cleanup_name(cell->name.c_str(ctx)) + postfix).c_str()); out << stringf("\t\t%s: {\n", get_string(cleanup_name(cell->name.c_str(ctx)) + postfix).c_str());
std::string tile_name = uarch->tile_name(cell->bel.tile); std::string tile_name = uarch->tile_name(cell->bel.tile);
IdString idx = ctx->getBelName(cell->bel)[1]; IdString idx = ctx->getBelName(cell->bel)[1];
std::string belname = idx.c_str(ctx); std::string belname = idx.c_str(ctx);
boost::replace_all(belname, ".FE", replace); boost::replace_all(belname, ".FE", replace);
config.clear(); config.clear();
out << stringf("\t\t\t\"location\": %s,\n",get_string(tile_name + ":" + belname).c_str()); out << stringf("\t\t\t\"location\": %s,\n", get_string(tile_name + ":" + belname).c_str());
out << stringf("\t\t\t\"type\": %s",get_string(type).c_str()); out << stringf("\t\t\t\"type\": %s", get_string(type).c_str());
} }
inline void add_config(std::string name, int val) inline void add_config(std::string name, int val)
@ -256,20 +270,24 @@ struct BitstreamJsonBackend
config.push_back(stringf("\t\t\t\t%s:%s", get_string(name).c_str(), get_string(val).c_str())); config.push_back(stringf("\t\t\t\t%s:%s", get_string(name).c_str(), get_string(val).c_str()));
} }
void close_instance() { void close_instance()
{
bool first = true; bool first = true;
if (!config.empty()) out << ",\n\t\t\t\"config\": {\n"; if (!config.empty())
out << ",\n\t\t\t\"config\": {\n";
for (auto &str : config) { for (auto &str : config) {
out << (first ? "" : ",\n"); out << (first ? "" : ",\n");
out << str.c_str(); out << str.c_str();
first = false; first = false;
} }
if (!config.empty()) out << "\n\t\t\t}"; if (!config.empty())
out << "\n\t\t\t}";
out << "\n\t\t}"; out << "\n\t\t}";
config.clear(); config.clear();
} }
void write_iop(CellInfo *cell) { void write_iop(CellInfo *cell)
{
open_instance(cell, str_or_default(cell->params, id_iobname, "")); open_instance(cell, str_or_default(cell->params, id_iobname, ""));
add_config("location", str_or_default(cell->params, id_location, "")); add_config("location", str_or_default(cell->params, id_location, ""));
add_config("differential", str_or_n_value_lower(cell->params, id_differential, "false")); add_config("differential", str_or_n_value_lower(cell->params, id_differential, "false"));
@ -294,15 +312,16 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
std::string tile_name = uarch->tile_name(cell->bel.tile); std::string tile_name = uarch->tile_name(cell->bel.tile);
std::string bank = tile_name.substr(0, tile_name.rfind(':')); std::string bank = tile_name.substr(0, tile_name.rfind(':'));
if (uarch->bank_voltage.count(bank)==0) { if (uarch->bank_voltage.count(bank) == 0) {
if (bank=="IOB0" || bank=="IOB1" || bank=="IOB6" || bank=="IOB7") if (bank == "IOB0" || bank == "IOB1" || bank == "IOB6" || bank == "IOB7")
uarch->bank_voltage[bank] = "3.3V"; uarch->bank_voltage[bank] = "3.3V";
else else
uarch->bank_voltage[bank] = "1.8V"; uarch->bank_voltage[bank] = "1.8V";
} }
} }
void write_ddfr(CellInfo *cell) { void write_ddfr(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("dff_load", bool_or_default(cell->params, id_dff_load, false)); add_config("dff_load", bool_or_default(cell->params, id_dff_load, false));
add_config("dff_sync", bool_or_default(cell->params, id_dff_sync, false)); add_config("dff_sync", bool_or_default(cell->params, id_dff_sync, false));
@ -312,7 +331,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_dfr(CellInfo *cell) { void write_dfr(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("data_inv", bool_or_default(cell->params, id_data_inv, false)); add_config("data_inv", bool_or_default(cell->params, id_data_inv, false));
add_config("dff_edge", bool_or_default(cell->params, id_dff_edge, false)); add_config("dff_edge", bool_or_default(cell->params, id_dff_edge, false));
@ -325,7 +345,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_bfr(CellInfo *cell) { void write_bfr(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("mode", int_or_default(cell->params, id_mode, 2)); add_config("mode", int_or_default(cell->params, id_mode, 2));
add_config("iobname", str_or_default(cell->params, id_iobname, "")); add_config("iobname", str_or_default(cell->params, id_iobname, ""));
@ -335,14 +356,16 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_cy(CellInfo *cell) { void write_cy(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("add_carry", int_or_default(cell->params, id_add_carry, 0)); add_config("add_carry", int_or_default(cell->params, id_add_carry, 0));
add_config("shifter", bool_or_default(cell->params, id_shifter, false)); add_config("shifter", bool_or_default(cell->params, id_shifter, false));
close_instance(); close_instance();
} }
void write_fe(CellInfo *cell) { void write_fe(CellInfo *cell)
{
if (bool_or_default(cell->params, id_lut_used)) { if (bool_or_default(cell->params, id_lut_used)) {
open_instance_fe(cell, "LUT", ".LUT"); open_instance_fe(cell, "LUT", ".LUT");
add_config("lut_table", extract_bits_or_default(cell->params, id_lut_table, 16)); add_config("lut_table", extract_bits_or_default(cell->params, id_lut_table, 16));
@ -351,7 +374,7 @@ struct BitstreamJsonBackend
if (bool_or_default(cell->params, id_dff_used)) { if (bool_or_default(cell->params, id_dff_used)) {
std::string subtype = str_or_default(cell->params, id_type, "DFF"); std::string subtype = str_or_default(cell->params, id_type, "DFF");
open_instance_fe(cell, subtype, ".DFF", "_D"); open_instance_fe(cell, subtype, ".DFF", "_D");
if (subtype =="DFF") { if (subtype == "DFF") {
add_config("dff_ctxt", std::to_string(int_or_default(cell->params, id_dff_ctxt, 0))); add_config("dff_ctxt", std::to_string(int_or_default(cell->params, id_dff_ctxt, 0)));
add_config("dff_edge", bool_or_default(cell->params, id_dff_edge, false)); add_config("dff_edge", bool_or_default(cell->params, id_dff_edge, false));
add_config("dff_init", bool_or_default(cell->params, id_dff_init, false)); add_config("dff_init", bool_or_default(cell->params, id_dff_init, false));
@ -363,19 +386,22 @@ struct BitstreamJsonBackend
} }
} }
void write_xlut(CellInfo *cell) { void write_xlut(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("lut_table", extract_bits_or_default(cell->params, id_lut_table, 16)); add_config("lut_table", extract_bits_or_default(cell->params, id_lut_table, 16));
close_instance(); close_instance();
} }
void write_iom(CellInfo *cell) { void write_iom(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("pads_path", str_or_default(cell->params, id_pads_path, ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")); add_config("pads_path", str_or_default(cell->params, id_pads_path, ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"));
close_instance(); close_instance();
} }
void write_gck(CellInfo *cell) { void write_gck(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("inv_in", bool_or_default(cell->params, id_inv_in, false)); add_config("inv_in", bool_or_default(cell->params, id_inv_in, false));
add_config("inv_out", bool_or_default(cell->params, id_inv_out, false)); add_config("inv_out", bool_or_default(cell->params, id_inv_out, false));
@ -383,7 +409,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_wfb(CellInfo *cell) { void write_wfb(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("delay_on", bool_or_default(cell->params, id_delay_on, false)); add_config("delay_on", bool_or_default(cell->params, id_delay_on, false));
add_config("delay", int_or_default(cell->params, id_delay, 0)); add_config("delay", int_or_default(cell->params, id_delay, 0));
@ -391,7 +418,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_wfg(CellInfo *cell) { void write_wfg(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("mode", int_or_default(cell->params, id_mode, 0)); add_config("mode", int_or_default(cell->params, id_mode, 0));
add_config("delay_on", bool_or_default(cell->params, id_delay_on, false)); add_config("delay_on", bool_or_default(cell->params, id_delay_on, false));
@ -407,7 +435,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_pll(CellInfo *cell) { void write_pll(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("clk_outdiv1", extract_bits_or_default(cell->params, id_clk_outdiv1, 3)); add_config("clk_outdiv1", extract_bits_or_default(cell->params, id_clk_outdiv1, 3));
add_config("clk_outdiv2", extract_bits_or_default(cell->params, id_clk_outdiv2, 3)); add_config("clk_outdiv2", extract_bits_or_default(cell->params, id_clk_outdiv2, 3));
@ -437,15 +466,18 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_rfb(CellInfo *cell) { void write_rfb(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
std::string context = str_or_default(cell->params, id_mem_ctxt, ""); std::string context = str_or_default(cell->params, id_mem_ctxt, "");
if (!context.empty()) add_config("mem_ctxt", context); if (!context.empty())
add_config("mem_ctxt", context);
add_config("wck_edge", bool_or_default(cell->params, id_wck_edge, false)); add_config("wck_edge", bool_or_default(cell->params, id_wck_edge, false));
close_instance(); close_instance();
} }
void write_ram(CellInfo *cell) { void write_ram(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("mcka_edge", bool_or_default(cell->params, id_mcka_edge, false)); add_config("mcka_edge", bool_or_default(cell->params, id_mcka_edge, false));
add_config("mckb_edge", bool_or_default(cell->params, id_mckb_edge, false)); add_config("mckb_edge", bool_or_default(cell->params, id_mckb_edge, false));
@ -454,11 +486,13 @@ struct BitstreamJsonBackend
add_config("raw_config0", extract_bits_or_default(cell->params, id_raw_config0, 4)); add_config("raw_config0", extract_bits_or_default(cell->params, id_raw_config0, 4));
add_config("raw_config1", extract_bits_or_default(cell->params, id_raw_config1, 16)); add_config("raw_config1", extract_bits_or_default(cell->params, id_raw_config1, 16));
std::string context = str_or_default(cell->params, id_mem_ctxt, ""); std::string context = str_or_default(cell->params, id_mem_ctxt, "");
if (!context.empty()) add_config("mem_ctxt", context); if (!context.empty())
add_config("mem_ctxt", context);
close_instance(); close_instance();
} }
void write_dsp(CellInfo *cell) { void write_dsp(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("raw_config0", extract_bits_or_default(cell->params, id_raw_config0, 27)); add_config("raw_config0", extract_bits_or_default(cell->params, id_raw_config0, 27));
add_config("raw_config1", extract_bits_or_default(cell->params, id_raw_config1, 24)); add_config("raw_config1", extract_bits_or_default(cell->params, id_raw_config1, 24));
@ -467,7 +501,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_cdc(CellInfo *cell) { void write_cdc(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
if (cell->type.in(id_DDE, id_TDE, id_CDC, id_XCDC)) { if (cell->type.in(id_DDE, id_TDE, id_CDC, id_XCDC)) {
add_config("ck0_edge", bool_or_default(cell->params, id_ck0_edge, false)); add_config("ck0_edge", bool_or_default(cell->params, id_ck0_edge, false));
@ -495,7 +530,8 @@ struct BitstreamJsonBackend
close_instance(); close_instance();
} }
void write_fifo(CellInfo *cell) { void write_fifo(CellInfo *cell)
{
open_instance(cell); open_instance(cell);
add_config("rck_edge", bool_or_default(cell->params, id_rck_edge, false)); add_config("rck_edge", bool_or_default(cell->params, id_rck_edge, false));
add_config("wck_edge", bool_or_default(cell->params, id_wck_edge, false)); add_config("wck_edge", bool_or_default(cell->params, id_wck_edge, false));
@ -511,13 +547,15 @@ struct BitstreamJsonBackend
{ {
for (auto &net : ctx->nets) { for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get(); NetInfo *ni = net.second.get();
if (ni->wires.size()==0) continue; if (ni->wires.size() == 0)
continue;
std::vector<std::string> nets; std::vector<std::string> nets;
for (auto &w : ni->wires) { for (auto &w : ni->wires) {
if (w.second.pip != PipId()) { if (w.second.pip != PipId()) {
PipId pip = w.second.pip; PipId pip = w.second.pip;
const auto &extra_data = *uarch->pip_extra_data(w.second.pip); const auto &extra_data = *uarch->pip_extra_data(w.second.pip);
if (!extra_data.name || extra_data.type != PipExtra::PIP_EXTRA_INTERCONNECT) continue; if (!extra_data.name || extra_data.type != PipExtra::PIP_EXTRA_INTERCONNECT)
continue;
auto &pd = chip_pip_info(ctx->chip_info, pip); auto &pd = chip_pip_info(ctx->chip_info, pip);
IdString src = IdString(chip_tile_info(ctx->chip_info, pip.tile).wires[pd.src_wire].name); IdString src = IdString(chip_tile_info(ctx->chip_info, pip.tile).wires[pd.src_wire].name);
std::string tile_name = uarch->tile_name(pip.tile); std::string tile_name = uarch->tile_name(pip.tile);
@ -525,15 +563,17 @@ struct BitstreamJsonBackend
std::string type = "OTC"; std::string type = "OTC";
if (src_name.find("UI1x") != std::string::npos) if (src_name.find("UI1x") != std::string::npos)
type = "ITC"; type = "ITC";
if (boost::starts_with(src_name,"SO1.")) type = "OTS"; if (boost::starts_with(src_name, "SO1."))
if (boost::starts_with(src_name,"SI1.")) type = "ITS"; type = "OTS";
if (boost::starts_with(src_name, "SI1."))
type = "ITS";
src_name = update_name(tile_name, src_name); src_name = update_name(tile_name, src_name);
src_name = src_name.substr(0, src_name.size() - 2); src_name = src_name.substr(0, src_name.size() - 2);
std::string name = cleanup_name(std::string(ni->name.c_str(ctx))+ "_" + src_name.substr(4)); std::string name = cleanup_name(std::string(ni->name.c_str(ctx)) + "_" + src_name.substr(4));
out << stringf(",\n\t\t%s: {\n", get_string(name).c_str()); out << stringf(",\n\t\t%s: {\n", get_string(name).c_str());
out << stringf("\t\t\t\"location\": %s,\n",get_string(tile_name + ":" + src_name).c_str()); out << stringf("\t\t\t\"location\": %s,\n", get_string(tile_name + ":" + src_name).c_str());
out << stringf("\t\t\t\"type\": %s\n\t\t}",get_string(type).c_str()); out << stringf("\t\t\t\"type\": %s\n\t\t}", get_string(type).c_str());
} }
} }
} }
@ -545,46 +585,81 @@ struct BitstreamJsonBackend
first_instance = true; first_instance = true;
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
switch (cell.second->type.index) { switch (cell.second->type.index) {
case id_BEYOND_FE.index: write_fe(cell.second.get()); break; case id_BEYOND_FE.index:
case id_IOP.index: write_fe(cell.second.get());
case id_IP.index: break;
case id_OP.index: case id_IOP.index:
case id_IOTP.index: case id_IP.index:
case id_ITP.index: case id_OP.index:
case id_OTP.index: write_iop(cell.second.get()); break; case id_IOTP.index:
case id_CY.index: write_cy(cell.second.get()); break; case id_ITP.index:
case id_WFB.index: write_wfb(cell.second.get()); break; case id_OTP.index:
case id_WFG.index: write_wfg(cell.second.get()); break; write_iop(cell.second.get());
case id_GCK.index: write_gck(cell.second.get()); break; break;
case id_IOM.index: write_iom(cell.second.get()); break; case id_CY.index:
case id_BFR.index: write_bfr(cell.second.get()); break; write_cy(cell.second.get());
case id_DDFR.index: write_ddfr(cell.second.get()); break; break;
case id_DFR.index: write_dfr(cell.second.get()); break; case id_WFB.index:
case id_RAM.index: write_ram(cell.second.get()); break; write_wfb(cell.second.get());
case id_RF.index: break;
case id_RFSP.index: case id_WFG.index:
case id_XHRF.index: write_wfg(cell.second.get());
case id_XWRF.index: break;
case id_XPRF.index: write_rfb(cell.second.get()); break; case id_GCK.index:
case id_XLUT.index: write_xlut(cell.second.get()); break; write_gck(cell.second.get());
case id_FIFO.index: // mode 0 break;
case id_XHFIFO.index: // mode 1 case id_IOM.index:
case id_XWFIFO.index: write_fifo(cell.second.get()); break; // mode 2 write_iom(cell.second.get());
case id_DDE.index: // mode 0 break;
case id_TDE.index: // mode 1 case id_BFR.index:
case id_CDC.index: // mode 2 write_bfr(cell.second.get());
case id_BGC.index: // mode 3 break;
case id_GBC.index: // mode 4 case id_DDFR.index:
case id_XCDC.index: write_cdc(cell.second.get()); break; // mode 5 write_ddfr(cell.second.get());
case id_DSP.index: write_dsp(cell.second.get()); break; break;
case id_PLL.index: write_pll(cell.second.get()); break; case id_DFR.index:
//case id_CRX.index: write_dfr(cell.second.get());
//case id_CTX.index: break;
//case id_PMA.index: case id_RAM.index:
//case id_Service.index: write_ram(cell.second.get());
//case id_SOCIF.index: break;
default: case id_RF.index:
log_error("Unhandled cell %s of type %s\n", cell.second.get()->name.c_str(ctx), cell.second->type.c_str(ctx)); case id_RFSP.index:
case id_XHRF.index:
case id_XWRF.index:
case id_XPRF.index:
write_rfb(cell.second.get());
break;
case id_XLUT.index:
write_xlut(cell.second.get());
break;
case id_FIFO.index: // mode 0
case id_XHFIFO.index: // mode 1
case id_XWFIFO.index:
write_fifo(cell.second.get());
break; // mode 2
case id_DDE.index: // mode 0
case id_TDE.index: // mode 1
case id_CDC.index: // mode 2
case id_BGC.index: // mode 3
case id_GBC.index: // mode 4
case id_XCDC.index:
write_cdc(cell.second.get());
break; // mode 5
case id_DSP.index:
write_dsp(cell.second.get());
break;
case id_PLL.index:
write_pll(cell.second.get());
break;
// case id_CRX.index:
// case id_CTX.index:
// case id_PMA.index:
// case id_Service.index:
// case id_SOCIF.index:
default:
log_error("Unhandled cell %s of type %s\n", cell.second.get()->name.c_str(ctx),
cell.second->type.c_str(ctx));
} }
} }
write_interconnections(); write_interconnections();
@ -599,7 +674,7 @@ struct BitstreamJsonBackend
bool first = true; bool first = true;
for (auto &bank : uarch->bank_voltage) { for (auto &bank : uarch->bank_voltage) {
out << (first ? "" : ",\n"); out << (first ? "" : ",\n");
out << stringf("\t\t\t%s:%s",get_string(bank.first).c_str(),get_string(bank.second).c_str()); out << stringf("\t\t\t%s:%s", get_string(bank.first).c_str(), get_string(bank.second).c_str());
first = false; first = false;
} }
out << "\n\t\t}\n\t}\n"; out << "\n\t\t}\n\t}\n";

View File

@ -82,217 +82,219 @@ void NgUltraImpl::parse_csv(const std::string &filename)
boost::split(arguments, line, boost::is_any_of(",")); boost::split(arguments, line, boost::is_any_of(","));
if (arguments.empty()) if (arguments.empty())
continue; continue;
switch(line_type) { switch (line_type) {
case IO_PADS: case IO_PADS: {
{ if (arguments.size() == 1 && arguments[0][0] == '!') {
if (arguments.size()==1 && arguments[0][0]=='!') { line_type = IO_BANKS;
line_type = IO_BANKS; continue;
continue; }
} if (arguments.size() != 15)
if (arguments.size()!=15) log_error("number of parameters in line %d must be 15\n", lineno);
log_error("number of parameters in line %d must be 15\n", lineno);
std::string arg_iobname = arguments.at(0); std::string arg_iobname = arguments.at(0);
std::string arg_location = arguments.at(1); std::string arg_location = arguments.at(1);
std::string arg_standard = arguments.at(2); std::string arg_standard = arguments.at(2);
std::string arg_drive = arguments.at(3); std::string arg_drive = arguments.at(3);
std::string arg_slewRate = arguments.at(4); std::string arg_slewRate = arguments.at(4);
std::string arg_inputDelayLine = arguments.at(5); std::string arg_inputDelayLine = arguments.at(5);
std::string arg_outputDelayLine = arguments.at(6); std::string arg_outputDelayLine = arguments.at(6);
std::string arg_differential = arguments.at(7); std::string arg_differential = arguments.at(7);
std::string arg_weakTermination = arguments.at(8); std::string arg_weakTermination = arguments.at(8);
std::string arg_termination = arguments.at(9); std::string arg_termination = arguments.at(9);
std::string arg_terminationReference = arguments.at(10); std::string arg_terminationReference = arguments.at(10);
std::string arg_turbo = arguments.at(11); std::string arg_turbo = arguments.at(11);
std::string arg_inputSignalSlope = arguments.at(12); std::string arg_inputSignalSlope = arguments.at(12);
std::string arg_outputCapacity = arguments.at(13); std::string arg_outputCapacity = arguments.at(13);
std::string arg_registered = arguments.at(14); std::string arg_registered = arguments.at(14);
// TODO: Remove this block // TODO: Remove this block
const std::vector<std::string> weak_values_check = { "None", "PullDown", "PullUp", "Keeper" }; const std::vector<std::string> weak_values_check = {"None", "PullDown", "PullUp", "Keeper"};
auto it2 = std::find(std::begin(weak_values_check),std::end(weak_values_check), arguments.at(4)); auto it2 = std::find(std::begin(weak_values_check), std::end(weak_values_check), arguments.at(4));
if (it2 != std::end(weak_values_check)) { if (it2 != std::end(weak_values_check)) {
if (!old_format) { if (!old_format) {
log_warning("Old CSV format detected. Please update file.\n"); log_warning("Old CSV format detected. Please update file.\n");
old_format = true; old_format = true;
}
arg_weakTermination = arguments.at(4);
arg_slewRate = arguments.at(5);
arg_termination = arguments.at(6);
arg_inputDelayLine = arguments.at(7);
arg_outputDelayLine = arguments.at(8);
arg_differential = arguments.at(9);
}
// End of block
if (!(boost::starts_with(arg_location, "IOB") && boost::contains(arg_location,"_D")))
log_error("invalid location name '%s' must start with 'IOB' in line %d\n", arg_location.c_str(), lineno);
const std::vector<std::string> standard_values = { "LVDS", "LVCMOS", "SSTL", "HSTL" }; // , "POD"
auto it = std::find(std::begin(standard_values),std::end(standard_values), arg_standard);
if (it == std::end(standard_values))
log_error("unknown standard value '%s' in line %d\n", arg_standard.c_str(), lineno);
const std::vector<std::string> drive_values = { "2mA", "4mA", "8mA", "16mA", "CatI", "CatII", "Undefined" }; // "6mA", "12mA",
it = std::find(std::begin(drive_values),std::end(drive_values), arg_drive);
if (it == std::end(drive_values))
log_error("unknown drive value '%s' in line %d\n", arg_drive.c_str(), lineno);
const std::vector<std::string> slew_values = { "Slow", "Medium", "Fast" };
it = std::find(std::begin(slew_values),std::end(slew_values), arg_slewRate);
if (it == std::end(slew_values))
log_error("unknown weak termination value '%s' in line %d\n", arg_slewRate.c_str(), lineno);
if (!is_number(arg_inputDelayLine)) {
log_error("input delay must be number, value '%s' in line %d\n", arg_inputDelayLine.c_str(), lineno);
} else {
int delay = std::stoi(arg_inputDelayLine);
if (delay<0 || delay >63)
log_error("input delay value must be in range from 0 to 63 in line %d\n", lineno);
}
if (!is_number(arg_outputDelayLine)) {
log_error("output delay must be number, value '%s' in line %d\n", arg_outputDelayLine.c_str(), lineno);
} else {
int delay = std::stoi(arg_outputDelayLine);
if (delay<0 || delay >63)
log_error("output delay value must be in range from 0 to 63 in line %d\n", lineno);
}
if (!arg_differential.empty() && arg_differential != "True" && arg_differential != "False")
log_error("differential must be boolean, value '%s' in line %d\n", arg_differential.c_str(), lineno);
const std::vector<std::string> weak_values = { "None", "PullDown", "PullUp", "Keeper" };
it = std::find(std::begin(weak_values),std::end(weak_values), arg_weakTermination);
if (it == std::end(weak_values))
log_error("unknown weak termination value '%s' in line %d\n", arg_weakTermination.c_str(), lineno);
if (!arg_termination.empty()) {
if (!is_number(arg_termination)) {
log_error("termination must be string containing int, value '%s' in line %d\n", arg_termination.c_str(), lineno);
} else {
int termination = std::stoi(arg_termination);
if (termination<30 || termination >80)
log_error("termination value must be in range from 30 to 80 in line %d\n", lineno);
}
}
const std::vector<std::string> termref_values = { "Floating", "VT" };
it = std::find(std::begin(termref_values),std::end(termref_values), arg_terminationReference);
if (it == std::end(termref_values))
log_error("unknown termination reference value '%s' in line %d\n", arg_terminationReference.c_str(), lineno);
if (!arg_turbo.empty() && arg_turbo != "True" && arg_turbo != "False")
log_error("turbo must be boolean, value '%s' in line %d\n", arg_turbo.c_str(), lineno);
if (!arg_inputSignalSlope.empty() && !is_number(arg_inputSignalSlope))
log_error("signal slope must be number, value '%s' in line %d\n", arg_inputSignalSlope.c_str(), lineno);
if (!arg_outputCapacity.empty() && !is_number(arg_outputCapacity))
log_error("output capacity must be number, value '%s' in line %d\n", arg_outputCapacity.c_str(), lineno);
const std::vector<std::string> registered_values = { "Auto", "I", "IC", "O", "OC", "IO", "IOC" };
it = std::find(std::begin(registered_values),std::end(registered_values), arg_registered);
if (it == std::end(registered_values))
log_error("unknown registered value '%s' in line %d\n", arg_registered.c_str(), lineno);
if (arg_standard=="LVDS" && arg_drive!="Undefined")
log_error("for port in line %d when standard is 'LVDS' drive must be 'Undefined'\n", lineno);
if (arg_standard=="LVCMOS" && !boost::ends_with(arg_drive,"mA"))
log_error("for port in line %d when standard is 'LVCMOS' drive current must be in mA\n", lineno);
if ((arg_standard=="SSTL" || arg_standard=="HSTL") && !boost::starts_with(arg_drive,"Cat"))
log_error("for port in line %d when standard is 'SSTL' or 'HSTL' drive current must be in 'CatI' or 'CatII'\n", lineno);
if (arg_terminationReference=="Floating") {
if (!(arg_differential == "True" && arg_weakTermination == "None")) {
log_error("for floating termination, differential myst be 'True' and weakTermination must be 'None' in line %d\n", lineno);
}
}
std::vector<CellInfo *> dest = get_cells(arg_iobname);
for (auto c : dest) {
c->params[id_iobname] = arg_iobname;
c->params[id_location] = arg_location;
c->params[id_standard] = arg_standard;
c->params[id_drive] = arg_drive;
c->params[id_slewRate] = arg_slewRate;
c->params[id_inputDelayLine] = arg_inputDelayLine;
c->params[id_outputDelayLine] = arg_outputDelayLine;
c->params[id_inputDelayOn] = std::string((std::stoi(arg_inputDelayLine)!=0) ? "True" : "False");
c->params[id_outputDelayOn] = std::string((std::stoi(arg_outputDelayLine)!=0) ? "True" : "False");
c->params[id_differential] = arg_differential;
c->params[id_weakTermination] = arg_weakTermination;
if (!arg_termination.empty()) {
c->params[id_termination] = arg_termination;
c->params[id_terminationReference] = arg_terminationReference;
}
c->params[id_turbo] = arg_turbo;
c->params[id_inputSignalSlope] = arg_inputSignalSlope;
c->params[id_outputCapacity] = arg_outputCapacity;
c->params[id_registered] = arg_registered;
}
if (dest.size()==0)
log_warning("Pad with name '%s' not found in netlist.\n", arg_iobname.c_str());
std::string bank_name = arg_location.substr(0,arg_location.find_first_of('_'));
banks_used.emplace(bank_name);
} }
break; arg_weakTermination = arguments.at(4);
case IO_BANKS: arg_slewRate = arguments.at(5);
{ arg_termination = arguments.at(6);
if (arguments.size()==1 && arguments[0][0]=='!') { arg_inputDelayLine = arguments.at(7);
line_type = IO_GCKS; arg_outputDelayLine = arguments.at(8);
continue; arg_differential = arguments.at(9);
} }
if (arguments.size()!=3) // End of block
log_error("number of parameters in line %d must be 3\n", lineno);
if (!boost::starts_with(arguments.at(0), "IOB")) if (!(boost::starts_with(arg_location, "IOB") && boost::contains(arg_location, "_D")))
log_error("wrong bank name '%s' in line %d\n", arguments.at(0).c_str(), lineno); log_error("invalid location name '%s' must start with 'IOB' in line %d\n", arg_location.c_str(),
lineno);
const char* voltages[] = { "1.2V", "1.5V", "1.8V", "2.5V", "3.3V" }; const std::vector<std::string> standard_values = {"LVDS", "LVCMOS", "SSTL", "HSTL"}; // , "POD"
auto it = std::find(std::begin(voltages),std::end(voltages), arguments.at(1)); auto it = std::find(std::begin(standard_values), std::end(standard_values), arg_standard);
if (it == std::end(voltages)) if (it == std::end(standard_values))
log_error("unknown voltage level '%s' in line %d\n", arguments.at(1).c_str(), lineno); log_error("unknown standard value '%s' in line %d\n", arg_standard.c_str(), lineno);
const char * direct_io_voltages[] = { "1.8V", "2.5V", "3.3V" }; const std::vector<std::string> drive_values = {"2mA", "4mA", "8mA", "16mA",
const char * complex_io_voltages[] = { "1.2V", "1.5V", "1.8V" }; "CatI", "CatII", "Undefined"}; // "6mA", "12mA",
it = std::find(std::begin(drive_values), std::end(drive_values), arg_drive);
if (it == std::end(drive_values))
log_error("unknown drive value '%s' in line %d\n", arg_drive.c_str(), lineno);
int bank = std::stoi(arguments.at(0).substr(3)); const std::vector<std::string> slew_values = {"Slow", "Medium", "Fast"};
switch(bank) { it = std::find(std::begin(slew_values), std::end(slew_values), arg_slewRate);
// direct if (it == std::end(slew_values))
case 0: log_error("unknown weak termination value '%s' in line %d\n", arg_slewRate.c_str(), lineno);
case 1:
case 6: if (!is_number(arg_inputDelayLine)) {
case 7: log_error("input delay must be number, value '%s' in line %d\n", arg_inputDelayLine.c_str(), lineno);
{ } else {
auto it = std::find(std::begin(direct_io_voltages),std::end(direct_io_voltages), arguments.at(1)); int delay = std::stoi(arg_inputDelayLine);
if (it == std::end(direct_io_voltages)) if (delay < 0 || delay > 63)
log_error("unsupported voltage level '%s' for bank '%s'\n", arguments.at(1).c_str(), arguments.at(0).c_str()); log_error("input delay value must be in range from 0 to 63 in line %d\n", lineno);
} }
break; if (!is_number(arg_outputDelayLine)) {
// complex log_error("output delay must be number, value '%s' in line %d\n", arg_outputDelayLine.c_str(), lineno);
default: } else {
auto it = std::find(std::begin(complex_io_voltages),std::end(complex_io_voltages), arguments.at(1)); int delay = std::stoi(arg_outputDelayLine);
if (it == std::end(complex_io_voltages)) if (delay < 0 || delay > 63)
log_error("unsupported voltage level '%s' for bank '%s'\n", arguments.at(1).c_str(), arguments.at(0).c_str()); log_error("output delay value must be in range from 0 to 63 in line %d\n", lineno);
} }
bank_voltage[arguments.at(0)] = arguments.at(1);
if (!arg_differential.empty() && arg_differential != "True" && arg_differential != "False")
log_error("differential must be boolean, value '%s' in line %d\n", arg_differential.c_str(), lineno);
const std::vector<std::string> weak_values = {"None", "PullDown", "PullUp", "Keeper"};
it = std::find(std::begin(weak_values), std::end(weak_values), arg_weakTermination);
if (it == std::end(weak_values))
log_error("unknown weak termination value '%s' in line %d\n", arg_weakTermination.c_str(), lineno);
if (!arg_termination.empty()) {
if (!is_number(arg_termination)) {
log_error("termination must be string containing int, value '%s' in line %d\n",
arg_termination.c_str(), lineno);
} else {
int termination = std::stoi(arg_termination);
if (termination < 30 || termination > 80)
log_error("termination value must be in range from 30 to 80 in line %d\n", lineno);
} }
break; }
case IO_GCKS:
{ const std::vector<std::string> termref_values = {"Floating", "VT"};
if (arguments.size()==1 && arguments[0][0]=='!') { it = std::find(std::begin(termref_values), std::end(termref_values), arg_terminationReference);
line_type = IO_ERROR; if (it == std::end(termref_values))
continue; log_error("unknown termination reference value '%s' in line %d\n", arg_terminationReference.c_str(),
} lineno);
if (arguments.size()!=2)
log_error("number of parameters in line %d must be 2\n", lineno); if (!arg_turbo.empty() && arg_turbo != "True" && arg_turbo != "False")
log_error("turbo must be boolean, value '%s' in line %d\n", arg_turbo.c_str(), lineno);
if (!arg_inputSignalSlope.empty() && !is_number(arg_inputSignalSlope))
log_error("signal slope must be number, value '%s' in line %d\n", arg_inputSignalSlope.c_str(), lineno);
if (!arg_outputCapacity.empty() && !is_number(arg_outputCapacity))
log_error("output capacity must be number, value '%s' in line %d\n", arg_outputCapacity.c_str(),
lineno);
const std::vector<std::string> registered_values = {"Auto", "I", "IC", "O", "OC", "IO", "IOC"};
it = std::find(std::begin(registered_values), std::end(registered_values), arg_registered);
if (it == std::end(registered_values))
log_error("unknown registered value '%s' in line %d\n", arg_registered.c_str(), lineno);
if (arg_standard == "LVDS" && arg_drive != "Undefined")
log_error("for port in line %d when standard is 'LVDS' drive must be 'Undefined'\n", lineno);
if (arg_standard == "LVCMOS" && !boost::ends_with(arg_drive, "mA"))
log_error("for port in line %d when standard is 'LVCMOS' drive current must be in mA\n", lineno);
if ((arg_standard == "SSTL" || arg_standard == "HSTL") && !boost::starts_with(arg_drive, "Cat"))
log_error("for port in line %d when standard is 'SSTL' or 'HSTL' drive current must be in 'CatI' or "
"'CatII'\n",
lineno);
if (arg_terminationReference == "Floating") {
if (!(arg_differential == "True" && arg_weakTermination == "None")) {
log_error("for floating termination, differential myst be 'True' and weakTermination must be "
"'None' in line %d\n",
lineno);
} }
break; }
std::vector<CellInfo *> dest = get_cells(arg_iobname);
for (auto c : dest) {
c->params[id_iobname] = arg_iobname;
c->params[id_location] = arg_location;
c->params[id_standard] = arg_standard;
c->params[id_drive] = arg_drive;
c->params[id_slewRate] = arg_slewRate;
c->params[id_inputDelayLine] = arg_inputDelayLine;
c->params[id_outputDelayLine] = arg_outputDelayLine;
c->params[id_inputDelayOn] = std::string((std::stoi(arg_inputDelayLine) != 0) ? "True" : "False");
c->params[id_outputDelayOn] = std::string((std::stoi(arg_outputDelayLine) != 0) ? "True" : "False");
c->params[id_differential] = arg_differential;
c->params[id_weakTermination] = arg_weakTermination;
if (!arg_termination.empty()) {
c->params[id_termination] = arg_termination;
c->params[id_terminationReference] = arg_terminationReference;
}
c->params[id_turbo] = arg_turbo;
c->params[id_inputSignalSlope] = arg_inputSignalSlope;
c->params[id_outputCapacity] = arg_outputCapacity;
c->params[id_registered] = arg_registered;
}
if (dest.size() == 0)
log_warning("Pad with name '%s' not found in netlist.\n", arg_iobname.c_str());
std::string bank_name = arg_location.substr(0, arg_location.find_first_of('_'));
banks_used.emplace(bank_name);
} break;
case IO_BANKS: {
if (arguments.size() == 1 && arguments[0][0] == '!') {
line_type = IO_GCKS;
continue;
}
if (arguments.size() != 3)
log_error("number of parameters in line %d must be 3\n", lineno);
if (!boost::starts_with(arguments.at(0), "IOB"))
log_error("wrong bank name '%s' in line %d\n", arguments.at(0).c_str(), lineno);
const char *voltages[] = {"1.2V", "1.5V", "1.8V", "2.5V", "3.3V"};
auto it = std::find(std::begin(voltages), std::end(voltages), arguments.at(1));
if (it == std::end(voltages))
log_error("unknown voltage level '%s' in line %d\n", arguments.at(1).c_str(), lineno);
const char *direct_io_voltages[] = {"1.8V", "2.5V", "3.3V"};
const char *complex_io_voltages[] = {"1.2V", "1.5V", "1.8V"};
int bank = std::stoi(arguments.at(0).substr(3));
switch (bank) {
// direct
case 0:
case 1:
case 6:
case 7: {
auto it = std::find(std::begin(direct_io_voltages), std::end(direct_io_voltages), arguments.at(1));
if (it == std::end(direct_io_voltages))
log_error("unsupported voltage level '%s' for bank '%s'\n", arguments.at(1).c_str(),
arguments.at(0).c_str());
} break;
// complex
default: default:
log_error("switching to unknown block of data in line %d\n", lineno); auto it = std::find(std::begin(complex_io_voltages), std::end(complex_io_voltages), arguments.at(1));
if (it == std::end(complex_io_voltages))
log_error("unsupported voltage level '%s' for bank '%s'\n", arguments.at(1).c_str(),
arguments.at(0).c_str());
}
bank_voltage[arguments.at(0)] = arguments.at(1);
} break;
case IO_GCKS: {
if (arguments.size() == 1 && arguments[0][0] == '!') {
line_type = IO_ERROR;
continue;
}
if (arguments.size() != 2)
log_error("number of parameters in line %d must be 2\n", lineno);
} break;
default:
log_error("switching to unknown block of data in line %d\n", lineno);
} }
} }
for(auto& bank_name : banks_used) { for (auto &bank_name : banks_used) {
if (bank_voltage.count(bank_name) == 0) { if (bank_voltage.count(bank_name) == 0) {
log_error("IO for bank '%s' defined, but no bank configuration.\n", bank_name.c_str()); log_error("IO for bank '%s' defined, but no bank configuration.\n", bank_name.c_str());
} }

View File

@ -40,8 +40,15 @@ NPNR_PACKED_STRUCT(struct NGUltraPipExtraDataPOD {
NPNR_PACKED_STRUCT(struct NGUltraBelExtraDataPOD { int32_t flags; }); NPNR_PACKED_STRUCT(struct NGUltraBelExtraDataPOD { int32_t flags; });
struct GckConfig { struct GckConfig
explicit GckConfig(BelId belid) { bel = belid; si1 = IdString(); si2 = IdString(); used = false; } {
explicit GckConfig(BelId belid)
{
bel = belid;
si1 = IdString();
si2 = IdString();
used = false;
}
BelId bel; BelId bel;
IdString si1; IdString si1;
IdString si2; IdString si2;
@ -50,16 +57,16 @@ struct GckConfig {
enum TILETypeZ enum TILETypeZ
{ {
BEL_LUT_Z = 0, BEL_LUT_Z = 0,
BEL_LUT_MAX_Z = 31, BEL_LUT_MAX_Z = 31,
BEL_CY_Z = 32, BEL_CY_Z = 32,
BEL_XLUT_Z = BEL_CY_Z + 4, BEL_XLUT_Z = BEL_CY_Z + 4,
BEL_RF_Z = BEL_XLUT_Z + 8, BEL_RF_Z = BEL_XLUT_Z + 8,
BEL_XRF_Z = BEL_RF_Z + 2, BEL_XRF_Z = BEL_RF_Z + 2,
BEL_FIFO_Z = BEL_XRF_Z + 1, BEL_FIFO_Z = BEL_XRF_Z + 1,
BEL_XFIFO_Z = BEL_FIFO_Z + 2, BEL_XFIFO_Z = BEL_FIFO_Z + 2,
BEL_CDC_Z = BEL_XFIFO_Z + 1, BEL_CDC_Z = BEL_XFIFO_Z + 1,
BEL_XCDC_Z = BEL_CDC_Z + 2 BEL_XCDC_Z = BEL_CDC_Z + 2
}; };
enum ClusterPlacement enum ClusterPlacement

View File

@ -24,440 +24,433 @@ NEXTPNR_NAMESPACE_BEGIN
namespace { namespace {
const Loc ng_ultra_place_cy_map[24] = { const Loc ng_ultra_place_cy_map[24] = {
{ 0, 1, 0 }, // S1 0 -> S2 0 CY24->CY1 {0, 1, 0}, // S1 0 -> S2 0 CY24->CY1
{ 0, 0, -1 }, // S1 1 -> S1 0 CY23->CY24 {0, 0, -1}, // S1 1 -> S1 0 CY23->CY24
{ 0, 0, -1 }, // S1 2 -> S1 1 CY22->CY23 {0, 0, -1}, // S1 2 -> S1 1 CY22->CY23
{ 0, 0, -1 }, // S1 3 -> S1 2 CY21->CY22 {0, 0, -1}, // S1 3 -> S1 2 CY21->CY22
{-1, 0,+3}, // S5 0 -> S1 1 CY20->CY21 {-1, 0, +3}, // S5 0 -> S1 1 CY20->CY21
{0, 0, -1}, // S5 1 -> S5 0 CY19->CY20 {0, 0, -1}, // S5 1 -> S5 0 CY19->CY20
{0, 0, -1}, // S5 2 -> S5 1 CY18->CY19 {0, 0, -1}, // S5 2 -> S5 1 CY18->CY19
{0, 0, -1}, // S5 3 -> S5 2 CY17->CY18 {0, 0, -1}, // S5 3 -> S5 2 CY17->CY18
{-1, 0,+3}, // S9 0 -> S5 1 CY16->CY17 {-1, 0, +3}, // S9 0 -> S5 1 CY16->CY17
{0, 0, -1}, // S9 1 -> S9 0 CY15->CY16 {0, 0, -1}, // S9 1 -> S9 0 CY15->CY16
{0, 0, -1}, // S9 2 -> S9 1 CY14->CY15 {0, 0, -1}, // S9 2 -> S9 1 CY14->CY15
{0, 0, -1}, // S9 3 -> S9 2 CY13->CY14 {0, 0, -1}, // S9 3 -> S9 2 CY13->CY14
{0, 0, +1}, // S2 0 -> S2 1 CY1->CY2 {0, 0, +1}, // S2 0 -> S2 1 CY1->CY2
{0, 0, +1}, // S2 1 -> S2 2 CY2->CY3 {0, 0, +1}, // S2 1 -> S2 2 CY2->CY3
{0, 0, +1}, // S2 2 -> S2 3 CY3->CY4 {0, 0, +1}, // S2 2 -> S2 3 CY3->CY4
{1, 0, -3}, // S2 3 -> S6 0 CY4->CY5 {1, 0, -3}, // S2 3 -> S6 0 CY4->CY5
{0, 0, +1}, // S6 0 -> S6 1 CY5->CY6 {0, 0, +1}, // S6 0 -> S6 1 CY5->CY6
{0, 0, +1}, // S6 1 -> S6 2 CY6->CY7 {0, 0, +1}, // S6 1 -> S6 2 CY6->CY7
{0, 0, +1}, // S6 2 -> S6 3 CY7->CY8 {0, 0, +1}, // S6 2 -> S6 3 CY7->CY8
{1, 0, -3}, // S6 3 -> S10 0 CY8->CY9 {1, 0, -3}, // S6 3 -> S10 0 CY8->CY9
{0, 0, +1}, // S10 0 -> S10 1 CY9->CY10 {0, 0, +1}, // S10 0 -> S10 1 CY9->CY10
{0, 0, +1}, // S10 1 -> S10 2 CY10->CY11 {0, 0, +1}, // S10 1 -> S10 2 CY10->CY11
{0, 0, +1}, // S10 2 -> S10 3 CY11->CY12 {0, 0, +1}, // S10 2 -> S10 3 CY11->CY12
{0,-1, 0}, // S10 3 -> S9 3 CY12->CY13 {0, -1, 0}, // S10 3 -> S9 3 CY12->CY13
}; };
const Loc ng_ultra_place_xrf[] = const Loc ng_ultra_place_xrf[] = {
{ {-1, 0, 1}, // I/O1
{-1, 0, 1},// I/O1 {-1, 0, 2}, // I/O2
{-1, 0, 2},// I/O2 {-1, 0, 5}, // I/O3
{-1, 0, 5},// I/O3 {-1, 0, 6}, // I/O4
{-1, 0, 6},// I/O4 {-1, 0, 7}, // I/O5
{-1, 0, 7},// I/O5 {-1, 0, 9}, // I/O6
{-1, 0, 9},// I/O6 {-1, 0, 10}, // I/O7
{-1, 0, 10},// I/O7 {-1, 0, 13}, // I/O8
{-1, 0, 13},// I/O8 {-1, 0, 14}, // I/O9
{-1, 0, 14},// I/O9 {-1, 0, 15}, // I/O10
{-1, 0, 15},// I/O10 {-1, 0, 16}, // I/O11
{-1, 0, 16},// I/O11 {-1, 0, 17}, // I/O12
{-1, 0, 17},// I/O12 {-1, 0, 18}, // I/O13
{-1, 0, 18},// I/O13 {-1, 0, 21}, // I/O14
{-1, 0, 21},// I/O14 {-1, 0, 24}, // I/O15
{-1, 0, 24},// I/O15 {-1, 0, 25}, // I/O16
{-1, 0, 25},// I/O16 {-1, 0, 26}, // I/O17
{-1, 0, 26},// I/O17 {-1, 0, 29}, // I/O18
{-1, 0, 29},// I/O18
{+1, 0, 1},// I/O19 {+1, 0, 1}, // I/O19
{+1, 0, 2},// I/O20 {+1, 0, 2}, // I/O20
{+1, 0, 5},// I/O21 {+1, 0, 5}, // I/O21
{+1, 0, 6},// I/O22 {+1, 0, 6}, // I/O22
{+1, 0, 7},// I/O23 {+1, 0, 7}, // I/O23
{+1, 0, 9},// I/O24 {+1, 0, 9}, // I/O24
{+1, 0, 10},// I/O25 {+1, 0, 10}, // I/O25
{+1, 0, 13},// I/O26 {+1, 0, 13}, // I/O26
{+1, 0, 14},// I/O27 {+1, 0, 14}, // I/O27
{+1, 0, 15},// I/O28 {+1, 0, 15}, // I/O28
{+1, 0, 16},// I/O29 {+1, 0, 16}, // I/O29
{+1, 0, 17},// I/O30 {+1, 0, 17}, // I/O30
{+1, 0, 18},// I/O31 {+1, 0, 18}, // I/O31
{+1, 0, 21},// I/O32 {+1, 0, 21}, // I/O32
{+1, 0, 24},// I/O33 {+1, 0, 24}, // I/O33
{+1, 0, 25},// I/O34 {+1, 0, 25}, // I/O34
{+1, 0, 26},// I/O35 {+1, 0, 26}, // I/O35
{+1, 0, 29},// I/O36 {+1, 0, 29}, // I/O36
{-1, 0, 4},// RA1 {-1, 0, 4}, // RA1
{-1, 0, 12},// RA2 {-1, 0, 12}, // RA2
{-1, 0, 20},// RA3 {-1, 0, 20}, // RA3
{-1, 0, 27},// RA4 {-1, 0, 27}, // RA4
{-1, 0, 31},// RA5 {-1, 0, 31}, // RA5
{+1, 0, 4},// RA6 {+1, 0, 4}, // RA6
{+1, 0, 12},// RA7 {+1, 0, 12}, // RA7
{+1, 0, 20},// RA8 {+1, 0, 20}, // RA8
{+1, 0, 27},// RA9 {+1, 0, 27}, // RA9
{+1, 0, 31},// RA10 {+1, 0, 31}, // RA10
{-1, 0, 3},// WA1 {-1, 0, 3}, // WA1
{-1, 0, 11},// WA2 {-1, 0, 11}, // WA2
{-1, 0, 19},// WA3 {-1, 0, 19}, // WA3
{-1, 0, 23},// WA4 {-1, 0, 23}, // WA4
{-1, 0, 28},// WA5 {-1, 0, 28}, // WA5
{+1, 0, 3},// WA6 {+1, 0, 3}, // WA6
{-1, 0, 0},// WE {-1, 0, 0}, // WE
{-1, 0, 8},// WEA {-1, 0, 8}, // WEA
}; };
const Loc ng_ultra_place_cdc1[] = const Loc ng_ultra_place_cdc1[] = {
{ {+1, 0, 1}, // AI1
{+1, 0, 1}, // AI1 {+1, 0, 2}, // AI2
{+1, 0, 2}, // AI2 {+1, 0, 9}, // AI3
{+1, 0, 9}, // AI3 {+1, 0, 17}, // AI4
{+1, 0, 17},// AI4 {+1, 0, 18}, // AI5
{+1, 0, 18},// AI5 {+1, 0, 25}, // AI6
{+1, 0, 25},// AI6
{+1, 0, 3}, // BI1 {+1, 0, 3}, // BI1
{+1, 0, 10},// BI2 {+1, 0, 10}, // BI2
{+1, 0, 11},// BI3 {+1, 0, 11}, // BI3
{+1, 0, 19},// BI4 {+1, 0, 19}, // BI4
{+1, 0, 26},// BI5 {+1, 0, 26}, // BI5
{+1, 0, 27},// BI6 {+1, 0, 27}, // BI6
{ 0, 0, 22},// ASRSTI {0, 0, 22}, // ASRSTI
{ 0, 0, 30},// ADRSTI {0, 0, 30}, // ADRSTI
{+1, 0, 24},// BSRSTI {+1, 0, 24}, // BSRSTI
{+1, 0, 8}, // BDRSTI {+1, 0, 8}, // BDRSTI
}; };
const Loc ng_ultra_place_cdc2[] = const Loc ng_ultra_place_cdc2[] = {
{ {-1, 0, 4}, // AI1
{-1, 0, 4}, // AI1 {-1, 0, 5}, // AI2
{-1, 0, 5}, // AI2 {-1, 0, 12}, // AI3
{-1, 0, 12},// AI3 {-1, 0, 20}, // AI4
{-1, 0, 20},// AI4 {-1, 0, 21}, // AI5
{-1, 0, 21},// AI5 {-1, 0, 28}, // AI6
{-1, 0, 28},// AI6
{-1, 0, 6}, // BI1 {-1, 0, 6}, // BI1
{-1, 0, 13},// BI2 {-1, 0, 13}, // BI2
{-1, 0, 14},// BI3 {-1, 0, 14}, // BI3
{-1, 0, 22},// BI4 {-1, 0, 22}, // BI4
{-1, 0, 29},// BI5 {-1, 0, 29}, // BI5
{-1, 0, 30},// BI6 {-1, 0, 30}, // BI6
{ 0, 0, 22},// ASRSTI {0, 0, 22}, // ASRSTI
{ 0, 0, 30},// ADRSTI {0, 0, 30}, // ADRSTI
{-1, 0, 23},// BSRSTI {-1, 0, 23}, // BSRSTI
{-1, 0, 7}, // BDRSTI {-1, 0, 7}, // BDRSTI
}; };
const Loc ng_ultra_place_xcdc[] = const Loc ng_ultra_place_xcdc[] = {
{ {0, 0, 1}, // AI1
{ 0, 0, 1}, // AI1 {0, 0, 2}, // AI2
{ 0, 0, 2}, // AI2 {0, 0, 9}, // AI3
{ 0, 0, 9}, // AI3 {0, 0, 17}, // AI4
{ 0, 0, 17},// AI4 {0, 0, 18}, // AI5
{ 0, 0, 18},// AI5 {0, 0, 25}, // AI6
{ 0, 0, 25},// AI6
{ 0, 0, 4}, // BI1 {0, 0, 4}, // BI1
{ 0, 0, 5}, // BI2 {0, 0, 5}, // BI2
{ 0, 0, 12},// BI3 {0, 0, 12}, // BI3
{ 0, 0, 20},// BI4 {0, 0, 20}, // BI4
{ 0, 0, 21},// BI5 {0, 0, 21}, // BI5
{ 0, 0, 28},// BI6 {0, 0, 28}, // BI6
{-1, 0, 22},// ASRSTI {-1, 0, 22}, // ASRSTI
{-1, 0, 30},// ADRSTI {-1, 0, 30}, // ADRSTI
{+1, 0, 22},// BSRSTI {+1, 0, 22}, // BSRSTI
{+1, 0, 30},// BDRSTI {+1, 0, 30}, // BDRSTI
{ 0, 0, 3}, // CI1 {0, 0, 3}, // CI1
{ 0, 0, 10},// CI2 {0, 0, 10}, // CI2
{ 0, 0, 11},// CI3 {0, 0, 11}, // CI3
{ 0, 0, 19},// CI4 {0, 0, 19}, // CI4
{ 0, 0, 26},// CI5 {0, 0, 26}, // CI5
{ 0, 0, 27},// CI6 {0, 0, 27}, // CI6
{ 0, 0, 6}, // DI1 {0, 0, 6}, // DI1
{ 0, 0, 13},// DI2 {0, 0, 13}, // DI2
{ 0, 0, 14},// DI3 {0, 0, 14}, // DI3
{ 0, 0, 22},// DI4 {0, 0, 22}, // DI4
{ 0, 0, 29},// DI5 {0, 0, 29}, // DI5
{ 0, 0, 30},// DI6 {0, 0, 30}, // DI6
{ 0, 0, 24},// CSRSTI {0, 0, 24}, // CSRSTI
{ 0, 0, 8}, // CDRSTI {0, 0, 8}, // CDRSTI
{ 0, 0, 23},// DSRSTI {0, 0, 23}, // DSRSTI
{ 0, 0, 7}, // DDRSTI {0, 0, 7}, // DDRSTI
}; };
const Loc ng_ultra_place_fifo1[] = const Loc ng_ultra_place_fifo1[] = {
{ {-1, 0, 1}, // I/O1
{-1, 0, 1}, // I/O1 {-1, 0, 2}, // I/O2
{-1, 0, 2}, // I/O2 {-1, 0, 5}, // I/O3
{-1, 0, 5}, // I/O3 {-1, 0, 6}, // I/O4
{-1, 0, 6}, // I/O4 {-1, 0, 7}, // I/O5
{-1, 0, 7}, // I/O5 {-1, 0, 9}, // I/O6
{-1, 0, 9}, // I/O6 {-1, 0, 10}, // I/O7
{-1, 0, 10},// I/O7 {-1, 0, 13}, // I/O8
{-1, 0, 13},// I/O8 {-1, 0, 14}, // I/O9
{-1, 0, 14},// I/O9 {-1, 0, 15}, // I/O10
{-1, 0, 15},// I/O10 {-1, 0, 16}, // I/O11
{-1, 0, 16},// I/O11 {-1, 0, 17}, // I/O12
{-1, 0, 17},// I/O12 {-1, 0, 18}, // I/O13
{-1, 0, 18},// I/O13 {-1, 0, 21}, // I/O14
{-1, 0, 21},// I/O14 {-1, 0, 24}, // I/O15
{-1, 0, 24},// I/O15 {-1, 0, 25}, // I/O16
{-1, 0, 25},// I/O16 {-1, 0, 26}, // I/O17
{-1, 0, 26},// I/O17 {-1, 0, 29}, // I/O18
{-1, 0, 29},// I/O18
{ 0, 0, 0},// I/O19 {0, 0, 0}, // I/O19
{ 0, 0, 0},// I/O20 {0, 0, 0}, // I/O20
{ 0, 0, 0},// I/O21 {0, 0, 0}, // I/O21
{ 0, 0, 0},// I/O22 {0, 0, 0}, // I/O22
{ 0, 0, 0},// I/O23 {0, 0, 0}, // I/O23
{ 0, 0, 0},// I/O24 {0, 0, 0}, // I/O24
{ 0, 0, 0},// I/O25 {0, 0, 0}, // I/O25
{ 0, 0, 0},// I/O26 {0, 0, 0}, // I/O26
{ 0, 0, 0},// I/O27 {0, 0, 0}, // I/O27
{ 0, 0, 0},// I/O28 {0, 0, 0}, // I/O28
{ 0, 0, 0},// I/O29 {0, 0, 0}, // I/O29
{ 0, 0, 0},// I/O30 {0, 0, 0}, // I/O30
{ 0, 0, 0},// I/O31 {0, 0, 0}, // I/O31
{ 0, 0, 0},// I/O32 {0, 0, 0}, // I/O32
{ 0, 0, 0},// I/O33 {0, 0, 0}, // I/O33
{ 0, 0, 0},// I/O34 {0, 0, 0}, // I/O34
{ 0, 0, 0},// I/O35 {0, 0, 0}, // I/O35
{ 0, 0, 0},// I/O36 {0, 0, 0}, // I/O36
{ 0, 0, 3}, // RAI1/RAO1 {0, 0, 3}, // RAI1/RAO1
{ 0, 0, 10},// RAI2/RAO2 {0, 0, 10}, // RAI2/RAO2
{ 0, 0, 11},// RAI3/RAO3 {0, 0, 11}, // RAI3/RAO3
{ 0, 0, 19},// RAI4/RAO4 {0, 0, 19}, // RAI4/RAO4
{ 0, 0, 26},// RAI5/RAO5 {0, 0, 26}, // RAI5/RAO5
{ 0, 0, 27},// RAI6/RAO6 {0, 0, 27}, // RAI6/RAO6
{ 0, 0, 0},// RAI7/RAO7 {0, 0, 0}, // RAI7/RAO7
{ 0, 0, 1}, // WAI1/WAO1 {0, 0, 1}, // WAI1/WAO1
{ 0, 0, 2}, // WAI2/WAO2 {0, 0, 2}, // WAI2/WAO2
{ 0, 0, 9}, // WAI3/WAO3 {0, 0, 9}, // WAI3/WAO3
{ 0, 0, 17},// WAI4/WAO4 {0, 0, 17}, // WAI4/WAO4
{ 0, 0, 18},// WAI5/WAO5 {0, 0, 18}, // WAI5/WAO5
{ 0, 0, 25},// WAI6/WAO6 {0, 0, 25}, // WAI6/WAO6
{ 0, 0, 0},// WAI7/WAO7 {0, 0, 0}, // WAI7/WAO7
{-1, 0, 0}, // WE {-1, 0, 0}, // WE
{-1, 0, 8}, // WEA {-1, 0, 8}, // WEA
{-1, 0, 22},// WRSTI1/WRSTO {-1, 0, 22}, // WRSTI1/WRSTO
{-1, 0, 30},// RRSTI1/RRSTO {-1, 0, 30}, // RRSTI1/RRSTO
{ 0, 0, 8}, // WRSTI2 {0, 0, 8}, // WRSTI2
{ 0, 0, 24},// RRSTI2 {0, 0, 24}, // RRSTI2
{ 0, 0, 0}, // WRSTI3/WRSTO {0, 0, 0}, // WRSTI3/WRSTO
{ 0, 0, 0}, // RRSTI3/RRSTO {0, 0, 0}, // RRSTI3/RRSTO
{ 0, 0, 0}, // WRSTI4 {0, 0, 0}, // WRSTI4
{ 0, 0, 0}, // RRSTI4 {0, 0, 0}, // RRSTI4
{-1, 0, 3}, // WEQ {-1, 0, 3}, // WEQ
{-1, 0, 4}, // REQ {-1, 0, 4}, // REQ
// {-1, 0, 11}, WEQ // {-1, 0, 11}, WEQ
// {-1, 0, 12}, REQ // {-1, 0, 12}, REQ
// {-1, 0, 19}, WEQ // {-1, 0, 19}, WEQ
// {-1, 0, 20}, REQ // {-1, 0, 20}, REQ
// {-1, 0, 27}, WEQ // {-1, 0, 27}, WEQ
// {-1, 0, 28}, REQ // {-1, 0, 28}, REQ
{ 0, 0, 0}, // WEQ2 {0, 0, 0}, // WEQ2
{ 0, 0, 0}, // REQ2 {0, 0, 0}, // REQ2
}; };
const Loc ng_ultra_place_fifo2[] = const Loc ng_ultra_place_fifo2[] = {
{ {+1, 0, 1}, // I/O1
{+1, 0, 1}, // I/O1 {+1, 0, 2}, // I/O2
{+1, 0, 2}, // I/O2 {+1, 0, 5}, // I/O3
{+1, 0, 5}, // I/O3 {+1, 0, 6}, // I/O4
{+1, 0, 6}, // I/O4 {+1, 0, 7}, // I/O5
{+1, 0, 7}, // I/O5 {+1, 0, 9}, // I/O6
{+1, 0, 9}, // I/O6 {+1, 0, 10}, // I/O7
{+1, 0, 10},// I/O7 {+1, 0, 13}, // I/O8
{+1, 0, 13},// I/O8 {+1, 0, 14}, // I/O9
{+1, 0, 14},// I/O9 {+1, 0, 15}, // I/O10
{+1, 0, 15},// I/O10 {+1, 0, 16}, // I/O11
{+1, 0, 16},// I/O11 {+1, 0, 17}, // I/O12
{+1, 0, 17},// I/O12 {+1, 0, 18}, // I/O13
{+1, 0, 18},// I/O13 {+1, 0, 21}, // I/O14
{+1, 0, 21},// I/O14 {+1, 0, 24}, // I/O15
{+1, 0, 24},// I/O15 {+1, 0, 25}, // I/O16
{+1, 0, 25},// I/O16 {+1, 0, 26}, // I/O17
{+1, 0, 26},// I/O17 {+1, 0, 29}, // I/O18
{+1, 0, 29},// I/O18
{ 0, 0, 0},// I/O19 {0, 0, 0}, // I/O19
{ 0, 0, 0},// I/O20 {0, 0, 0}, // I/O20
{ 0, 0, 0},// I/O21 {0, 0, 0}, // I/O21
{ 0, 0, 0},// I/O22 {0, 0, 0}, // I/O22
{ 0, 0, 0},// I/O23 {0, 0, 0}, // I/O23
{ 0, 0, 0},// I/O24 {0, 0, 0}, // I/O24
{ 0, 0, 0},// I/O25 {0, 0, 0}, // I/O25
{ 0, 0, 0},// I/O26 {0, 0, 0}, // I/O26
{ 0, 0, 0},// I/O27 {0, 0, 0}, // I/O27
{ 0, 0, 0},// I/O28 {0, 0, 0}, // I/O28
{ 0, 0, 0},// I/O29 {0, 0, 0}, // I/O29
{ 0, 0, 0},// I/O30 {0, 0, 0}, // I/O30
{ 0, 0, 0},// I/O31 {0, 0, 0}, // I/O31
{ 0, 0, 0},// I/O32 {0, 0, 0}, // I/O32
{ 0, 0, 0},// I/O33 {0, 0, 0}, // I/O33
{ 0, 0, 0},// I/O34 {0, 0, 0}, // I/O34
{ 0, 0, 0},// I/O35 {0, 0, 0}, // I/O35
{ 0, 0, 0},// I/O36 {0, 0, 0}, // I/O36
{ 0, 0, 6}, // RAI1/RAO1 {0, 0, 6}, // RAI1/RAO1
{ 0, 0, 13},// RAI2/RAO2 {0, 0, 13}, // RAI2/RAO2
{ 0, 0, 14},// RAI3/RAO3 {0, 0, 14}, // RAI3/RAO3
{ 0, 0, 22},// RAI4/RAO4 {0, 0, 22}, // RAI4/RAO4
{ 0, 0, 29},// RAI5/RAO5 {0, 0, 29}, // RAI5/RAO5
{ 0, 0, 30},// RAI6/RAO6 {0, 0, 30}, // RAI6/RAO6
{ 0, 0, 0},// RAI7/RAO7 {0, 0, 0}, // RAI7/RAO7
{ 0, 0, 4}, // WAI1/WAO1 {0, 0, 4}, // WAI1/WAO1
{ 0, 0, 5}, // WAI2/WAO2 {0, 0, 5}, // WAI2/WAO2
{ 0, 0, 12},// WAI3/WAO3 {0, 0, 12}, // WAI3/WAO3
{ 0, 0, 20},// WAI4/WAO4 {0, 0, 20}, // WAI4/WAO4
{ 0, 0, 21},// WAI5/WAO5 {0, 0, 21}, // WAI5/WAO5
{ 0, 0, 28},// WAI6/WAO6 {0, 0, 28}, // WAI6/WAO6
{ 0, 0, 0},// WAI7/WAO7 {0, 0, 0}, // WAI7/WAO7
{+1, 0, 0}, // WE {+1, 0, 0}, // WE
{+1, 0, 8}, // WEA {+1, 0, 8}, // WEA
{+1, 0, 22},// WRSTI1/WRSTO {+1, 0, 22}, // WRSTI1/WRSTO
{+1, 0, 30},// RRSTI1/RRSTO {+1, 0, 30}, // RRSTI1/RRSTO
{ 0, 0, 7}, // WRSTI2 {0, 0, 7}, // WRSTI2
{ 0, 0, 23},// RRSTI2 {0, 0, 23}, // RRSTI2
{ 0, 0, 0}, // WRSTI3/WRSTO {0, 0, 0}, // WRSTI3/WRSTO
{ 0, 0, 0}, // RRSTI3/RRSTO {0, 0, 0}, // RRSTI3/RRSTO
{ 0, 0, 0}, // WRSTI4 {0, 0, 0}, // WRSTI4
{ 0, 0, 0}, // RRSTI4 {0, 0, 0}, // RRSTI4
{+1, 0, 3}, // WEQ {+1, 0, 3}, // WEQ
{+1, 0, 4}, // REQ {+1, 0, 4}, // REQ
// {+1, 0, 11}, WEQ // {+1, 0, 11}, WEQ
// {+1, 0, 12}, REQ // {+1, 0, 12}, REQ
// {+1, 0, 19}, WEQ // {+1, 0, 19}, WEQ
// {+1, 0, 20}, REQ // {+1, 0, 20}, REQ
// {+1, 0, 27}, WEQ // {+1, 0, 27}, WEQ
// {+1, 0, 28}, REQ // {+1, 0, 28}, REQ
{ 0, 0, 0}, // WEQ2 {0, 0, 0}, // WEQ2
{ 0, 0, 0}, // REQ2 {0, 0, 0}, // REQ2
}; };
const Loc ng_ultra_place_xfifo[] = const Loc ng_ultra_place_xfifo[] = {
{ {-1, 0, 1}, // I/O1
{-1, 0, 1}, // I/O1 {-1, 0, 2}, // I/O2
{-1, 0, 2}, // I/O2 {-1, 0, 5}, // I/O3
{-1, 0, 5}, // I/O3 {-1, 0, 6}, // I/O4
{-1, 0, 6}, // I/O4 {-1, 0, 7}, // I/O5
{-1, 0, 7}, // I/O5 {-1, 0, 9}, // I/O6
{-1, 0, 9}, // I/O6 {-1, 0, 10}, // I/O7
{-1, 0, 10},// I/O7 {-1, 0, 13}, // I/O8
{-1, 0, 13},// I/O8 {-1, 0, 14}, // I/O9
{-1, 0, 14},// I/O9 {-1, 0, 15}, // I/O10
{-1, 0, 15},// I/O10 {-1, 0, 16}, // I/O11
{-1, 0, 16},// I/O11 {-1, 0, 17}, // I/O12
{-1, 0, 17},// I/O12 {-1, 0, 18}, // I/O13
{-1, 0, 18},// I/O13 {-1, 0, 21}, // I/O14
{-1, 0, 21},// I/O14 {-1, 0, 24}, // I/O15
{-1, 0, 24},// I/O15 {-1, 0, 25}, // I/O16
{-1, 0, 25},// I/O16 {-1, 0, 26}, // I/O17
{-1, 0, 26},// I/O17 {-1, 0, 29}, // I/O18
{-1, 0, 29},// I/O18 {+1, 0, 1}, // I/O19
{+1, 0, 1}, // I/O19 {+1, 0, 2}, // I/O20
{+1, 0, 2}, // I/O20 {+1, 0, 5}, // I/O21
{+1, 0, 5}, // I/O21 {+1, 0, 6}, // I/O22
{+1, 0, 6}, // I/O22 {+1, 0, 7}, // I/O23
{+1, 0, 7}, // I/O23 {+1, 0, 9}, // I/O24
{+1, 0, 9}, // I/O24 {+1, 0, 10}, // I/O25
{+1, 0, 10},// I/O25 {+1, 0, 13}, // I/O26
{+1, 0, 13},// I/O26 {+1, 0, 14}, // I/O27
{+1, 0, 14},// I/O27 {+1, 0, 15}, // I/O28
{+1, 0, 15},// I/O28 {+1, 0, 16}, // I/O29
{+1, 0, 16},// I/O29 {+1, 0, 17}, // I/O30
{+1, 0, 17},// I/O30 {+1, 0, 18}, // I/O31
{+1, 0, 18},// I/O31 {+1, 0, 21}, // I/O32
{+1, 0, 21},// I/O32 {+1, 0, 24}, // I/O33
{+1, 0, 24},// I/O33 {+1, 0, 25}, // I/O34
{+1, 0, 25},// I/O34 {+1, 0, 26}, // I/O35
{+1, 0, 26},// I/O35 {+1, 0, 29}, // I/O36
{+1, 0, 29},// I/O36
{ 0, 0, 3}, // RAI1/RAO1 {0, 0, 3}, // RAI1/RAO1
{ 0, 0, 10},// RAI2/RAO2 {0, 0, 10}, // RAI2/RAO2
{ 0, 0, 11},// RAI3/RAO3 {0, 0, 11}, // RAI3/RAO3
{ 0, 0, 19},// RAI4/RAO4 {0, 0, 19}, // RAI4/RAO4
{ 0, 0, 26},// RAI5/RAO5 {0, 0, 26}, // RAI5/RAO5
{ 0, 0, 27},// RAI6/RAO6 {0, 0, 27}, // RAI6/RAO6
{ 0, 0, 6}, // RAI7/RAO7 {0, 0, 6}, // RAI7/RAO7
{ 0, 0, 1}, // WAI1/WAO1 {0, 0, 1}, // WAI1/WAO1
{ 0, 0, 2}, // WAI2/WAO2 {0, 0, 2}, // WAI2/WAO2
{ 0, 0, 9}, // WAI3/WAO3 {0, 0, 9}, // WAI3/WAO3
{ 0, 0, 17},// WAI4/WAO4 {0, 0, 17}, // WAI4/WAO4
{ 0, 0, 18},// WAI5/WAO5 {0, 0, 18}, // WAI5/WAO5
{ 0, 0, 25},// WAI6/WAO6 {0, 0, 25}, // WAI6/WAO6
{ 0, 0, 4}, // WAI7/WAO7 {0, 0, 4}, // WAI7/WAO7
{-1, 0, 0}, // WE {-1, 0, 0}, // WE
{-1, 0, 8}, // WEA {-1, 0, 8}, // WEA
{-1, 0, 22},// WRSTI1/WRSTO {-1, 0, 22}, // WRSTI1/WRSTO
{-1, 0, 30},// RRSTI1/RRSTO {-1, 0, 30}, // RRSTI1/RRSTO
{ 0, 0, 8}, // WRSTI2 {0, 0, 8}, // WRSTI2
{ 0, 0, 24},// RRSTI2 {0, 0, 24}, // RRSTI2
{+1, 0, 22},// WRSTI3/WRSTO {+1, 0, 22}, // WRSTI3/WRSTO
{+1, 0, 30},// RRSTI3/RRSTO {+1, 0, 30}, // RRSTI3/RRSTO
{ 0, 0, 7}, // WRSTI4 {0, 0, 7}, // WRSTI4
{ 0, 0, 23},// RRSTI4 {0, 0, 23}, // RRSTI4
{-1, 0, 3}, // WEQ1 {-1, 0, 3}, // WEQ1
{-1, 0, 4}, // REQ1 {-1, 0, 4}, // REQ1
// {-1, 0, 11}, WEQ1 // {-1, 0, 11}, WEQ1
// {-1, 0, 12}, REQ1 // {-1, 0, 12}, REQ1
// {-1, 0, 19}, WEQ1 // {-1, 0, 19}, WEQ1
// {-1, 0, 20}, REQ1 // {-1, 0, 20}, REQ1
// {-1, 0, 27}, WEQ1 // {-1, 0, 27}, WEQ1
// {-1, 0, 28}, REQ1 // {-1, 0, 28}, REQ1
{+1, 0, 3}, // WEQ2 {+1, 0, 3}, // WEQ2
{+1, 0, 4}, // REQ2 {+1, 0, 4}, // REQ2
// {+1, 0, 11}, WEQ2 // {+1, 0, 11}, WEQ2
// {+1, 0, 12}, REQ2 // {+1, 0, 12}, REQ2
// {+1, 0, 19}, WEQ2 // {+1, 0, 19}, WEQ2
// {+1, 0, 20}, REQ2 // {+1, 0, 20}, REQ2
// {+1, 0, 27}, WEQ2 // {+1, 0, 27}, WEQ2
// {+1, 0, 28}, REQ2 // {+1, 0, 28}, REQ2
}; };
}; }; // namespace
namespace ng_ultra { namespace ng_ultra {
Loc getNextLocInDSPChain(const NgUltraImpl *impl, Loc loc) Loc getNextLocInDSPChain(const NgUltraImpl *impl, Loc loc)
{ {
BelId bel = impl->ctx->getBelByLocation(loc); BelId bel = impl->ctx->getBelByLocation(loc);
if (impl->dsp_cascade.count(bel)==0) { if (impl->dsp_cascade.count(bel) == 0) {
loc.z = -1; // End of chain loc.z = -1; // End of chain
return loc; return loc;
} }
@ -497,14 +490,15 @@ Loc getNextLocInDFFChain(Loc loc)
return result; return result;
} }
int z = loc.z + 8; int z = loc.z + 8;
if (z>31) z++; if (z > 31)
z++;
result.z = z % 32; // BEL_LUT_Z is 0 result.z = z % 32; // BEL_LUT_Z is 0
return result; return result;
} }
Loc getCYFE(Loc root, int pos) Loc getCYFE(Loc root, int pos)
{ {
int p[] = { 2-1, 25-1, 10-1, 17-1 }; int p[] = {2 - 1, 25 - 1, 10 - 1, 17 - 1};
int cy = root.z - BEL_CY_Z; int cy = root.z - BEL_CY_Z;
Loc result; Loc result;
result.x = root.x; result.x = root.x;
@ -528,7 +522,7 @@ Loc getXRFFE(Loc root, int pos)
if (root.z == BEL_XRF_Z) { if (root.z == BEL_XRF_Z) {
// XRF1 // XRF1
result.x += root.x; result.x += root.x;
} else { } else {
// RF1 or RF2 // RF1 or RF2
result.x = root.x + ((root.z == BEL_RF_Z) ? -1 : +1); result.x = root.x + ((root.z == BEL_RF_Z) ? -1 : +1);
} }
@ -541,7 +535,7 @@ Loc getCDCFE(Loc root, int pos)
Loc result; Loc result;
if (root.z == BEL_CDC_Z) { if (root.z == BEL_CDC_Z) {
result = ng_ultra_place_cdc1[pos]; result = ng_ultra_place_cdc1[pos];
} else if (root.z == BEL_CDC_Z+1) { } else if (root.z == BEL_CDC_Z + 1) {
result = ng_ultra_place_cdc2[pos]; result = ng_ultra_place_cdc2[pos];
} else if (root.z == BEL_XCDC_Z) { } else if (root.z == BEL_XCDC_Z) {
result = ng_ultra_place_xcdc[pos]; result = ng_ultra_place_xcdc[pos];
@ -558,7 +552,7 @@ Loc getFIFOFE(Loc root, int pos)
Loc result; Loc result;
if (root.z == BEL_FIFO_Z) { if (root.z == BEL_FIFO_Z) {
result = ng_ultra_place_fifo1[pos]; result = ng_ultra_place_fifo1[pos];
} else if (root.z == BEL_FIFO_Z+1) { } else if (root.z == BEL_FIFO_Z + 1) {
result = ng_ultra_place_fifo2[pos]; result = ng_ultra_place_fifo2[pos];
} else if (root.z == BEL_XFIFO_Z) { } else if (root.z == BEL_XFIFO_Z) {
result = ng_ultra_place_xfifo[pos]; result = ng_ultra_place_xfifo[pos];
@ -570,5 +564,5 @@ Loc getFIFOFE(Loc root, int pos)
return result; return result;
} }
}; }; // namespace ng_ultra
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -37,7 +37,7 @@ Loc getXRFFE(Loc root, int pos);
Loc getCDCFE(Loc root, int pos); Loc getCDCFE(Loc root, int pos);
Loc getFIFOFE(Loc root, int pos); Loc getFIFOFE(Loc root, int pos);
}; }; // namespace ng_ultra
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -59,25 +59,26 @@ struct NgUltraImpl : HimbaechelAPI
bool getClusterPlacement(ClusterId cluster, BelId root_bel, bool getClusterPlacement(ClusterId cluster, BelId root_bel,
std::vector<std::pair<CellInfo *, BelId>> &placement) const override; std::vector<std::pair<CellInfo *, BelId>> &placement) const override;
bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc, bool getChildPlacement(const BaseClusterInfo *cluster, Loc root_loc,
std::vector<std::pair<CellInfo *, BelId>> &placement) const; std::vector<std::pair<CellInfo *, BelId>> &placement) const;
BoundingBox getRouteBoundingBox(WireId src, WireId dst) const override; BoundingBox getRouteBoundingBox(WireId src, WireId dst) const override;
delay_t estimateDelay(WireId src, WireId dst) const override; delay_t estimateDelay(WireId src, WireId dst) const override;
delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override; delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const override;
bool checkPipAvail(PipId pip) const override { return blocked_pips.count(pip)==0; } bool checkPipAvail(PipId pip) const override { return blocked_pips.count(pip) == 0; }
bool checkPipAvailForNet(PipId pip, const NetInfo *net) const override { return checkPipAvail(pip); }; bool checkPipAvailForNet(PipId pip, const NetInfo *net) const override { return checkPipAvail(pip); };
void expandBoundingBox(BoundingBox &bb) const override; void expandBoundingBox(BoundingBox &bb) const override;
void drawBel(std::vector<GraphicElement> &g, GraphicElement::style_t style, IdString bel_type, Loc loc) override; void drawBel(std::vector<GraphicElement> &g, GraphicElement::style_t style, IdString bel_type, Loc loc) override;
public:
public:
int tile_lobe(int tile) const; int tile_lobe(int tile) const;
TileTypeExtra tile_type(int tile) const; TileTypeExtra tile_type(int tile) const;
IdString tile_name_id(int tile) const; IdString tile_name_id(int tile) const;
std::string tile_name(int tile) const; std::string tile_name(int tile) const;
const dict<IdString,pool<IdString>>& get_fabric_lowskew_sinks(); const dict<IdString, pool<IdString>> &get_fabric_lowskew_sinks();
bool is_fabric_lowskew_sink(const PortRef &ref); bool is_fabric_lowskew_sink(const PortRef &ref);
bool is_ring_clock_sink(const PortRef &ref); bool is_ring_clock_sink(const PortRef &ref);
bool is_ring_over_tile_clock_sink(const PortRef &ref); bool is_ring_over_tile_clock_sink(const PortRef &ref);
@ -89,15 +90,15 @@ public:
const NGUltraPipExtraDataPOD *pip_extra_data(PipId pip) const; const NGUltraPipExtraDataPOD *pip_extra_data(PipId pip) const;
const NGUltraBelExtraDataPOD *bel_extra_data(BelId bel) const; const NGUltraBelExtraDataPOD *bel_extra_data(BelId bel) const;
dict<IdString,BelId> iom_bels; dict<IdString, BelId> iom_bels;
dict<std::string, std::string> bank_voltage; dict<std::string, std::string> bank_voltage;
dict<BelId,IdString> global_capable_bels; dict<BelId, IdString> global_capable_bels;
dict<std::string,BelId> locations; dict<std::string, BelId> locations;
dict<std::string,Loc> tile_locations; dict<std::string, Loc> tile_locations;
dict<int,std::vector<GckConfig>> gck_per_lobe; dict<int, std::vector<GckConfig>> gck_per_lobe;
pool<PipId> blocked_pips; pool<PipId> blocked_pips;
dict<IdString, std::pair<IdString,IdString>> bank_to_ckg; dict<IdString, std::pair<IdString, IdString>> bank_to_ckg;
dict<BelId, IdString> unused_wfg; dict<BelId, IdString> unused_wfg;
dict<BelId, IdString> unused_pll; dict<BelId, IdString> unused_pll;
dict<BelId, BelId> dsp_cascade; dict<BelId, BelId> dsp_cascade;

File diff suppressed because it is too large Load Diff

View File

@ -83,9 +83,11 @@ TESTABLE_PRIVATE:
void ddfr_rewrite(CellInfo *cell); void ddfr_rewrite(CellInfo *cell);
void exchange_if_constant(CellInfo *cell, IdString input1, IdString input2); void exchange_if_constant(CellInfo *cell, IdString input1, IdString input2);
void pack_cy_input_and_output(CellInfo *cy, IdString cluster, IdString in_port, IdString out_port, int placer, int &lut_only, int &lut_and_ff, int &dff_only); void pack_cy_input_and_output(CellInfo *cy, IdString cluster, IdString in_port, IdString out_port, int placer,
int &lut_only, int &lut_and_ff, int &dff_only);
void pack_xrf_input_and_output(CellInfo *cy, IdString cluster, IdString in_port, IdString out_port, ClusterPlacement placement, int &lut_only, int &lut_and_ff, int &dff_only); void pack_xrf_input_and_output(CellInfo *cy, IdString cluster, IdString in_port, IdString out_port,
ClusterPlacement placement, int &lut_only, int &lut_and_ff, int &dff_only);
void connect_gnd_if_unconnected(CellInfo *cell, IdString input, bool warn); void connect_gnd_if_unconnected(CellInfo *cell, IdString input, bool warn);
void disconnect_if_gnd(CellInfo *cell, IdString input); void disconnect_if_gnd(CellInfo *cell, IdString input);
@ -107,10 +109,10 @@ TESTABLE_PRIVATE:
int make_init_with_const_input(int init, int input, bool value); int make_init_with_const_input(int init, int input, bool value);
int memory_width(int config, bool ecc); int memory_width(int config, bool ecc);
int memory_addr_bits(int config,bool ecc); int memory_addr_bits(int config, bool ecc);
void constrain_location(CellInfo *cell); void constrain_location(CellInfo *cell);
void extract_lowskew_signals(CellInfo *cell, dict<IdString,dict<IdString,std::vector<PortRef>>> &lowskew_signals); void extract_lowskew_signals(CellInfo *cell, dict<IdString, dict<IdString, std::vector<PortRef>>> &lowskew_signals);
// Cell creating // Cell creating
CellInfo *create_cell_ptr(IdString type, IdString name); CellInfo *create_cell_ptr(IdString type, IdString name);

View File

@ -18,9 +18,9 @@
*/ */
#include <vector> #include <vector>
#include "command.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "nextpnr.h" #include "nextpnr.h"
#include "command.h"
#include "uarch/ng-ultra/ng_ultra.h" #include "uarch/ng-ultra/ng_ultra.h"
#include "uarch/ng-ultra/pack.h" #include "uarch/ng-ultra/pack.h"
#define HIMBAECHEL_CONSTIDS "uarch/ng-ultra/constids.inc" #define HIMBAECHEL_CONSTIDS "uarch/ng-ultra/constids.inc"
@ -38,13 +38,13 @@ class NGUltraLutDffTest : public ::testing::Test
ctx = new Context(chipArgs); ctx = new Context(chipArgs);
ctx->uarch->init(ctx); ctx->uarch->init(ctx);
ctx->late_init(); ctx->late_init();
impl = (NgUltraImpl*)(ctx->uarch.get()); impl = (NgUltraImpl *)(ctx->uarch.get());
} }
virtual void TearDown() { delete ctx; } virtual void TearDown() { delete ctx; }
int const_autoidx = 0; int const_autoidx = 0;
NetInfo* add_constant_driver(const char *name, char constval) NetInfo *add_constant_driver(const char *name, char constval)
{ {
IdString cell_name = ctx->idf("%s%s%d", name, (constval == '1' ? "$VCC$" : "$GND$"), const_autoidx++); IdString cell_name = ctx->idf("%s%s%d", name, (constval == '1' ? "$VCC$" : "$GND$"), const_autoidx++);
CellInfo *cc = ctx->createCell(cell_name, ctx->id(constval == '1' ? "VCC" : "GND")); CellInfo *cc = ctx->createCell(cell_name, ctx->id(constval == '1' ? "VCC" : "GND"));
@ -67,7 +67,7 @@ class NGUltraLutDffTest : public ::testing::Test
int S1 = I4 ? (lut_table >> 8) & 0xff : lut_table & 0xff; int S1 = I4 ? (lut_table >> 8) & 0xff : lut_table & 0xff;
int S2 = I3 ? (S1 >> 4 & 0xf) : S1 & 0xf; int S2 = I3 ? (S1 >> 4 & 0xf) : S1 & 0xf;
int S3 = I2 ? (S2 >> 2 & 0x3) : S2 & 0x3; int S3 = I2 ? (S2 >> 2 & 0x3) : S2 & 0x3;
int O = I1 ? (S3 >> 1 & 0x1) : S3 & 0x1; int O = I1 ? (S3 >> 1 & 0x1) : S3 & 0x1;
return O; return O;
} }
@ -99,19 +99,19 @@ TEST_F(NGUltraLutDffTest, remove_unused_gnd)
add_port(cell, "I2", PORT_IN); add_port(cell, "I2", PORT_IN);
add_port(cell, "I3", PORT_IN); add_port(cell, "I3", PORT_IN);
add_port(cell, "I4", PORT_IN); add_port(cell, "I4", PORT_IN);
cell->connectPort(id_I1, add_constant_driver("TEST",'1')); cell->connectPort(id_I1, add_constant_driver("TEST", '1'));
cell->connectPort(id_I2, add_constant_driver("TEST",'1')); cell->connectPort(id_I2, add_constant_driver("TEST", '1'));
cell->connectPort(id_I3, add_constant_driver("TEST",'1')); cell->connectPort(id_I3, add_constant_driver("TEST", '1'));
ASSERT_EQ(ctx->cells.size(), 4LU); ASSERT_EQ(ctx->cells.size(), 4LU);
packer.pack_constants(); packer.pack_constants();
ASSERT_EQ(ctx->cells.size(), 3LU); ASSERT_EQ(ctx->cells.size(), 3LU);
impl->remove_constants(); impl->remove_constants();
ASSERT_EQ(ctx->cells.size(), 2LU); ASSERT_EQ(ctx->cells.size(), 2LU);
ASSERT_EQ(ctx->cells.find(ctx->id("$PACKER_GND_DRV")),ctx->cells.end()); ASSERT_EQ(ctx->cells.find(ctx->id("$PACKER_GND_DRV")), ctx->cells.end());
ASSERT_NE(ctx->cells.find(ctx->id("$PACKER_VCC_DRV")),ctx->cells.end()); ASSERT_NE(ctx->cells.find(ctx->id("$PACKER_VCC_DRV")), ctx->cells.end());
ASSERT_EQ(ctx->nets.find(ctx->id("$PACKER_GND")),ctx->nets.end()); ASSERT_EQ(ctx->nets.find(ctx->id("$PACKER_GND")), ctx->nets.end());
ASSERT_NE(ctx->nets.find(ctx->id("$PACKER_VCC")),ctx->nets.end()); ASSERT_NE(ctx->nets.find(ctx->id("$PACKER_VCC")), ctx->nets.end());
} }
TEST_F(NGUltraLutDffTest, remove_unused_vcc) TEST_F(NGUltraLutDffTest, remove_unused_vcc)
@ -122,26 +122,26 @@ TEST_F(NGUltraLutDffTest, remove_unused_vcc)
add_port(cell, "I2", PORT_IN); add_port(cell, "I2", PORT_IN);
add_port(cell, "I3", PORT_IN); add_port(cell, "I3", PORT_IN);
add_port(cell, "I4", PORT_IN); add_port(cell, "I4", PORT_IN);
cell->connectPort(id_I1, add_constant_driver("TEST",'0')); cell->connectPort(id_I1, add_constant_driver("TEST", '0'));
cell->connectPort(id_I2, add_constant_driver("TEST",'0')); cell->connectPort(id_I2, add_constant_driver("TEST", '0'));
cell->connectPort(id_I3, add_constant_driver("TEST",'0')); cell->connectPort(id_I3, add_constant_driver("TEST", '0'));
ASSERT_EQ(ctx->cells.size(), 4LU); ASSERT_EQ(ctx->cells.size(), 4LU);
packer.pack_constants(); packer.pack_constants();
ASSERT_EQ(ctx->cells.size(), 3LU); ASSERT_EQ(ctx->cells.size(), 3LU);
impl->remove_constants(); impl->remove_constants();
ASSERT_EQ(ctx->cells.size(), 2LU); ASSERT_EQ(ctx->cells.size(), 2LU);
ASSERT_NE(ctx->cells.find(ctx->id("$PACKER_GND_DRV")),ctx->cells.end()); ASSERT_NE(ctx->cells.find(ctx->id("$PACKER_GND_DRV")), ctx->cells.end());
ASSERT_EQ(ctx->cells.find(ctx->id("$PACKER_VCC_DRV")),ctx->cells.end()); ASSERT_EQ(ctx->cells.find(ctx->id("$PACKER_VCC_DRV")), ctx->cells.end());
ASSERT_NE(ctx->nets.find(ctx->id("$PACKER_GND")),ctx->nets.end()); ASSERT_NE(ctx->nets.find(ctx->id("$PACKER_GND")), ctx->nets.end());
ASSERT_EQ(ctx->nets.find(ctx->id("$PACKER_VCC")),ctx->nets.end()); ASSERT_EQ(ctx->nets.find(ctx->id("$PACKER_VCC")), ctx->nets.end());
} }
TEST_F(NGUltraLutDffTest, make_init_with_const_input) TEST_F(NGUltraLutDffTest, make_init_with_const_input)
{ {
NgUltraPacker packer(ctx, impl); NgUltraPacker packer(ctx, impl);
for (int lut_table=0;lut_table<0x10000;lut_table++) { for (int lut_table = 0; lut_table < 0x10000; lut_table++) {
for(int lut=0;lut<16;lut++) { for (int lut = 0; lut < 16; lut++) {
int I4 = (lut & 8) ? 1 : 0; int I4 = (lut & 8) ? 1 : 0;
int I3 = (lut & 4) ? 1 : 0; int I3 = (lut & 4) ? 1 : 0;
int I2 = (lut & 2) ? 1 : 0; int I2 = (lut & 2) ? 1 : 0;
@ -152,10 +152,10 @@ TEST_F(NGUltraLutDffTest, make_init_with_const_input)
int tab3 = packer.make_init_with_const_input(tab2, 2, I3); int tab3 = packer.make_init_with_const_input(tab2, 2, I3);
int tab4 = packer.make_init_with_const_input(tab3, 3, I4); int tab4 = packer.make_init_with_const_input(tab3, 3, I4);
ASSERT_EQ(evaluate_lut(I1,I2,I3,I4,lut_table),evaluate_lut(I1,I2,I3,I4,tab1)); ASSERT_EQ(evaluate_lut(I1, I2, I3, I4, lut_table), evaluate_lut(I1, I2, I3, I4, tab1));
ASSERT_EQ(evaluate_lut(I1,I2,I3,I4,lut_table),evaluate_lut(I1,I2,I3,I4,tab2)); ASSERT_EQ(evaluate_lut(I1, I2, I3, I4, lut_table), evaluate_lut(I1, I2, I3, I4, tab2));
ASSERT_EQ(evaluate_lut(I1,I2,I3,I4,lut_table),evaluate_lut(I1,I2,I3,I4,tab3)); ASSERT_EQ(evaluate_lut(I1, I2, I3, I4, lut_table), evaluate_lut(I1, I2, I3, I4, tab3));
ASSERT_EQ(evaluate_lut(I1,I2,I3,I4,lut_table),evaluate_lut(I1,I2,I3,I4,tab4)); ASSERT_EQ(evaluate_lut(I1, I2, I3, I4, lut_table), evaluate_lut(I1, I2, I3, I4, tab4));
} }
} }
} }

View File

@ -18,8 +18,8 @@
*/ */
#include <vector> #include <vector>
#include "log.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "log.h"
USING_NEXTPNR_NAMESPACE USING_NEXTPNR_NAMESPACE