From f61e9e56094946492bdd364ab272c19919a9faca Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 24 Jul 2018 12:22:57 +0200 Subject: ecp5: Set BANKREF to correct VccIO Signed-off-by: David Shah --- ecp5/bitstream.cc | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'ecp5') diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 19ddb9f9..1efee5fc 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -30,6 +30,7 @@ #include #include +#include "io.h" #include "log.h" #include "util.h" @@ -182,12 +183,34 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex } } } + // Find bank voltages + std::unordered_map bankVcc; + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (ci->bel != BelId() && ci->type == ctx->id("TRELLIS_IO")) { + int bank = ctx->getPioBelBank(ci->bel); + std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33"); + IOVoltage vcc = get_vccio(ioType_from_str(iotype)); + if (bankVcc.find(bank) != bankVcc.end()) { + // TODO: strong and weak constraints + if (bankVcc[bank] != vcc) { + log_error("Error processing '%s': incompatible IO voltages %s and %s on bank %d.", + cell.first.c_str(ctx), iovoltage_to_str(bankVcc[bank]).c_str(), + iovoltage_to_str(vcc).c_str(), bank); + } + } else { + bankVcc[bank] = vcc; + } + } + } - // Set all bankref tiles to 3.3V (TODO) + // Set all bankref tiles to appropriate VccIO for (const auto &tile : empty_chip.tiles) { std::string type = tile.second->info.type; if (type.find("BANKREF") != std::string::npos && type != "BANKREF8") { - cc.tiles[tile.first].add_enum("BANK.VCCIO", "3V3"); + int bank = std::stoi(type.substr(7)); + if (bankVcc.find(bank) != bankVcc.end()) + cc.tiles[tile.first].add_enum("BANK.VCCIO", iovoltage_to_str(bankVcc[bank])); } } -- cgit v1.2.3 From 35a6bc496eb28f26c42e25a5e746987329e96f3e Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 24 Jul 2018 12:57:54 +0200 Subject: ecp5: Support for differential IO Signed-off-by: David Shah --- ecp5/bitstream.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'ecp5') diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 1efee5fc..c2218762 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -258,6 +258,20 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex std::string pic_tile = get_pic_tile(ctx, empty_chip, bel); cc.tiles[pio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); + if (is_differential(ioType_from_str(iotype))) { + // Explicitly disable other pair + std::string other; + if (pio == "PIOA") + other = "PIOB"; + else if (pio == "PIOC") + other = "PIOD"; + else + log_error("cannot place differential IO at location %s\n", pio.c_str()); + cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); + cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); + cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE"); + cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); + } if (dir != "INPUT" && (ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr)) { // Tie tristate low if unconnected for outputs or bidir @@ -270,7 +284,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex std::string cib_wirename = ctx->locInfo(cib_wire)->wire_data[cib_wire.index].name.get(); cc.tiles[cib_tile].add_enum("CIB." + cib_wirename + "MUX", "0"); } - if (dir == "INPUT") { + if (dir == "INPUT" && !is_differential(ioType_from_str(iotype))) { cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS", "ON"); } } else { -- cgit v1.2.3 From 974ca143e80ac48b0e87054001a48b0d6597c6fa Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 24 Jul 2018 16:09:29 +0200 Subject: Remove implementations of deprecated APIs Signed-off-by: David Shah --- ecp5/arch.cc | 38 +++++--------------------------------- ecp5/arch.h | 3 --- ecp5/arch_place.cc | 7 ++++--- 3 files changed, 9 insertions(+), 39 deletions(-) (limited to 'ecp5') diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 7d67dd0c..ea8abc0e 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -192,14 +192,14 @@ BelId Arch::getBelByName(IdString name) const return ret; } -BelRange Arch::getBelsAtSameTile(BelId bel) const +BelRange Arch::getBelsByTile(int x, int y) const { BelRange br; - NPNR_ASSERT(bel != BelId()); - br.b.cursor_tile = bel.location.y * chip_info->width + bel.location.x; - br.e.cursor_tile = bel.location.y * chip_info->width + bel.location.x; + + br.b.cursor_tile = y * chip_info->width + x; + br.e.cursor_tile = y * chip_info->width + x; br.b.cursor_index = 0; - br.e.cursor_index = locInfo(bel)->num_bels - 1; + br.e.cursor_index = chip_info->locations[chip_info->location_type[br.b.cursor_tile]].num_bels - 1; br.b.chip = chip_info; br.e.chip = chip_info; ++br.e; @@ -399,36 +399,8 @@ BelId Arch::getBelByLocation(Loc loc) const return BelId(); } -BelRange Arch::getBelsByTile(int x, int y) const -{ - BelRange br; - - int num_bels = 0; - - if (x < chip_info->width && y < chip_info->height) { - const LocationTypePOD &locI = chip_info->locations[chip_info->location_type[y * chip_info->width + x]]; - num_bels = locI.num_bels; - } - - br.b.cursor_tile = y * chip_info->width + x; - br.e.cursor_tile = y * chip_info->width + x; - br.b.cursor_index = 0; - br.e.cursor_index = num_bels - 1; - br.b.chip = chip_info; - br.e.chip = chip_info; - ++br.e; - return br; -} - // ----------------------------------------------------------------------- -void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const -{ - x = bel.location.x; - y = bel.location.y; - gb = false; -} - delay_t Arch::estimateDelay(WireId src, WireId dst) const { return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y)); diff --git a/ecp5/arch.h b/ecp5/arch.h index ce2b90c3..4400db5e 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -482,8 +482,6 @@ struct Arch : BaseCtx return range; } - BelRange getBelsAtSameTile(BelId bel) const; - BelType getBelType(BelId bel) const { NPNR_ASSERT(bel != BelId()); @@ -752,7 +750,6 @@ struct Arch : BaseCtx // ------------------------------------------------- - void estimatePosition(BelId bel, int &x, int &y, bool &gb) const; delay_t estimateDelay(WireId src, WireId dst) const; delay_t getDelayEpsilon() const { return 20; } delay_t getRipupDelayPenalty() const { return 200; } diff --git a/ecp5/arch_place.cc b/ecp5/arch_place.cc index 22ebab67..84432043 100644 --- a/ecp5/arch_place.cc +++ b/ecp5/arch_place.cc @@ -66,7 +66,8 @@ bool Arch::isBelLocationValid(BelId bel) const { if (getBelType(bel) == TYPE_TRELLIS_SLICE) { std::vector bel_cells; - for (auto bel_other : getBelsAtSameTile(bel)) { + Loc bel_loc = getBelLocation(bel); + for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { IdString cell_other = getBoundBelCell(bel_other); if (cell_other != IdString()) { const CellInfo *ci_other = cells.at(cell_other).get(); @@ -89,8 +90,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const NPNR_ASSERT(getBelType(bel) == TYPE_TRELLIS_SLICE); std::vector bel_cells; - - for (auto bel_other : getBelsAtSameTile(bel)) { + Loc bel_loc = getBelLocation(bel); + for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { IdString cell_other = getBoundBelCell(bel_other); if (cell_other != IdString() && bel_other != bel) { const CellInfo *ci_other = cells.at(cell_other).get(); -- cgit v1.2.3 From 3931c84fedc568e24c7e7e98132ec5757cdb29ab Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 24 Jul 2018 16:38:35 +0200 Subject: ecp5: Architecture testing and fixing Signed-off-by: David Shah --- ecp5/arch.cc | 8 +++++++- ecp5/main.cc | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'ecp5') diff --git a/ecp5/arch.cc b/ecp5/arch.cc index ea8abc0e..5507d1e3 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -202,7 +202,10 @@ BelRange Arch::getBelsByTile(int x, int y) const br.e.cursor_index = chip_info->locations[chip_info->location_type[br.b.cursor_tile]].num_bels - 1; br.b.chip = chip_info; br.e.chip = chip_info; - ++br.e; + if (br.e.cursor_index == -1) + ++br.e.cursor_index; + else + ++br.e; return br; } @@ -278,6 +281,7 @@ PipId Arch::getPipByName(IdString name) const Location loc; std::string basename; std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this)); + ret.location = loc; const LocationTypePOD *loci = locInfo(ret); for (int i = 0; i < loci->num_pips; i++) { PipId curr; @@ -285,6 +289,8 @@ PipId Arch::getPipByName(IdString name) const curr.index = i; pip_by_name[getPipName(curr)] = curr; } + if (pip_by_name.find(name) == pip_by_name.end()) + NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this)); return pip_by_name[name]; } diff --git a/ecp5/main.cc b/ecp5/main.cc index 5a4a900a..90096855 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -63,6 +63,7 @@ int main(int argc, char *argv[]) #ifndef NO_GUI options.add_options()("gui", "start gui"); #endif + options.add_options()("test", "check architecture database integrity"); options.add_options()("25k", "set device type to LFE5U-25F"); options.add_options()("45k", "set device type to LFE5U-45F"); @@ -148,6 +149,9 @@ int main(int argc, char *argv[]) if (vm.count("no-tmdriv")) ctx->timing_driven = false; + if (vm.count("test")) + ctx->archcheck(); + #ifndef NO_GUI if (vm.count("gui")) { Application a(argc, argv); -- cgit v1.2.3 From c9c3d970c918f9c91d9886467d7957cbc49bd6b1 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 24 Jul 2018 20:21:31 +0200 Subject: Fixed pybiding so generic can work and ecp5 expose all needed --- ecp5/arch_pybindings.cc | 125 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 3 deletions(-) (limited to 'ecp5') diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index 8310c3a1..c261c3ec 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -2,7 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf - * Copyright (C) 2018 David Shah + * Copyright (C) 2018 David Shah * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,13 +20,132 @@ #ifndef NO_PYTHON +#include "arch_pybindings.h" #include "nextpnr.h" #include "pybindings.h" NEXTPNR_NAMESPACE_BEGIN -void arch_wrap_python() {} +void arch_wrap_python() +{ + using namespace PythonConversion; + class_("ArchArgs").def_readwrite("type", &ArchArgs::type); + + class_("BelId").def_readwrite("index", &BelId::index); + + class_("WireId").def_readwrite("index", &WireId::index); + + class_("PipId").def_readwrite("index", &PipId::index); + + class_("BelPin").def_readwrite("bel", &BelPin::bel).def_readwrite("pin", &BelPin::pin); + + enum_("PortPin") +#define X(t) .value("PIN_" #t, PIN_##t) + +#include "portpins.inc" + ; +#undef X + + auto arch_cls = class_, boost::noncopyable>("Arch", init()); + auto ctx_cls = class_, boost::noncopyable>("Context", no_init) + .def("checksum", &Context::checksum) + .def("pack", &Context::pack) + .def("place", &Context::place) + .def("route", &Context::route); + + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getBelType"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "checkBelAvail"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getBelChecksum"); + fn_wrapper_3a_v, + conv_from_str, pass_through>::def_wrap(ctx_cls, "bindBel"); + fn_wrapper_1a_v>::def_wrap( + ctx_cls, "unbindBel"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getBoundBelCell"); + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingBelCell"); + fn_wrapper_0a>::def_wrap(ctx_cls, + "getBels"); + + fn_wrapper_2a, + conv_from_str, conv_from_str>::def_wrap(ctx_cls, "getBelPinWire"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getWireBelPins"); + + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getWireChecksum"); + fn_wrapper_3a_v, + conv_from_str, pass_through>::def_wrap(ctx_cls, "bindWire"); + fn_wrapper_1a_v>::def_wrap( + ctx_cls, "unbindWire"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "checkWireAvail"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getBoundWireNet"); + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingWireNet"); + + fn_wrapper_0a>::def_wrap( + ctx_cls, "getWires"); + + fn_wrapper_0a>::def_wrap( + ctx_cls, "getPips"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getPipChecksum"); + fn_wrapper_3a_v, + conv_from_str, pass_through>::def_wrap(ctx_cls, "bindPip"); + fn_wrapper_1a_v>::def_wrap( + ctx_cls, "unbindPip"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "checkPipAvail"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getBoundPipNet"); + fn_wrapper_1a, conv_from_str>::def_wrap(ctx_cls, "getConflictingPipNet"); + + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getPipsDownhill"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getPipsUphill"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getWireAliases"); + + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getPipSrcWire"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getPipDstWire"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getPipDelay"); + + fn_wrapper_1a, + pass_through>::def_wrap(ctx_cls, "getPackagePinBel"); + fn_wrapper_1a, + conv_from_str>::def_wrap(ctx_cls, "getBelPackagePin"); + + fn_wrapper_0a>::def_wrap( + ctx_cls, "getChipName"); + fn_wrapper_0a>::def_wrap(ctx_cls, + "archId"); + + typedef std::unordered_map> CellMap; + typedef std::unordered_map> NetMap; + + readonly_wrapper>::def_wrap(ctx_cls, + "cells"); + readonly_wrapper>::def_wrap(ctx_cls, + "nets"); + WRAP_RANGE(Bel, conv_to_str); + WRAP_RANGE(Wire, conv_to_str); + WRAP_RANGE(AllPip, conv_to_str); + WRAP_RANGE(Pip, conv_to_str); + + WRAP_MAP_UPTR(CellMap, "IdCellMap"); + WRAP_MAP_UPTR(NetMap, "IdNetMap"); +} NEXTPNR_NAMESPACE_END -#endif +#endif // NO_PYTHON -- cgit v1.2.3 From 6a7f3cd336ebb35389d0c4ee4f8b457d2a2e026a Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 24 Jul 2018 21:25:33 +0200 Subject: ecp5: Working on LVDS inputs for Versa support Signed-off-by: David Shah --- ecp5/bitstream.cc | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'ecp5') diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index c2218762..9a925d63 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -185,6 +185,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex } // Find bank voltages std::unordered_map bankVcc; + std::unordered_map bankLvds; + for (auto &cell : ctx->cells) { CellInfo *ci = cell.second.get(); if (ci->bel != BelId() && ci->type == ctx->id("TRELLIS_IO")) { @@ -201,6 +203,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex } else { bankVcc[bank] = vcc; } + if (iotype == "LVDS") + bankLvds[bank] = true; } } @@ -211,6 +215,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex int bank = std::stoi(type.substr(7)); if (bankVcc.find(bank) != bankVcc.end()) cc.tiles[tile.first].add_enum("BANK.VCCIO", iovoltage_to_str(bankVcc[bank])); + if (bankLvds[bank]) { + cc.tiles[tile.first].add_enum("BANK.DIFF_REF", "ON"); + cc.tiles[tile.first].add_enum("BANK.LVDSO", "ON"); + } } } -- cgit v1.2.3 From 32c7247785f48b2307e559a0af50d9387bda8b49 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 24 Jul 2018 22:26:26 +0200 Subject: ecp5: Bitsream gen tuning Signed-off-by: David Shah --- ecp5/bitstream.cc | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'ecp5') diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 9a925d63..f1feba24 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -191,18 +191,23 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex CellInfo *ci = cell.second.get(); if (ci->bel != BelId() && ci->type == ctx->id("TRELLIS_IO")) { int bank = ctx->getPioBelBank(ci->bel); + std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT"); std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33"); - IOVoltage vcc = get_vccio(ioType_from_str(iotype)); - if (bankVcc.find(bank) != bankVcc.end()) { - // TODO: strong and weak constraints - if (bankVcc[bank] != vcc) { - log_error("Error processing '%s': incompatible IO voltages %s and %s on bank %d.", - cell.first.c_str(ctx), iovoltage_to_str(bankVcc[bank]).c_str(), - iovoltage_to_str(vcc).c_str(), bank); + + if (dir != "INPUT") { + IOVoltage vcc = get_vccio(ioType_from_str(iotype)); + if (bankVcc.find(bank) != bankVcc.end()) { + // TODO: strong and weak constraints + if (bankVcc[bank] != vcc) { + log_error("Error processing '%s': incompatible IO voltages %s and %s on bank %d.", + cell.first.c_str(ctx), iovoltage_to_str(bankVcc[bank]).c_str(), + iovoltage_to_str(vcc).c_str(), bank); + } + } else { + bankVcc[bank] = vcc; } - } else { - bankVcc[bank] = vcc; } + if (iotype == "LVDS") bankLvds[bank] = true; } @@ -275,8 +280,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex other = "PIOD"; else log_error("cannot place differential IO at location %s\n", pio.c_str()); - cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); - cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); + //cc.tiles[pio_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); + //cc.tiles[pic_tile].add_enum(other + ".BASE_TYPE", "_NONE_"); cc.tiles[pio_tile].add_enum(other + ".PULLMODE", "NONE"); cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); } -- cgit v1.2.3