From a630758ca7f65b412a4dd2e717902f669df15fd1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 26 Dec 2018 18:14:23 -0800 Subject: [PATCH] Cleanup --- xc7/arch.cc | 371 ++-------------------------------------- xc7/arch.h | 70 +------- xc7/arch_place.cc | 116 +++---------- xc7/blinky.sh | 2 +- xc7/cells.cc | 224 +------------------------ xc7/delay.cc | 73 -------- xc7/pack.cc | 418 +--------------------------------------------- 7 files changed, 56 insertions(+), 1218 deletions(-) diff --git a/xc7/arch.cc b/xc7/arch.cc index bb569d16..6ec2d521 100644 --- a/xc7/arch.cc +++ b/xc7/arch.cc @@ -28,27 +28,8 @@ #include "router1.h" #include "util.h" -#include -#include -#include -#include -#include -#include -#include -struct nextpnr_binary_iarchive : public boost::archive::binary_iarchive { - nextpnr_binary_iarchive(boost::iostreams::filtering_istreambuf &ifs, NEXTPNR_NAMESPACE::BaseCtx* ctx, const std::string& inDeviceName, const std::string& inPackageName) : boost::archive::binary_iarchive(ifs), ctx(ctx), inDeviceName(inDeviceName), inPackageName(inPackageName) {} - NEXTPNR_NAMESPACE::BaseCtx *ctx; - std::string inDeviceName, inPackageName; -}; -struct nextpnr_binary_oarchive : public boost::archive::binary_oarchive { - nextpnr_binary_oarchive(boost::iostreams::filtering_ostreambuf &ofs, NEXTPNR_NAMESPACE::BaseCtx* ctx) : boost::archive::binary_oarchive(ofs), ctx(ctx) {} - NEXTPNR_NAMESPACE::BaseCtx *ctx; -}; - #include "torc/common/DirectoryTree.hpp" -//#define TORC_INFO_DB "torc_info.ar" - NEXTPNR_NAMESPACE_BEGIN std::unique_ptr torc_info; @@ -369,29 +350,7 @@ Arch::Arch(ArchArgs args) : args(args) { torc::common::DirectoryTree directoryTree("/opt/torc/src/torc"); if (args.type == ArchArgs::Z020) { -#ifdef TORC_INFO_DB - std::ifstream ifs(TORC_INFO_DB, std::ios::binary); - if (ifs) { - boost::iostreams::filtering_istreambuf fifs; - fifs.push(boost::iostreams::zlib_decompressor()); - fifs.push(ifs); - nextpnr_binary_iarchive ia(fifs, this, "xc7z020", args.package); - ia >> torc_info; - } else -#endif - { - torc_info = std::unique_ptr(new TorcInfo(this, "xc7z020", args.package)); -#ifdef TORC_INFO_DB - std::ofstream ofs(TORC_INFO_DB, std::ios::binary); - if (ofs) { - boost::iostreams::filtering_ostreambuf fofs; - fofs.push(boost::iostreams::zlib_compressor()); - fofs.push(ofs); - nextpnr_binary_oarchive oa(fofs, this); - oa << torc_info; - } -#endif - } + torc_info = std::unique_ptr(new TorcInfo(this, "xc7z020", args.package)); } else if (args.type == ArchArgs::VX980) { torc_info = std::unique_ptr(new TorcInfo(this, "xc7vx980t", args.package)); } else { @@ -406,21 +365,9 @@ Arch::Arch(ArchArgs args) : args(args) log_info("Number of pips: %d\n", torc_info->num_pips); } - // package_info = nullptr; - // for (int i = 0; i < chip_info->num_packages; i++) { - // if (chip_info->packages_data[i].name.get() == args.package) { - // package_info = &(chip_info->packages_data[i]); - // break; - // } - // } - // if (package_info == nullptr) - // log_error("Unsupported package '%s'.\n", args.package.c_str()); - - // bel_carry.resize(chip_info->num_bels); bel_to_cell.resize(torc_info->num_bels); wire_to_net.resize(torc_info->num_wires); pip_to_net.resize(torc_info->num_pips); - // switches_locked.resize(chip_info->num_switches); } // ----------------------------------------------------------------------- @@ -429,6 +376,8 @@ std::string Arch::getChipName() const { if (args.type == ArchArgs::Z020) { return "z020"; + } else if (args.type == ArchArgs::VX980) { + return "vx980"; } else { log_error("Unsupported XC7 chip type.\n"); } @@ -440,6 +389,8 @@ IdString Arch::archArgsToId(ArchArgs args) const { if (args.type == ArchArgs::Z020) return id("z020"); + if (args.type == ArchArgs::VX980) + return id("vx980"); return IdString(); } @@ -564,49 +515,12 @@ WireId Arch::getBelPinWire(BelId bel, IdString pin) const pin_name.c_str()); return torc_info->tilewire_to_wire(tw); - - // NPNR_ASSERT(bel != BelId()); - // - // int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; - // const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); - // - // if (num_bel_wires < 7) { - // for (int i = 0; i < num_bel_wires; i++) { - // if (bel_wires[i].port == pin.index) { - // ret.index = bel_wires[i].wire_index; - // break; - // } - // } - // } else { - // int b = 0, e = num_bel_wires - 1; - // while (b <= e) { - // int i = (b + e) / 2; - // if (bel_wires[i].port == pin.index) { - // ret.index = bel_wires[i].wire_index; - // break; - // } - // if (bel_wires[i].port > pin.index) - // e = i - 1; - // else - // b = i + 1; - // } - // } - // - //return ret; } std::vector Arch::getBelPins(BelId bel) const { std::vector ret; - -/* NPNR_ASSERT(bel != BelId()); - - int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; - const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); - - for (int i = 0; i < num_bel_wires; i++) - ret.push_back(IdString(bel_wires[i].port)); -*/ + NPNR_ASSERT("TODO"); return ret; } @@ -615,54 +529,17 @@ std::vector Arch::getBelPins(BelId bel) const WireId Arch::getWireByName(IdString name) const { WireId ret; - if (wire_by_name.empty()) { for (int i = 0; i < chip_info->num_wires; i++) wire_by_name[id(chip_info->wire_data[i].name.get())] = i; } - - // auto it = wire_by_name.find(name); - // if (it != wire_by_name.end()) - // ret.index = it->second; - return ret; } IdString Arch::getWireType(WireId wire) const { NPNR_ASSERT(wire != WireId()); - // switch (chip_info->wire_data[wire.index].type) { - // case WireInfoPOD::WIRE_TYPE_NONE: - // return IdString(); - // case WireInfoPOD::WIRE_TYPE_GLB2LOCAL: - // return id("GLB2LOCAL"); - // case WireInfoPOD::WIRE_TYPE_GLB_NETWK: - // return id("GLB_NETWK"); - // case WireInfoPOD::WIRE_TYPE_LOCAL: - // return id("LOCAL"); - // case WireInfoPOD::WIRE_TYPE_LUTFF_IN: - // return id("LUTFF_IN"); - // case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT: - // return id("LUTFF_IN_LUT"); - // case WireInfoPOD::WIRE_TYPE_LUTFF_LOUT: - // return id("LUTFF_LOUT"); - // case WireInfoPOD::WIRE_TYPE_LUTFF_OUT: - // return id("LUTFF_OUT"); - // case WireInfoPOD::WIRE_TYPE_LUTFF_COUT: - // return id("LUTFF_COUT"); - // case WireInfoPOD::WIRE_TYPE_LUTFF_GLOBAL: - // return id("LUTFF_GLOBAL"); - // case WireInfoPOD::WIRE_TYPE_CARRY_IN_MUX: - // return id("CARRY_IN_MUX"); - // case WireInfoPOD::WIRE_TYPE_SP4_V: - // return id("SP4_V"); - // case WireInfoPOD::WIRE_TYPE_SP4_H: - // return id("SP4_H"); - // case WireInfoPOD::WIRE_TYPE_SP12_V: - // return id("SP12_V"); - // case WireInfoPOD::WIRE_TYPE_SP12_H: - // return id("SP12_H"); - // } + NPNR_ASSERT("TODO"); return IdString(); } @@ -670,6 +547,7 @@ IdString Arch::getWireType(WireId wire) const std::vector> Arch::getWireAttrs(WireId wire) const { std::vector> ret; + NPNR_ASSERT("TODO"); return ret; } @@ -678,19 +556,7 @@ std::vector> Arch::getWireAttrs(WireId wire) co PipId Arch::getPipByName(IdString name) const { PipId ret; - -/* if (pip_by_name.empty()) { - for (int i = 0; i < chip_info->num_pips; i++) { - PipId pip; - pip.index = i; - pip_by_name[getPipName(pip)] = i; - } - } - - auto it = pip_by_name.find(name); - if (it != pip_by_name.end()) - ret.index = it->second; -*/ + NPNR_ASSERT("TODO"); return ret; } @@ -703,33 +569,12 @@ IdString Arch::getPipName(PipId pip) const std::stringstream pip_name; pip_name << ewi_src.mTileName << "." << ewi_src.mWireName << ".->." << ewi_dst.mWireName; return id(pip_name.str()); - - //#if 1 - // int x = chip_info->pip_data[pip.index].x; - // int y = chip_info->pip_data[pip.index].y; - // - // std::string src_name = chip_info->wire_data[chip_info->pip_data[pip.index].src].name.get(); - // std::replace(src_name.begin(), src_name.end(), '/', '.'); - // - // std::string dst_name = chip_info->wire_data[chip_info->pip_data[pip.index].dst].name.get(); - // std::replace(dst_name.begin(), dst_name.end(), '/', '.'); - // - // return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name); - //#else - // return id(chip_info->pip_data[pip.index].name.get()); - //#endif } -//IdString Arch::getPipType(PipId pip) const -//{ -// NPNR_ASSERT(pip != PipId()); -// return IdString(); -//} - std::vector> Arch::getPipAttrs(PipId pip) const { std::vector> ret; - + NPNR_ASSERT("TODO"); return ret; } @@ -739,11 +584,7 @@ BelId Arch::getPackagePinBel(const std::string &pin) const { return getBelByName std::string Arch::getBelPackagePin(BelId bel) const { - // for (int i = 0; i < package_info->num_pins; i++) { - // if (package_info->pins[i].bel_index == bel.index) { - // return std::string(package_info->pins[i].name.get()); - // } - // } + NPNR_ASSERT("TODO"); return ""; } @@ -762,39 +603,7 @@ IdString Arch::getGroupName(GroupId group) const std::string suffix; switch (group.type) { - case GroupId::TYPE_FRAME: - suffix = "tile"; - break; - case GroupId::TYPE_MAIN_SW: - suffix = "main_sw"; - break; - case GroupId::TYPE_LOCAL_SW: - suffix = "local_sw"; - break; - case GroupId::TYPE_LC0_SW: - suffix = "lc0_sw"; - break; - case GroupId::TYPE_LC1_SW: - suffix = "lc1_sw"; - break; - case GroupId::TYPE_LC2_SW: - suffix = "lc2_sw"; - break; - case GroupId::TYPE_LC3_SW: - suffix = "lc3_sw"; - break; - case GroupId::TYPE_LC4_SW: - suffix = "lc4_sw"; - break; - case GroupId::TYPE_LC5_SW: - suffix = "lc5_sw"; - break; - case GroupId::TYPE_LC6_SW: - suffix = "lc6_sw"; - break; - case GroupId::TYPE_LC7_SW: - suffix = "lc7_sw"; - break; + NPNR_ASSERT("TODO"); default: return IdString(); } @@ -805,52 +614,7 @@ IdString Arch::getGroupName(GroupId group) const std::vector Arch::getGroups() const { std::vector ret; -/* - for (int y = 0; y < chip_info->height; y++) { - for (int x = 0; x < chip_info->width; x++) { - TileType type = chip_info->tile_grid[y * chip_info->width + x]; - if (type == TILE_NONE) - continue; - - GroupId group; - group.type = GroupId::TYPE_FRAME; - group.x = x; - group.y = y; - // ret.push_back(group); - - group.type = GroupId::TYPE_MAIN_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LOCAL_SW; - ret.push_back(group); - - if (type == TILE_LOGIC) { - group.type = GroupId::TYPE_LC0_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC1_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC2_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC3_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC4_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC5_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC6_SW; - ret.push_back(group); - - group.type = GroupId::TYPE_LC7_SW; - ret.push_back(group); - } - } - }*/ + NPNR_ASSERT("TODO"); return ret; } @@ -869,12 +633,14 @@ std::vector Arch::getGroupWires(GroupId group) const std::vector Arch::getGroupPips(GroupId group) const { std::vector ret; + NPNR_ASSERT("TODO"); return ret; } std::vector Arch::getGroupGroups(GroupId group) const { std::vector ret; + NPNR_ASSERT("TODO"); return ret; } @@ -929,6 +695,7 @@ DecalXY Arch::getGroupDecal(GroupId group) const std::vector Arch::getDecalGraphics(DecalId decal) const { std::vector ret; + NPNR_ASSERT("TODO"); return ret; } @@ -1078,109 +845,3 @@ void Arch::assignCellInfo(CellInfo *cell) } NEXTPNR_NAMESPACE_END - -// outside of any namespace -BOOST_SERIALIZATION_SPLIT_FREE(Segments::SegmentReference) -BOOST_SERIALIZATION_SPLIT_FREE(CompactSegmentIndex) -BOOST_SERIALIZATION_SPLIT_FREE(TileIndex) -BOOST_SERIALIZATION_SPLIT_FREE(Arc) -BOOST_SERIALIZATION_SPLIT_FREE(Tilewire) -BOOST_SERIALIZATION_SPLIT_FREE(WireIndex) -BOOST_SERIALIZATION_SPLIT_FREE(SiteIndex) -BOOST_SERIALIZATION_SPLIT_FREE(NEXTPNR_NAMESPACE::IdString) - -namespace boost { namespace serialization { - -template -inline void load_construct_data( - Archive & ar, NEXTPNR_NAMESPACE::TorcInfo * t, const unsigned int file_version -){ - const auto& inDeviceName = static_cast(ar).inDeviceName; - const auto& inPackageName = static_cast(ar).inPackageName; - ::new(t)NEXTPNR_NAMESPACE::TorcInfo(inDeviceName, inPackageName); -} - -template -void save(Archive& ar, const Segments::SegmentReference& o, unsigned int) { - ar & o.getCompactSegmentIndex(); - ar & o.getAnchorTileIndex(); -} -template -void load(Archive& ar, Segments::SegmentReference& o, unsigned int) { - CompactSegmentIndex i; - TileIndex j; - ar & i; - ar & j; - o = Segments::SegmentReference(i, j); -} -#define SERIALIZE_POD(__T__) \ -template \ -void save(Archive& ar, const __T__& o, unsigned int) { \ - ar & static_cast<__T__::pod>(o); \ -} \ -template \ -void load(Archive& ar, __T__& o, unsigned int) { \ - __T__::pod i; \ - ar & i; \ - o = __T__(i); \ -} -SERIALIZE_POD(CompactSegmentIndex) -SERIALIZE_POD(TileIndex) -SERIALIZE_POD(WireIndex) -SERIALIZE_POD(SiteIndex) -template -void save(Archive& ar, const Arc& o, unsigned int) { - ar & o.getSourceTilewire(); - ar & o.getSinkTilewire(); -} -template -void load(Archive& ar, Arc& o, unsigned int) { - Tilewire s, t; - ar & s; - ar & t; - o = Arc(s, t); -} -template -void save(Archive& ar, const Tilewire& o, unsigned int) { - ar & o.getTileIndex(); - ar & o.getWireIndex(); -} -template -void load(Archive& ar, Tilewire& o, unsigned int) { - TileIndex i; - WireIndex j; - ar & i; - ar & j; - o.setTileIndex(TileIndex(i)); - o.setWireIndex(WireIndex(j)); -} -template -void serialize(Archive& ar, NEXTPNR_NAMESPACE::Loc& o, unsigned int) { - ar & o.x; - ar & o.y; - ar & o.z; -} -template -void serialize(Archive& ar, NEXTPNR_NAMESPACE::DelayInfo& o, unsigned int) { - ar & o.delay; -} -template -void save(Archive& ar, const NEXTPNR_NAMESPACE::IdString& o, unsigned int) { - const std::string i = o.str(static_cast(ar).ctx); - ar & i; -} -template -void load(Archive& ar, NEXTPNR_NAMESPACE::IdString& o, unsigned int) { - std::string i; - ar & i; - o = static_cast(ar).ctx->id(i); -} -#define SERIALIZE_INDEX(__T__) \ -template \ -void serialize(Archive& ar, __T__& o, unsigned int) { \ - ar & o.index; \ -} -SERIALIZE_INDEX(NEXTPNR_NAMESPACE::BelId) -SERIALIZE_INDEX(NEXTPNR_NAMESPACE::WireId) -SERIALIZE_INDEX(NEXTPNR_NAMESPACE::PipId) -}} // namespace boost::serialization diff --git a/xc7/arch.h b/xc7/arch.h index f0b48d43..75f8530a 100644 --- a/xc7/arch.h +++ b/xc7/arch.h @@ -21,8 +21,6 @@ #error Include "arch.h" via "nextpnr.h" only. #endif -#include - #include "torc/Architecture.hpp" #include "torc/Common.hpp" using namespace torc::architecture; @@ -327,29 +325,6 @@ struct TorcInfo std::vector> tile_to_xy; TorcInfo(const std::string &inDeviceName, const std::string &inPackageName); -private: - friend class boost::serialization::access; - //TorcInfo(const std::string &inDeviceName, const std::string &inPackageName); - //template friend inline void load_construct_data(Archive &ar, T *t, const unsigned int file_version); - template - void serialize(Archive & ar, const unsigned int /*version*/) - { - ar & bel_to_site_index; - ar & num_bels; - ar & site_index_to_bel; - ar & site_index_to_type; - ar & bel_to_loc; - ar & segment_to_wire; - ar & trivial_to_wire; - ar & wire_to_tilewire; - ar & num_wires; - ar & wire_to_delay; - ar & wire_to_pips_downhill; - ar & pip_to_arc; - ar & num_pips; - ar & wire_is_global; - ar & tile_to_xy; - } }; extern std::unique_ptr torc_info; @@ -675,7 +650,6 @@ struct Arch : BaseCtx auto pip = it->second.pip; if (pip != PipId()) { pip_to_net[pip.index] = nullptr; - // switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr; } net_wires.erase(it); @@ -708,10 +682,7 @@ struct Arch : BaseCtx BelPinRange getWireBelPins(WireId wire) const { BelPinRange range; - // NPNR_ASSERT(wire != WireId()); - // range.b.ptr = chip_info->wire_data[wire.index].bel_pins.get(); - // range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bel_pins; - throw; + NPNR_ASSERT("TODO"); return range; } @@ -731,10 +702,8 @@ struct Arch : BaseCtx { NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip_to_net[pip.index] == nullptr); - // NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == nullptr); pip_to_net[pip.index] = net; - // switches_locked[chip_info->pip_data[pip.index].switch_index] = net; WireId dst = getPipDstWire(pip); NPNR_ASSERT(wire_to_net[dst.index] == nullptr); @@ -749,7 +718,6 @@ struct Arch : BaseCtx { NPNR_ASSERT(pip != PipId()); NPNR_ASSERT(pip_to_net[pip.index] != nullptr); - // NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != nullptr); WireId dst = getPipDstWire(pip); NPNR_ASSERT(wire_to_net[dst.index] != nullptr); @@ -757,7 +725,6 @@ struct Arch : BaseCtx pip_to_net[pip.index]->wires.erase(dst); pip_to_net[pip.index] = nullptr; - // switches_locked[chip_info->pip_data[pip.index].switch_index] = nullptr; refreshUiPip(pip); refreshUiWire(dst); } @@ -765,25 +732,6 @@ struct Arch : BaseCtx bool checkPipAvail(PipId pip) const { NPNR_ASSERT(pip != PipId()); - // auto &pi = chip_info->pip_data[pip.index]; - // auto &si = chip_info->bits_info->switches[pi.switch_index]; - - // if (switches_locked[pi.switch_index] != nullptr) - // return false; - - // if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) { - // NPNR_ASSERT(si.bel >= 0); - // if (bel_to_cell[si.bel] != nullptr) - // return false; - //} - - // if (pi.flags & PipInfoPOD::FLAG_NOCARRY) { - // NPNR_ASSERT(si.bel >= 0); - // if (bel_carry[si.bel]) - // return false; - //} - - // return true; return pip_to_net[pip.index] == nullptr; } @@ -798,7 +746,6 @@ struct Arch : BaseCtx NetInfo *getConflictingPipNet(PipId pip) const { NPNR_ASSERT(pip != PipId()); - // return switches_locked[chip_info->pip_data[pip.index].switch_index]; return pip_to_net[pip.index]; } @@ -812,16 +759,9 @@ struct Arch : BaseCtx Loc getPipLocation(PipId pip) const { - //const auto &arc = torc_info->pip_to_arc[pip.index]; - //const auto &tw = arc.getSourceTilewire(); - //const auto &tile_info = torc_info->tiles.getTileInfo(tw.getTileIndex()); - - //Loc loc; - //loc.x = tile_info.getCol(); - //loc.y = tile_info.getRow(); - //loc.z = 0; - //return loc; - throw; + Loc loc; + NPNR_ASSERT("TODO"); + return loc; } IdString getPipName(PipId pip) const; @@ -980,6 +920,4 @@ struct Arch : BaseCtx float placer_constraintWeight = 10; }; -// void ice40DelayFuzzerMain(Context *ctx); - NEXTPNR_NAMESPACE_END diff --git a/xc7/arch_place.cc b/xc7/arch_place.cc index fd09006e..7d1e32e4 100644 --- a/xc7/arch_place.cc +++ b/xc7/arch_place.cc @@ -29,43 +29,14 @@ NEXTPNR_NAMESPACE_BEGIN bool Arch::logicCellsCompatible(const CellInfo **it, const size_t size) const { - // bool dffs_exist = false, dffs_neg = false; - // const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr; - // - // for (auto cell : boost::make_iterator_range(it, it+size)) { - // NPNR_ASSERT(cell->belType == id_ICESTORM_LC); - // if (cell->lcInfo.dffEnable) { - // if (!dffs_exist) { - // dffs_exist = true; - // cen = cell->lcInfo.cen; - // clk = cell->lcInfo.clk; - // sr = cell->lcInfo.sr; - // - // if (cell->lcInfo.negClk) { - // dffs_neg = true; - // } - // } else { - // if (cen != cell->lcInfo.cen) - // return false; - // if (clk != cell->lcInfo.clk) - // return false; - // if (sr != cell->lcInfo.sr) - // return false; - // if (dffs_neg != cell->lcInfo.negClk) - // return false; - // } - // } - // locals_count += cell->lcInfo.inputCount; - // } - // - // return locals_count <= 32; + // TODO: Check clock, clock-enable, and set-reset compatiility return true; } bool Arch::isBelLocationValid(BelId bel) const { - if (getBelType(bel) == id_ICESTORM_LC) { - std::array bel_cells; + if (getBelType(bel) == id("XC7_LC")) { + std::array bel_cells; size_t num_cells = 0; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { @@ -85,70 +56,23 @@ bool Arch::isBelLocationValid(BelId bel) const bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { - // if (cell->type == id_ICESTORM_LC) { - // NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC); - // - // std::array bel_cells; - // size_t num_cells = 0; - // - // Loc bel_loc = getBelLocation(bel); - // for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { - // CellInfo *ci_other = getBoundBelCell(bel_other); - // if (ci_other != nullptr && bel_other != bel) - // bel_cells[num_cells++] = ci_other; - // } - // - // bel_cells[num_cells++] = cell; - // return logicCellsCompatible(bel_cells.data(), num_cells); - // } else if (cell->type == id_SB_IO) { - // // Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to. - // - // // Find shared PLL by looking for driving bel siblings from D_IN_0 - // // that are a PLL clock output. - // auto wire = getBelPinWire(bel, id_D_IN_0); - // IdString pll_bel_pin; - // BelId pll_bel; - // for (auto pin : getWireBelPins(wire)) { - // if (pin.pin == id_PLLOUT_A || pin.pin == id_PLLOUT_B) { - // pll_bel = pin.bel; - // pll_bel_pin = pin.pin; - // break; - // } - // } - // // Is there a PLL that shares this IO buffer? - // if (pll_bel.index != -1) { - // auto pll_cell = getBoundBelCell(pll_bel); - // // Is a PLL placed in this PLL bel? - // if (pll_cell != nullptr) { - // // Is the shared port driving a net? - // auto pi = pll_cell->ports[pll_bel_pin]; - // if (pi.net != nullptr) { - // // Are we perhaps a PAD INPUT Bel that can be placed here? - // if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) { - // return true; - // } - // return false; - // } - // } - // } - // return getBelPackagePin(bel) != ""; - // } else if (cell->type == id_SB_GB) { - // NPNR_ASSERT(cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net != nullptr); - // const NetInfo *net = cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net; - // IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT)); - // int glb_id = std::stoi(std::string("") + glb_net.str(this).back()); - // if (net->is_reset && net->is_enable) - // return false; - // else if (net->is_reset) - // return (glb_id % 2) == 0; - // else if (net->is_enable) - // return (glb_id % 2) == 1; - // else - // return true; - // } else { - // // TODO: IO cell clock checks - return true; - // } + if (cell->type == id("XC7_LC")) { + std::array bel_cells; + size_t num_cells = 0; + + Loc bel_loc = getBelLocation(bel); + for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { + CellInfo *ci_other = getBoundBelCell(bel_other); + if (ci_other != nullptr && bel_other != bel) + bel_cells[num_cells++] = ci_other; + } + + bel_cells[num_cells++] = cell; + return logicCellsCompatible(bel_cells.data(), num_cells); + } + else { + return true; + } } NEXTPNR_NAMESPACE_END diff --git a/xc7/blinky.sh b/xc7/blinky.sh index dff168e0..1ba77434 100755 --- a/xc7/blinky.sh +++ b/xc7/blinky.sh @@ -1,7 +1,7 @@ #!/bin/bash set -ex yosys blinky.ys -- ../nextpnr-xc7 --json blinky.json --pcf blinky.pcf --xdl blinky.xdl --freq 150 +../nextpnr-xc7 --json blinky.json --pcf blinky.pcf --xdl blinky.xdl --freq 150 xdl -xdl2ncd blinky.xdl bitgen -w blinky.ncd -g UnconstrainedPins:Allow trce blinky.ncd -v 10 diff --git a/xc7/cells.cc b/xc7/cells.cc index e95de384..07cb30b0 100644 --- a/xc7/cells.cc +++ b/xc7/cells.cc @@ -68,190 +68,15 @@ std::unique_ptr create_xc7_cell(Context *ctx, IdString type, std::stri add_port(ctx, new_cell.get(), "OMUX", PORT_OUT); add_port(ctx, new_cell.get(), "COUT", PORT_OUT); } else if (type == ctx->id("IOBUF")) { - if (ctx->args.type == ArchArgs::Z020) { - new_cell->type = id_IOB33; - } else { - new_cell->type = id_IOB18; - } - //new_cell->params[ctx->id("PIN_TYPE")] = "0"; - //new_cell->params[ctx->id("PULLUP")] = "0"; - //new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; - //new_cell->params[ctx->id("IOSTANDARD")] = "SB_LVCMOS"; - - // add_port(ctx, new_cell.get(), "PACKAGE_PIN", PORT_INOUT); - // - // add_port(ctx, new_cell.get(), "LATCH_INPUT_VALUE", PORT_IN); - // add_port(ctx, new_cell.get(), "CLOCK_ENABLE", PORT_IN); - // add_port(ctx, new_cell.get(), "INPUT_CLK", PORT_IN); - // add_port(ctx, new_cell.get(), "OUTPUT_CLK", PORT_IN); - // - // add_port(ctx, new_cell.get(), "OUTPUT_ENABLE", PORT_IN); - // add_port(ctx, new_cell.get(), "D_OUT_0", PORT_IN); - // add_port(ctx, new_cell.get(), "D_OUT_1", PORT_IN); - // - // add_port(ctx, new_cell.get(), "D_IN_0", PORT_OUT); - // add_port(ctx, new_cell.get(), "D_IN_1", PORT_OUT); + if (ctx->args.type == ArchArgs::Z020) + new_cell->type = id_IOB33; + else + new_cell->type = id_IOB18; add_port(ctx, new_cell.get(), "I", PORT_OUT); add_port(ctx, new_cell.get(), "O", PORT_IN); - // } else if (type == ctx->id("ICESTORM_RAM")) { - // new_cell->params[ctx->id("NEG_CLK_W")] = "0"; - // new_cell->params[ctx->id("NEG_CLK_R")] = "0"; - // new_cell->params[ctx->id("WRITE_MODE")] = "0"; - // new_cell->params[ctx->id("READ_MODE")] = "0"; - // - // add_port(ctx, new_cell.get(), "RCLK", PORT_IN); - // add_port(ctx, new_cell.get(), "RCLKE", PORT_IN); - // add_port(ctx, new_cell.get(), "RE", PORT_IN); - // - // add_port(ctx, new_cell.get(), "WCLK", PORT_IN); - // add_port(ctx, new_cell.get(), "WCLKE", PORT_IN); - // add_port(ctx, new_cell.get(), "WE", PORT_IN); - // - // for (int i = 0; i < 16; i++) { - // add_port(ctx, new_cell.get(), "WDATA_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "MASK_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "RDATA_" + std::to_string(i), PORT_OUT); - // } - // - // for (int i = 0; i < 11; i++) { - // add_port(ctx, new_cell.get(), "RADDR_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "WADDR_" + std::to_string(i), PORT_IN); - // } - // } else if (type == ctx->id("ICESTORM_LFOSC")) { - // add_port(ctx, new_cell.get(), "CLKLFEN", PORT_IN); - // add_port(ctx, new_cell.get(), "CLKLFPU", PORT_IN); - // add_port(ctx, new_cell.get(), "CLKLF", PORT_OUT); - // add_port(ctx, new_cell.get(), "CLKLF_FABRIC", PORT_OUT); - // } else if (type == ctx->id("ICESTORM_HFOSC")) { - // new_cell->params[ctx->id("CLKHF_DIV")] = "0b00"; - // new_cell->params[ctx->id("TRIM_EN")] = "0b0"; - // - // add_port(ctx, new_cell.get(), "CLKHFEN", PORT_IN); - // add_port(ctx, new_cell.get(), "CLKHFPU", PORT_IN); - // add_port(ctx, new_cell.get(), "CLKHF", PORT_OUT); - // add_port(ctx, new_cell.get(), "CLKHF_FABRIC", PORT_OUT); - // for (int i = 0; i < 10; i++) - // add_port(ctx, new_cell.get(), "TRIM" + std::to_string(i), PORT_IN); } else if (type == id_BUFGCTRL) { add_port(ctx, new_cell.get(), "I0", PORT_IN); add_port(ctx, new_cell.get(), "O", PORT_OUT); - // } else if (type == ctx->id("ICESTORM_SPRAM")) { - // add_port(ctx, new_cell.get(), "WREN", PORT_IN); - // add_port(ctx, new_cell.get(), "CHIPSELECT", PORT_IN); - // add_port(ctx, new_cell.get(), "CLOCK", PORT_IN); - // add_port(ctx, new_cell.get(), "STANDBY", PORT_IN); - // add_port(ctx, new_cell.get(), "SLEEP", PORT_IN); - // add_port(ctx, new_cell.get(), "POWEROFF", PORT_IN); - // - // for (int i = 0; i < 16; i++) { - // add_port(ctx, new_cell.get(), "DATAIN_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "DATAOUT_" + std::to_string(i), PORT_OUT); - // } - // for (int i = 0; i < 14; i++) { - // add_port(ctx, new_cell.get(), "ADDRESS_" + std::to_string(i), PORT_IN); - // } - // for (int i = 0; i < 4; i++) { - // add_port(ctx, new_cell.get(), "MASKWREN_" + std::to_string(i), PORT_IN); - // } - // } else if (type == ctx->id("ICESTORM_DSP")) { - // new_cell->params[ctx->id("NEG_TRIGGER")] = "0"; - // - // new_cell->params[ctx->id("C_REG")] = "0"; - // new_cell->params[ctx->id("A_REG")] = "0"; - // new_cell->params[ctx->id("B_REG")] = "0"; - // new_cell->params[ctx->id("D_REG")] = "0"; - // new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = "0"; - // new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = "0"; - // new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = "0"; - // new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = "0"; - // - // new_cell->params[ctx->id("TOPOUTPUT_SELECT")] = "0"; - // new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = "0"; - // new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = "0"; - // new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = "0"; - // - // new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = "0"; - // new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = "0"; - // new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = "0"; - // new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = "0"; - // - // new_cell->params[ctx->id("MODE_8x8")] = "0"; - // new_cell->params[ctx->id("A_SIGNED")] = "0"; - // new_cell->params[ctx->id("B_SIGNED")] = "0"; - // - // add_port(ctx, new_cell.get(), "CLK", PORT_IN); - // add_port(ctx, new_cell.get(), "CE", PORT_IN); - // for (int i = 0; i < 16; i++) { - // add_port(ctx, new_cell.get(), "C_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "A_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "B_" + std::to_string(i), PORT_IN); - // add_port(ctx, new_cell.get(), "D_" + std::to_string(i), PORT_IN); - // } - // add_port(ctx, new_cell.get(), "AHOLD", PORT_IN); - // add_port(ctx, new_cell.get(), "BHOLD", PORT_IN); - // add_port(ctx, new_cell.get(), "CHOLD", PORT_IN); - // add_port(ctx, new_cell.get(), "DHOLD", PORT_IN); - // - // add_port(ctx, new_cell.get(), "IRSTTOP", PORT_IN); - // add_port(ctx, new_cell.get(), "IRSTBOT", PORT_IN); - // add_port(ctx, new_cell.get(), "ORSTTOP", PORT_IN); - // add_port(ctx, new_cell.get(), "ORSTBOT", PORT_IN); - // - // add_port(ctx, new_cell.get(), "OLOADTOP", PORT_IN); - // add_port(ctx, new_cell.get(), "OLOADBOT", PORT_IN); - // - // add_port(ctx, new_cell.get(), "ADDSUBTOP", PORT_IN); - // add_port(ctx, new_cell.get(), "ADDSUBBOT", PORT_IN); - // - // add_port(ctx, new_cell.get(), "OHOLDTOP", PORT_IN); - // add_port(ctx, new_cell.get(), "OHOLDBOT", PORT_IN); - // - // add_port(ctx, new_cell.get(), "CI", PORT_IN); - // add_port(ctx, new_cell.get(), "ACCUMCI", PORT_IN); - // add_port(ctx, new_cell.get(), "SIGNEXTIN", PORT_IN); - // - // for (int i = 0; i < 32; i++) { - // add_port(ctx, new_cell.get(), "O_" + std::to_string(i), PORT_OUT); - // } - // - // add_port(ctx, new_cell.get(), "CO", PORT_OUT); - // add_port(ctx, new_cell.get(), "ACCUMCO", PORT_OUT); - // add_port(ctx, new_cell.get(), "SIGNEXTOUT", PORT_OUT); - // - // } else if (type == ctx->id("ICESTORM_PLL")) { - // new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = "0"; - // new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = "0"; - // - // new_cell->params[ctx->id("DIVF")] = "0"; - // new_cell->params[ctx->id("DIVQ")] = "0"; - // new_cell->params[ctx->id("DIVR")] = "0"; - // - // new_cell->params[ctx->id("FDA_FEEDBACK")] = "0"; - // new_cell->params[ctx->id("FDA_RELATIVE")] = "0"; - // new_cell->params[ctx->id("FEEDBACK_PATH")] = "0"; - // new_cell->params[ctx->id("FILTER_RANGE")] = "0"; - // - // new_cell->params[ctx->id("PLLOUT_SELECT_A")] = "0"; - // new_cell->params[ctx->id("PLLOUT_SELECT_B")] = "0"; - // - // new_cell->params[ctx->id("PLLTYPE")] = "0"; - // new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = "0"; - // new_cell->params[ctx->id("TEST_MODE")] = "0"; - // - // add_port(ctx, new_cell.get(), "BYPASS", PORT_IN); - // add_port(ctx, new_cell.get(), "DYNAMICDELAY", PORT_IN); - // add_port(ctx, new_cell.get(), "EXTFEEDBACK", PORT_IN); - // add_port(ctx, new_cell.get(), "LATCHINPUTVALUE", PORT_IN); - // add_port(ctx, new_cell.get(), "REFERENCECLK", PORT_IN); - // add_port(ctx, new_cell.get(), "RESETB", PORT_IN); - // - // add_port(ctx, new_cell.get(), "SCLK", PORT_IN); - // add_port(ctx, new_cell.get(), "SDI", PORT_IN); - // add_port(ctx, new_cell.get(), "SDI", PORT_OUT); - // - // add_port(ctx, new_cell.get(), "LOCK", PORT_OUT); - // add_port(ctx, new_cell.get(), "PLLOUT_A", PORT_OUT); - // add_port(ctx, new_cell.get(), "PLLOUT_B", PORT_OUT); } else { log_error("unable to create XC7 cell of type %s\n", type.c_str(ctx)); } @@ -390,34 +215,11 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio) } } -uint8_t sb_pll40_type(const BaseCtx *ctx, const CellInfo *cell) -{ - if (cell->type == ctx->id("SB_PLL40_PAD")) - return 2; - if (cell->type == ctx->id("SB_PLL40_2_PAD")) - return 4; - if (cell->type == ctx->id("SB_PLL40_2F_PAD")) - return 5; - if (cell->type == ctx->id("SB_PLL40_CORE")) - return 3; - if (cell->type == ctx->id("SB_PLL40_2F_CORE")) - return 7; - NPNR_ASSERT(0); -} - bool is_clock_port(const BaseCtx *ctx, const PortRef &port) { if (port.cell == nullptr) return false; - if (is_ff(ctx, port.cell)) - return port.port == ctx->id("C"); - if (port.cell->type == ctx->id("ICESTORM_LC")) - return port.port == id_CLK; - if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM")) - return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK") || port.port == ctx->id("RCLKN") || - port.port == ctx->id("WCLKN"); - if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) - return port.port == id_CLK; + NPNR_ASSERT("TODO"); return false; } @@ -425,13 +227,7 @@ bool is_reset_port(const BaseCtx *ctx, const PortRef &port) { if (port.cell == nullptr) return false; - if (is_ff(ctx, port.cell)) - return port.port == id_R || port.port == id_S; - if (port.cell->type == ctx->id("ICESTORM_LC")) - return port.port == id_SR; - if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) - return port.port == ctx->id("IRSTTOP") || port.port == ctx->id("IRSTBOT") || port.port == ctx->id("ORSTTOP") || - port.port == ctx->id("ORSTBOT"); + NPNR_ASSERT("TODO"); return false; } @@ -439,13 +235,7 @@ bool is_enable_port(const BaseCtx *ctx, const PortRef &port) { if (port.cell == nullptr) return false; - if (is_ff(ctx, port.cell)) - return port.port == ctx->id("E"); - if (port.cell->type == ctx->id("ICESTORM_LC")) - return port.port == id_CEN; - // FIXME - // if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) - // return port.port == ctx->id("CE"); + NPNR_ASSERT("TODO"); return false; } diff --git a/xc7/delay.cc b/xc7/delay.cc index 8b8b0ae7..67f96b98 100644 --- a/xc7/delay.cc +++ b/xc7/delay.cc @@ -25,79 +25,6 @@ NEXTPNR_NAMESPACE_BEGIN #define NUM_FUZZ_ROUTES 100000 -void ice40DelayFuzzerMain(Context *ctx) -{ - // std::vector srcWires, dstWires; - // - // for (int i = 0; i < ctx->chip_info->num_wires; i++) { - // WireId wire; - // wire.index = i; - // - // switch (ctx->chip_info->wire_data[i].type) { - // case WireInfoPOD::WIRE_TYPE_LUTFF_OUT: - // srcWires.push_back(wire); - // break; - // - // case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT: - // dstWires.push_back(wire); - // break; - // - // default: - // break; - // } - // } - // - // ctx->shuffle(srcWires); - // ctx->shuffle(dstWires); - // - // int index = 0; - // int cnt = 0; - // - // while (cnt < NUM_FUZZ_ROUTES) { - // if (index >= int(srcWires.size()) || index >= int(dstWires.size())) { - // index = 0; - // ctx->shuffle(srcWires); - // ctx->shuffle(dstWires); - // } - // - // WireId src = srcWires[index]; - // WireId dst = dstWires[index++]; - // std::unordered_map route; - // - //#if NUM_FUZZ_ROUTES <= 1000 - // if (!ctx->getActualRouteDelay(src, dst, nullptr, &route, false)) - // continue; - //#else - // if (!ctx->getActualRouteDelay(src, dst, nullptr, &route, true)) - // continue; - //#endif - // - // WireId cursor = dst; - // delay_t delay = 0; - // - // while (1) { - // delay += ctx->getWireDelay(cursor).maxDelay(); - // - // printf("%s %d %d %s %s %d %d\n", cursor == dst ? "dst" : "src", - // int(ctx->chip_info->wire_data[cursor.index].x), int(ctx->chip_info->wire_data[cursor.index].y), - // ctx->getWireType(cursor).c_str(ctx), ctx->getWireName(cursor).c_str(ctx), int(delay), - // int(ctx->estimateDelay(cursor, dst))); - // - // if (cursor == src) - // break; - // - // PipId pip = route.at(cursor); - // delay += ctx->getPipDelay(pip).maxDelay(); - // cursor = ctx->getPipSrcWire(pip); - // } - // - // cnt++; - // - // if (cnt % 100 == 0) - // fprintf(stderr, "Fuzzed %d arcs.\n", cnt); - // } -} - delay_t Arch::estimateDelay(WireId src, WireId dst) const { const auto &src_tw = torc_info->wire_to_tilewire[src.index]; diff --git a/xc7/pack.cc b/xc7/pack.cc index 14ec4fe7..a4b57f2a 100644 --- a/xc7/pack.cc +++ b/xc7/pack.cc @@ -128,172 +128,15 @@ static bool net_is_constant(const Context *ctx, NetInfo *net, bool &value) // Pack carry logic static void pack_carries(Context *ctx) { - log_info("Packing carries..\n"); - std::unordered_set exhausted_cells; - std::unordered_set packed_cells; - std::vector> new_cells; - - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; - if (is_carry(ctx, ci)) { - packed_cells.insert(cell.first); - - CellInfo *carry_ci_lc; - bool ci_value; - bool ci_const = net_is_constant(ctx, ci->ports.at(ctx->id("CI")).net, ci_value); - if (ci_const) { - carry_ci_lc = nullptr; - } else { - carry_ci_lc = net_only_drives(ctx, ci->ports.at(ctx->id("CI")).net, is_lc, ctx->id("I3"), false); - } - - std::set i0_matches, i1_matches; - NetInfo *i0_net = ci->ports.at(ctx->id("I0")).net; - NetInfo *i1_net = ci->ports.at(ctx->id("I1")).net; - // Find logic cells connected to both I0 and I1 - if (i0_net) { - for (auto usr : i0_net->users) { - if (is_lc(ctx, usr.cell) && usr.port == ctx->id("I1")) { - if (ctx->cells.find(usr.cell->name) != ctx->cells.end() && - exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) { - // This clause stops us double-packing cells - i0_matches.insert(usr.cell->name); - if (!i1_net) { - // I1 is don't care when disconnected, duplicate I0 - i1_matches.insert(usr.cell->name); - } - } - } - } - } - if (i1_net) { - for (auto usr : i1_net->users) { - if (is_lc(ctx, usr.cell) && usr.port == ctx->id("I2")) { - if (ctx->cells.find(usr.cell->name) != ctx->cells.end() && - exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) { - // This clause stops us double-packing cells - i1_matches.insert(usr.cell->name); - if (!i0_net) { - // I0 is don't care when disconnected, duplicate I1 - i0_matches.insert(usr.cell->name); - } - } - } - } - } - - std::set carry_lcs; - std::set_intersection(i0_matches.begin(), i0_matches.end(), i1_matches.begin(), i1_matches.end(), - std::inserter(carry_lcs, carry_lcs.end())); - CellInfo *carry_lc = nullptr; - if (carry_ci_lc && carry_lcs.find(carry_ci_lc->name) != carry_lcs.end()) { - carry_lc = carry_ci_lc; - } else { - // No LC to pack into matching I0/I1, insert a new one - std::unique_ptr created_lc = - create_xc7_cell(ctx, ctx->id("XC7_LC"), cell.first.str(ctx) + "$CARRY"); - carry_lc = created_lc.get(); - created_lc->ports.at(ctx->id("I1")).net = i0_net; - if (i0_net) { - PortRef pr; - pr.cell = created_lc.get(); - pr.port = ctx->id("I1"); - i0_net->users.push_back(pr); - } - created_lc->ports.at(ctx->id("I2")).net = i1_net; - if (i1_net) { - PortRef pr; - pr.cell = created_lc.get(); - pr.port = ctx->id("I2"); - i1_net->users.push_back(pr); - } - new_cells.push_back(std::move(created_lc)); - } - carry_lc->params[ctx->id("CARRY_ENABLE")] = "1"; - replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN")); - replace_port(ci, ctx->id("CO"), carry_lc, ctx->id("COUT")); - if (i0_net) { - auto &i0_usrs = i0_net->users; - i0_usrs.erase(std::remove_if(i0_usrs.begin(), i0_usrs.end(), [ci, ctx](const PortRef &pr) { - return pr.cell == ci && pr.port == ctx->id("I0"); - })); - } - if (i1_net) { - auto &i1_usrs = i1_net->users; - i1_usrs.erase(std::remove_if(i1_usrs.begin(), i1_usrs.end(), [ci, ctx](const PortRef &pr) { - return pr.cell == ci && pr.port == ctx->id("I1"); - })); - } - - // Check for constant driver on CIN - if (carry_lc->ports.at(ctx->id("CIN")).net != nullptr) { - IdString cin_net = carry_lc->ports.at(ctx->id("CIN")).net->name; - if (cin_net == ctx->id("$PACKER_GND_NET") || cin_net == ctx->id("$PACKER_VCC_NET")) { - carry_lc->params[ctx->id("CIN_CONST")] = "1"; - carry_lc->params[ctx->id("CIN_SET")] = cin_net == ctx->id("$PACKER_VCC_NET") ? "1" : "0"; - carry_lc->ports.at(ctx->id("CIN")).net = nullptr; - auto &cin_users = ctx->nets.at(cin_net)->users; - cin_users.erase( - std::remove_if(cin_users.begin(), cin_users.end(), [carry_lc, ctx](const PortRef &pr) { - return pr.cell == carry_lc && pr.port == ctx->id("CIN"); - })); - } - } - exhausted_cells.insert(carry_lc->name); - } - } - for (auto pcell : packed_cells) { - ctx->cells.erase(pcell); - } - for (auto &ncell : new_cells) { - ctx->cells[ncell->name] = std::move(ncell); - } + //log_info("Packing carries..\n"); + // TODO } // "Pack" RAMs static void pack_ram(Context *ctx) { - log_info("Packing RAMs..\n"); - - std::unordered_set packed_cells; - std::vector> new_cells; - - for (auto cell : sorted(ctx->cells)) { - CellInfo *ci = cell.second; - if (is_ram(ctx, ci)) { - std::unique_ptr packed = - create_xc7_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM"); - packed_cells.insert(ci->name); - for (auto param : ci->params) - packed->params[param.first] = param.second; - packed->params[ctx->id("NEG_CLK_W")] = - std::to_string(ci->type == ctx->id("SB_RAM40_4KNW") || ci->type == ctx->id("SB_RAM40_4KNRNW")); - packed->params[ctx->id("NEG_CLK_R")] = - std::to_string(ci->type == ctx->id("SB_RAM40_4KNR") || ci->type == ctx->id("SB_RAM40_4KNRNW")); - packed->type = ctx->id("ICESTORM_RAM"); - for (auto port : ci->ports) { - PortInfo &pi = port.second; - std::string newname = pi.name.str(ctx); - size_t bpos = newname.find('['); - if (bpos != std::string::npos) { - newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); - } - if (pi.name == ctx->id("RCLKN")) - newname = "RCLK"; - else if (pi.name == ctx->id("WCLKN")) - newname = "WCLK"; - replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); - } - new_cells.push_back(std::move(packed)); - } - } - - for (auto pcell : packed_cells) { - ctx->cells.erase(pcell); - } - for (auto &ncell : new_cells) { - ctx->cells[ncell->name] = std::move(ncell); - } + //log_info("Packing RAMs..\n"); + // TODO } // Merge a net into a constant net @@ -308,14 +151,6 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne if ((is_lut(ctx, uc) || is_lc(ctx, uc) || is_carry(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') && !constval) { uc->ports[user.port].net = nullptr; - } else if ((is_sb_mac16(ctx, uc) || uc->type == ctx->id("ICESTORM_DSP")) && - (user.port != id_CLK && - ((constval && user.port == ctx->id("CE")) || (!constval && user.port != ctx->id("CE"))))) { - uc->ports[user.port].net = nullptr; - } else if (is_ram(ctx, uc) && !constval && user.port != ctx->id("RCLK") && user.port != ctx->id("RCLKN") && - user.port != ctx->id("WCLK") && user.port != ctx->id("WCLKN") && user.port != ctx->id("RCLKE") && - user.port != ctx->id("WCLKE")) { - uc->ports[user.port].net = nullptr; } else { uc->ports[user.port].net = constnet; constnet->users.push_back(user); @@ -421,9 +256,9 @@ static void pack_io(Context *ctx) } } else { // Create a IOBUF buffer - std::unique_ptr ice_cell = create_xc7_cell(ctx, ctx->id("IOBUF"), ci->name.str(ctx)); - nxio_to_sb(ctx, ci, ice_cell.get()); - new_cells.push_back(std::move(ice_cell)); + std::unique_ptr xc7_cell = create_xc7_cell(ctx, ctx->id("IOBUF"), ci->name.str(ctx)); + nxio_to_sb(ctx, ci, xc7_cell.get()); + new_cells.push_back(std::move(xc7_cell)); sb = new_cells.back().get(); } packed_cells.insert(ci->name); @@ -443,8 +278,7 @@ static bool is_logic_port(BaseCtx *ctx, const PortRef &port) { if (is_clock_port(ctx, port) || is_reset_port(ctx, port) || is_enable_port(ctx, port)) return false; - return !is_sb_io(ctx, port.cell) && !is_sb_pll40(ctx, port.cell) && !is_sb_pll40_pad(ctx, port.cell) && - port.cell->type != ctx->id("SB_GB"); + return !is_sb_io(ctx, port.cell) && port.cell->type != id_BUFGCTRL; } static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen, bool is_logic) @@ -855,242 +689,6 @@ static void pack_special(Context *ctx) ci->params.emplace(ctx->id("VREF_START"), "01"); ci->params[ctx->id("COMPENSATION")] = "INTERNAL"; - } else if (is_sb_lfosc(ctx, ci)) { - std::unique_ptr packed = - create_xc7_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC"); - packed_cells.insert(ci->name); - replace_port(ci, ctx->id("CLKLFEN"), packed.get(), ctx->id("CLKLFEN")); - replace_port(ci, ctx->id("CLKLFPU"), packed.get(), ctx->id("CLKLFPU")); - if (/*bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))*/ true) { // FIXME - replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF_FABRIC")); - } else { - replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF")); - } - new_cells.push_back(std::move(packed)); - } else if (is_sb_hfosc(ctx, ci)) { - std::unique_ptr packed = - create_xc7_cell(ctx, ctx->id("ICESTORM_HFOSC"), ci->name.str(ctx) + "_OSC"); - packed_cells.insert(ci->name); - packed->params[ctx->id("CLKHF_DIV")] = str_or_default(ci->params, ctx->id("CLKHF_DIV"), "0b00"); - replace_port(ci, ctx->id("CLKHFEN"), packed.get(), ctx->id("CLKHFEN")); - replace_port(ci, ctx->id("CLKHFPU"), packed.get(), ctx->id("CLKHFPU")); - if (/*bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))*/ true) { // FIXME - replace_port(ci, ctx->id("CLKHF"), packed.get(), ctx->id("CLKHF_FABRIC")); - } else { - replace_port(ci, ctx->id("CLKHF"), packed.get(), ctx->id("CLKHF")); - } - new_cells.push_back(std::move(packed)); - } else if (is_sb_spram(ctx, ci)) { - std::unique_ptr packed = - create_xc7_cell(ctx, ctx->id("ICESTORM_SPRAM"), ci->name.str(ctx) + "_RAM"); - packed_cells.insert(ci->name); - for (auto port : ci->ports) { - PortInfo &pi = port.second; - std::string newname = pi.name.str(ctx); - size_t bpos = newname.find('['); - if (bpos != std::string::npos) { - newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); - } - replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); - } - new_cells.push_back(std::move(packed)); - } else if (is_sb_mac16(ctx, ci)) { - std::unique_ptr packed = - create_xc7_cell(ctx, ctx->id("ICESTORM_DSP"), ci->name.str(ctx) + "_DSP"); - packed_cells.insert(ci->name); - for (auto attr : ci->attrs) - packed->attrs[attr.first] = attr.second; - for (auto param : ci->params) - packed->params[param.first] = param.second; - - for (auto port : ci->ports) { - PortInfo &pi = port.second; - std::string newname = pi.name.str(ctx); - size_t bpos = newname.find('['); - if (bpos != std::string::npos) { - newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); - } - replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); - } - new_cells.push_back(std::move(packed)); - } else if (is_sb_pll40(ctx, ci)) { - bool is_pad = is_sb_pll40_pad(ctx, ci); - bool is_core = !is_pad; - - std::unique_ptr packed = - create_xc7_cell(ctx, ctx->id("ICESTORM_PLL"), ci->name.str(ctx) + "_PLL"); - packed->attrs[ctx->id("TYPE")] = ci->type.str(ctx); - packed_cells.insert(ci->name); - - for (auto attr : ci->attrs) - packed->attrs[attr.first] = attr.second; - for (auto param : ci->params) - packed->params[param.first] = param.second; - - auto feedback_path = packed->params[ctx->id("FEEDBACK_PATH")]; - packed->params[ctx->id("FEEDBACK_PATH")] = - feedback_path == "DELAY" - ? "0" - : feedback_path == "SIMPLE" ? "1" - : feedback_path == "PHASE_AND_DELAY" - ? "2" - : feedback_path == "EXTERNAL" ? "6" : feedback_path; - packed->params[ctx->id("PLLTYPE")] = std::to_string(sb_pll40_type(ctx, ci)); - - NetInfo *pad_packagepin_net = nullptr; - - for (auto port : ci->ports) { - PortInfo &pi = port.second; - std::string newname = pi.name.str(ctx); - size_t bpos = newname.find('['); - if (bpos != std::string::npos) { - newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); - } - if (pi.name == ctx->id("PLLOUTCOREA")) - newname = "PLLOUT_A"; - if (pi.name == ctx->id("PLLOUTCOREB")) - newname = "PLLOUT_B"; - if (pi.name == ctx->id("PLLOUTCORE")) - newname = "PLLOUT_A"; - - if (pi.name == ctx->id("PACKAGEPIN")) { - if (!is_pad) { - log_error(" PLL '%s' has a PACKAGEPIN but is not a PAD PLL", ci->name.c_str(ctx)); - } else { - // We drop this port and instead place the PLL adequately below. - pad_packagepin_net = port.second.net; - NPNR_ASSERT(pad_packagepin_net != nullptr); - continue; - } - } - if (pi.name == ctx->id("REFERENCECLK")) { - if (!is_core) - log_error(" PLL '%s' has a REFERENCECLK but is not a CORE PLL", ci->name.c_str(ctx)); - } - - replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); - } - - // If PLL is not constrained already, do that - we need this - // information to then constrain the LOCK LUT. - BelId pll_bel; - bool constrained = false; - if (packed->attrs.find(ctx->id("BEL")) == packed->attrs.end()) { - for (auto bel : ctx->getBels()) { - if (ctx->getBelType(bel) != id_ICESTORM_PLL) - continue; - - // A PAD PLL must have its' PACKAGEPIN on the SB_IO that's shared - // with PLLOUT_A. - if (is_pad) { - auto pll_sb_io_belpin = ctx->getIOBSharingPLLPin(bel, id_PLLOUT_A); - NPNR_ASSERT(pad_packagepin_net != nullptr); - auto pll_packagepin_driver = pad_packagepin_net->driver; - NPNR_ASSERT(pll_packagepin_driver.cell != nullptr); - if (pll_packagepin_driver.cell->type != ctx->id("SB_IO")) { - log_error(" PLL '%s' has a PACKAGEPIN driven by " - "an %s, should be directly connected to an input SB_IO\n", - ci->name.c_str(ctx), pll_packagepin_driver.cell->type.c_str(ctx)); - } - - auto packagepin_cell = pll_packagepin_driver.cell; - auto packagepin_bel_name = packagepin_cell->attrs.find(ctx->id("BEL")); - if (packagepin_bel_name == packagepin_cell->attrs.end()) { - log_error(" PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx), - packagepin_cell->name.c_str(ctx)); - } - auto packagepin_bel = ctx->getBelByName(ctx->id(packagepin_bel_name->second)); - if (pll_sb_io_belpin.bel != packagepin_bel) { - log_error(" PLL '%s' PACKAGEPIN is connected to pin %s, can only be pin %s\n", - ci->name.c_str(ctx), ctx->getBelPackagePin(packagepin_bel).c_str(), - ctx->getBelPackagePin(pll_sb_io_belpin.bel).c_str()); - } - if (pad_packagepin_net->users.size() != 1) { - log_error(" PLL '%s' clock input '%s' can only drive PLL\n", ci->name.c_str(ctx), - pad_packagepin_net->name.c_str(ctx)); - } - // Set an attribute about this PLL's PAD SB_IO. - packed->attrs[ctx->id("BEL_PAD_INPUT")] = packagepin_bel_name->second; - // Remove the connection from the SB_IO to the PLL. - packagepin_cell->ports.erase(pll_packagepin_driver.port); - } - - log_info(" constrained '%s' to %s\n", packed->name.c_str(ctx), ctx->getBelName(bel).c_str(ctx)); - packed->attrs[ctx->id("BEL")] = ctx->getBelName(bel).str(ctx); - pll_bel = bel; - constrained = true; - } - if (!constrained) { - log_error(" could not constrain '%s' to any PLL Bel\n", packed->name.c_str(ctx)); - } - } - - // Delete the original PACKAGEPIN net if needed. - if (pad_packagepin_net != nullptr) { - for (auto user : pad_packagepin_net->users) { - user.cell->ports.erase(user.port); - } - ctx->nets.erase(pad_packagepin_net->name); - pad_packagepin_net = nullptr; - } - - // The LOCK signal on iCE40 PLLs goes through the neigh_op_bnl_1 wire. - // In practice, this means the LOCK signal can only directly reach LUT - // inputs. - // If we have a net connected to LOCK, make sure it only drives LUTs. - auto port = packed->ports[ctx->id("LOCK")]; - if (port.net != nullptr) { - bool found_lut = false; - bool all_luts = true; - unsigned int lut_count = 0; - for (const auto &user : port.net->users) { - NPNR_ASSERT(user.cell != nullptr); - if (user.cell->type == ctx->id("XC7_LC")) { - found_lut = true; - lut_count++; - } else { - all_luts = false; - } - } - - if (found_lut && all_luts) { - // Every user is a LUT, carry on now. - } else if (found_lut && !all_luts && lut_count < 8) { - // Strategy: create a pass-through LUT, move all non-LUT users behind it. - log_info(" LUT strategy for %s: move non-LUT users to new LUT\n", port.name.c_str(ctx)); - auto pt = spliceLUT(ctx, packed.get(), port.name, true); - new_cells.push_back(std::move(pt)); - } else { - // Strategy: create a pass-through LUT, move every user behind it. - log_info(" LUT strategy for %s: move all users to new LUT\n", port.name.c_str(ctx)); - auto pt = spliceLUT(ctx, packed.get(), port.name, false); - new_cells.push_back(std::move(pt)); - } - - // Find wire that will be driven by this port. - const auto pll_out_wire = ctx->getBelPinWire(pll_bel, port.name); - NPNR_ASSERT(pll_out_wire != WireId()); - - // Now, constrain all LUTs on the output of the signal to be at - // the correct Bel relative to the PLL Bel. - // int x = ctx->chip_info->wire_data[pll_out_wire.index].x; - // int y = ctx->chip_info->wire_data[pll_out_wire.index].y; - // int z = 0; - // for (const auto &user : port.net->users) { - // NPNR_ASSERT(user.cell != nullptr); - // NPNR_ASSERT(user.cell->type == ctx->id("XC7_LC")); - - // // TODO(q3k): handle when the Bel might be already the - // // target of another constraint. - // NPNR_ASSERT(z < 8); - // auto target_bel = ctx->getBelByLocation(Loc(x, y, z++)); - // auto target_bel_name = ctx->getBelName(target_bel).str(ctx); - // user.cell->attrs[ctx->id("BEL")] = target_bel_name; - // log_info(" constrained '%s' to %s\n", user.cell->name.c_str(ctx), target_bel_name.c_str()); - //} - } - - new_cells.push_back(std::move(packed)); } }