machxo2: Update with Arch API changes
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
32433db7ae
commit
3f7618283d
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@
|
|||||||
/nextpnr-nexus*
|
/nextpnr-nexus*
|
||||||
/nextpnr-fpga_interchange*
|
/nextpnr-fpga_interchange*
|
||||||
/nextpnr-gowin*
|
/nextpnr-gowin*
|
||||||
|
/nextpnr-machxo2*
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
Makefile
|
Makefile
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
|
@ -39,9 +39,8 @@ namespace std {
|
|||||||
|
|
||||||
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString>>
|
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString>>
|
||||||
{
|
{
|
||||||
std::size_t
|
std::size_t operator()(
|
||||||
operator()(const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const
|
const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const noexcept
|
||||||
noexcept
|
|
||||||
{
|
{
|
||||||
std::size_t seed = 0;
|
std::size_t seed = 0;
|
||||||
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(idp.first));
|
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(idp.first));
|
||||||
@ -61,7 +60,7 @@ template <> struct hash<std::pair<int, NEXTPNR_NAMESPACE_PREFIX BelId>>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !(defined(ARCH_GENERIC) || defined(ARCH_MACHXO2) || defined(ARCH_GOWIN))
|
#if !(defined(ARCH_GENERIC) || defined(ARCH_GOWIN))
|
||||||
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId>>
|
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX BelId>>
|
||||||
{
|
{
|
||||||
std::size_t
|
std::size_t
|
||||||
|
1
machxo2/.gitignore
vendored
Normal file
1
machxo2/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
chipdb/
|
105
machxo2/arch.cc
105
machxo2/arch.cc
@ -100,7 +100,8 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
if (!package_info)
|
if (!package_info)
|
||||||
log_error("Unsupported package '%s' for '%s'.\n", args.package.c_str(), getChipName().c_str());
|
log_error("Unsupported package '%s' for '%s'.\n", args.package.c_str(), getChipName().c_str());
|
||||||
|
|
||||||
bel_to_cell.resize(chip_info->height * chip_info->width * max_loc_bels, nullptr);
|
BaseArch::init_cell_types();
|
||||||
|
BaseArch::init_bel_buckets();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip) { return get_chip_info(chip) != nullptr; }
|
bool Arch::isAvailable(ArchArgs::ArchArgsTypes chip) { return get_chip_info(chip) != nullptr; }
|
||||||
@ -172,16 +173,18 @@ IdString Arch::archArgsToId(ArchArgs args) const
|
|||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
BelId Arch::getBelByName(IdString name) const
|
BelId Arch::getBelByName(IdStringList name) const
|
||||||
{
|
{
|
||||||
BelId ret;
|
BelId ret;
|
||||||
auto it = bel_by_name.find(name);
|
IdString name_id = name[0];
|
||||||
|
|
||||||
|
auto it = bel_by_name.find(name_id);
|
||||||
if (it != bel_by_name.end())
|
if (it != bel_by_name.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
Location loc;
|
Location loc;
|
||||||
std::string basename;
|
std::string basename;
|
||||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
|
std::tie(loc.x, loc.y, basename) = split_identifier_name(name_id.str(this));
|
||||||
ret.location = loc;
|
ret.location = loc;
|
||||||
const TileTypePOD *tilei = tileInfo(ret);
|
const TileTypePOD *tilei = tileInfo(ret);
|
||||||
for (int i = 0; i < tilei->num_bels; i++) {
|
for (int i = 0; i < tilei->num_bels; i++) {
|
||||||
@ -191,7 +194,7 @@ BelId Arch::getBelByName(IdString name) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret.index >= 0)
|
if (ret.index >= 0)
|
||||||
bel_by_name[name] = ret;
|
bel_by_name[name_id] = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,17 +306,18 @@ BelId Arch::getPackagePinBel(const std::string &pin) const
|
|||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
WireId Arch::getWireByName(IdString name) const
|
WireId Arch::getWireByName(IdStringList name) const
|
||||||
{
|
{
|
||||||
WireId ret;
|
WireId ret;
|
||||||
|
IdString name_id = name[0];
|
||||||
|
|
||||||
auto it = wire_by_name.find(name);
|
auto it = wire_by_name.find(name_id);
|
||||||
if (it != wire_by_name.end())
|
if (it != wire_by_name.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
Location loc;
|
Location loc;
|
||||||
std::string basename;
|
std::string basename;
|
||||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
|
std::tie(loc.x, loc.y, basename) = split_identifier_name(name_id.str(this));
|
||||||
ret.location = loc;
|
ret.location = loc;
|
||||||
|
|
||||||
const TileTypePOD *tilei = tileInfo(ret);
|
const TileTypePOD *tilei = tileInfo(ret);
|
||||||
@ -324,23 +328,24 @@ WireId Arch::getWireByName(IdString name) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret.index >= 0)
|
if (ret.index >= 0)
|
||||||
wire_by_name[name] = ret;
|
wire_by_name[name_id] = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
PipId Arch::getPipByName(IdString name) const
|
PipId Arch::getPipByName(IdStringList name) const
|
||||||
{
|
{
|
||||||
PipId ret;
|
PipId ret;
|
||||||
|
IdString name_id = name[0];
|
||||||
|
|
||||||
auto it = pip_by_name.find(name);
|
auto it = pip_by_name.find(name_id);
|
||||||
if (it != pip_by_name.end())
|
if (it != pip_by_name.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
Location loc;
|
Location loc;
|
||||||
std::string basename;
|
std::string basename;
|
||||||
std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
|
std::tie(loc.x, loc.y, basename) = split_identifier_name(name_id.str(this));
|
||||||
ret.location = loc;
|
ret.location = loc;
|
||||||
|
|
||||||
const TileTypePOD *tilei = tileInfo(ret);
|
const TileTypePOD *tilei = tileInfo(ret);
|
||||||
@ -348,51 +353,31 @@ PipId Arch::getPipByName(IdString name) const
|
|||||||
PipId curr;
|
PipId curr;
|
||||||
curr.location = loc;
|
curr.location = loc;
|
||||||
curr.index = i;
|
curr.index = i;
|
||||||
pip_by_name[getPipName(curr)] = curr;
|
pip_by_name[getPipName(curr)[0]] = curr;
|
||||||
}
|
}
|
||||||
if (pip_by_name.find(name) == pip_by_name.end())
|
if (pip_by_name.find(name_id) == pip_by_name.end())
|
||||||
NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this));
|
NPNR_ASSERT_FALSE_STR("no pip named " + name_id.str(this));
|
||||||
return pip_by_name[name];
|
return pip_by_name[name_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString Arch::getPipName(PipId pip) const
|
IdStringList Arch::getPipName(PipId pip) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
|
|
||||||
int x = pip.location.x;
|
int x = pip.location.x;
|
||||||
int y = pip.location.y;
|
int y = pip.location.y;
|
||||||
|
|
||||||
std::string src_name = getWireName(getPipSrcWire(pip)).str(this);
|
std::string src_name = getWireName(getPipSrcWire(pip)).str(getCtx());
|
||||||
std::replace(src_name.begin(), src_name.end(), '/', '.');
|
std::replace(src_name.begin(), src_name.end(), '/', '.');
|
||||||
|
|
||||||
std::string dst_name = getWireName(getPipDstWire(pip)).str(this);
|
std::string dst_name = getWireName(getPipDstWire(pip)).str(getCtx());
|
||||||
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
|
std::replace(dst_name.begin(), dst_name.end(), '/', '.');
|
||||||
|
|
||||||
return id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name);
|
return IdStringList(id("X" + std::to_string(x) + "/Y" + std::to_string(y) + "/" + src_name + ".->." + dst_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
GroupId Arch::getGroupByName(IdString name) const { return GroupId(); }
|
|
||||||
|
|
||||||
IdString Arch::getGroupName(GroupId group) const { return IdString(); }
|
|
||||||
|
|
||||||
std::vector<GroupId> Arch::getGroups() const
|
|
||||||
{
|
|
||||||
std::vector<GroupId> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<BelId> &Arch::getGroupBels(GroupId group) const { return bel_id_dummy; }
|
|
||||||
|
|
||||||
const std::vector<WireId> &Arch::getGroupWires(GroupId group) const { return wire_id_dummy; }
|
|
||||||
|
|
||||||
const std::vector<PipId> &Arch::getGroupPips(GroupId group) const { return pip_id_dummy; }
|
|
||||||
|
|
||||||
const std::vector<GroupId> &Arch::getGroupGroups(GroupId group) const { return group_id_dummy; }
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
delay_t Arch::estimateDelay(WireId src, WireId dst) const
|
delay_t Arch::estimateDelay(WireId src, WireId dst) const
|
||||||
{
|
{
|
||||||
// Taxicab distance multiplied by pipDelay (0.01) and fake wireDelay (0.01).
|
// Taxicab distance multiplied by pipDelay (0.01) and fake wireDelay (0.01).
|
||||||
@ -413,8 +398,6 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
|
|||||||
return (abs(dst.location.x - src.location.x) + abs(dst.location.y - src.location.y)) * (0.01 + 0.01);
|
return (abs(dst.location.x - src.location.x) + abs(dst.location.y - src.location.y)) * (0.01 + 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; }
|
|
||||||
|
|
||||||
ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
|
ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
|
||||||
{
|
{
|
||||||
ArcBounds bb;
|
ArcBounds bb;
|
||||||
@ -432,6 +415,13 @@ bool Arch::place()
|
|||||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||||
archInfoToAttributes();
|
archInfoToAttributes();
|
||||||
return retVal;
|
return retVal;
|
||||||
|
} else if (placer == "heap") {
|
||||||
|
PlacerHeapCfg cfg(getCtx());
|
||||||
|
cfg.ioBufTypes.insert(id_FACADE_IO);
|
||||||
|
bool retVal = placer_heap(getCtx(), cfg);
|
||||||
|
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||||
|
archInfoToAttributes();
|
||||||
|
return retVal;
|
||||||
} else {
|
} else {
|
||||||
log_error("MachXO2 architecture does not support placer '%s'\n", placer.c_str());
|
log_error("MachXO2 architecture does not support placer '%s'\n", placer.c_str());
|
||||||
}
|
}
|
||||||
@ -455,35 +445,6 @@ bool Arch::route()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const { return graphic_element_dummy; }
|
|
||||||
|
|
||||||
DecalXY Arch::getBelDecal(BelId bel) const { return DecalXY(); }
|
|
||||||
|
|
||||||
DecalXY Arch::getWireDecal(WireId wire) const { return DecalXY(); }
|
|
||||||
|
|
||||||
DecalXY Arch::getPipDecal(PipId pip) const { return DecalXY(); }
|
|
||||||
|
|
||||||
DecalXY Arch::getGroupDecal(GroupId group) const { return DecalXY(); }
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the port class, also setting clockPort if applicable
|
|
||||||
TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const
|
|
||||||
{
|
|
||||||
return TMG_IGNORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
|
|
||||||
{
|
|
||||||
return TimingClockingInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
|
bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
|
||||||
{
|
{
|
||||||
// FIXME: Unlike ECP5, SLICEs in a given tile do not share a clock, so
|
// FIXME: Unlike ECP5, SLICEs in a given tile do not share a clock, so
|
||||||
@ -514,8 +475,6 @@ const std::vector<std::string> Arch::availablePlacers = {"sa",
|
|||||||
const std::string Arch::defaultRouter = "router1";
|
const std::string Arch::defaultRouter = "router1";
|
||||||
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
||||||
|
|
||||||
void Arch::assignArchInfo() {}
|
|
||||||
|
|
||||||
bool Arch::cellsCompatible(const CellInfo **cells, int count) const { return false; }
|
bool Arch::cellsCompatible(const CellInfo **cells, int count) const { return false; }
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> Arch::getTilesAtLocation(int row, int col)
|
std::vector<std::pair<std::string, std::string>> Arch::getTilesAtLocation(int row, int col)
|
||||||
|
426
machxo2/arch.h
426
machxo2/arch.h
@ -377,109 +377,31 @@ struct ArchArgs
|
|||||||
} speed = SPEED_4;
|
} speed = SPEED_4;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WireInfo;
|
struct ArchRanges : BaseArchRanges
|
||||||
|
|
||||||
struct PipInfo
|
|
||||||
{
|
{
|
||||||
IdString name, type;
|
using ArchArgsT = ArchArgs;
|
||||||
std::map<IdString, std::string> attrs;
|
// Bels
|
||||||
NetInfo *bound_net;
|
using AllBelsRangeT = BelRange;
|
||||||
WireId srcWire, dstWire;
|
using TileBelsRangeT = BelRange;
|
||||||
DelayInfo delay;
|
using BelPinsRangeT = std::vector<IdString>;
|
||||||
DecalXY decalxy;
|
// Wires
|
||||||
Loc loc;
|
using AllWiresRangeT = WireRange;
|
||||||
|
using DownhillPipRangeT = PipRange;
|
||||||
|
using UphillPipRangeT = PipRange;
|
||||||
|
using WireBelPinRangeT = BelPinRange;
|
||||||
|
// Pips
|
||||||
|
using AllPipsRangeT = AllPipRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WireInfo
|
struct Arch : BaseArch<ArchRanges>
|
||||||
{
|
|
||||||
IdString name, type;
|
|
||||||
std::map<IdString, std::string> attrs;
|
|
||||||
NetInfo *bound_net;
|
|
||||||
std::vector<PipId> downhill, uphill, aliases;
|
|
||||||
BelPin uphill_bel_pin;
|
|
||||||
std::vector<BelPin> downhill_bel_pins;
|
|
||||||
std::vector<BelPin> bel_pins;
|
|
||||||
DecalXY decalxy;
|
|
||||||
int x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PinInfo
|
|
||||||
{
|
|
||||||
IdString name;
|
|
||||||
WireId wire;
|
|
||||||
PortType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BelInfo
|
|
||||||
{
|
|
||||||
IdString name, type;
|
|
||||||
std::map<IdString, std::string> attrs;
|
|
||||||
CellInfo *bound_cell;
|
|
||||||
std::unordered_map<IdString, PinInfo> pins;
|
|
||||||
DecalXY decalxy;
|
|
||||||
int x, y, z;
|
|
||||||
bool gb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GroupInfo
|
|
||||||
{
|
|
||||||
IdString name;
|
|
||||||
std::vector<BelId> bels;
|
|
||||||
std::vector<WireId> wires;
|
|
||||||
std::vector<PipId> pips;
|
|
||||||
std::vector<GroupId> groups;
|
|
||||||
DecalXY decalxy;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CellDelayKey
|
|
||||||
{
|
|
||||||
IdString from, to;
|
|
||||||
inline bool operator==(const CellDelayKey &other) const { return from == other.from && to == other.to; }
|
|
||||||
};
|
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX CellDelayKey>
|
|
||||||
{
|
|
||||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX CellDelayKey &dk) const noexcept
|
|
||||||
{
|
|
||||||
std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from);
|
|
||||||
seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace std
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
struct CellTiming
|
|
||||||
{
|
|
||||||
std::unordered_map<IdString, TimingPortClass> portClasses;
|
|
||||||
std::unordered_map<CellDelayKey, DelayInfo> combDelays;
|
|
||||||
std::unordered_map<IdString, std::vector<TimingClockingInfo>> clockingInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Arch : BaseCtx
|
|
||||||
{
|
{
|
||||||
const ChipInfoPOD *chip_info;
|
const ChipInfoPOD *chip_info;
|
||||||
const PackageInfoPOD *package_info;
|
const PackageInfoPOD *package_info;
|
||||||
|
|
||||||
std::vector<CellInfo *> bel_to_cell;
|
|
||||||
std::unordered_map<WireId, NetInfo *> wire_to_net;
|
|
||||||
std::unordered_map<PipId, NetInfo *> pip_to_net;
|
|
||||||
|
|
||||||
mutable std::unordered_map<IdString, BelId> bel_by_name;
|
mutable std::unordered_map<IdString, BelId> bel_by_name;
|
||||||
mutable std::unordered_map<IdString, WireId> wire_by_name;
|
mutable std::unordered_map<IdString, WireId> wire_by_name;
|
||||||
mutable std::unordered_map<IdString, PipId> pip_by_name;
|
mutable std::unordered_map<IdString, PipId> pip_by_name;
|
||||||
|
|
||||||
// Placeholders to be removed.
|
|
||||||
std::unordered_map<Loc, BelId> bel_by_loc;
|
|
||||||
std::vector<BelId> bel_id_dummy;
|
|
||||||
std::vector<BelPin> bel_pin_dummy;
|
|
||||||
std::vector<WireId> wire_id_dummy;
|
|
||||||
std::vector<PipId> pip_id_dummy;
|
|
||||||
std::vector<GroupId> group_id_dummy;
|
|
||||||
std::vector<GraphicElement> graphic_element_dummy;
|
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
template <typename Id> const TileTypePOD *tileInfo(Id &id) const
|
template <typename Id> const TileTypePOD *tileInfo(Id &id) const
|
||||||
{
|
{
|
||||||
@ -500,35 +422,35 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
static bool isAvailable(ArchArgs::ArchArgsTypes chip);
|
static bool isAvailable(ArchArgs::ArchArgsTypes chip);
|
||||||
|
|
||||||
std::string getChipName() const;
|
std::string getChipName() const override;
|
||||||
// Extra helper
|
// Extra helper
|
||||||
std::string getFullChipName() const;
|
std::string getFullChipName() const;
|
||||||
|
|
||||||
IdString archId() const { return id("machxo2"); }
|
IdString archId() const override { return id("machxo2"); }
|
||||||
ArchArgs archArgs() const { return args; }
|
ArchArgs archArgs() const override { return args; }
|
||||||
IdString archArgsToId(ArchArgs args) const;
|
IdString archArgsToId(ArchArgs args) const override;
|
||||||
|
|
||||||
static const int max_loc_bels = 20;
|
static const int max_loc_bels = 20;
|
||||||
|
|
||||||
int getGridDimX() const { return chip_info->width; }
|
int getGridDimX() const override { return chip_info->width; }
|
||||||
int getGridDimY() const { return chip_info->height; }
|
int getGridDimY() const override { return chip_info->height; }
|
||||||
int getTileBelDimZ(int x, int y) const { return max_loc_bels; }
|
int getTileBelDimZ(int x, int y) const override { return max_loc_bels; }
|
||||||
// TODO: Make more precise? The CENTER MUX having config bits across
|
// TODO: Make more precise? The CENTER MUX having config bits across
|
||||||
// tiles can complicate this?
|
// tiles can complicate this?
|
||||||
int getTilePipDimZ(int x, int y) const { return 2; }
|
int getTilePipDimZ(int x, int y) const override { return 2; }
|
||||||
|
|
||||||
// Bels
|
// Bels
|
||||||
BelId getBelByName(IdString name) const;
|
BelId getBelByName(IdStringList name) const override;
|
||||||
|
|
||||||
IdString getBelName(BelId bel) const
|
IdStringList getBelName(BelId bel) const override
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bel != BelId());
|
NPNR_ASSERT(bel != BelId());
|
||||||
std::stringstream name;
|
std::stringstream name;
|
||||||
name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << tileInfo(bel)->bel_data[bel.index].name.get();
|
name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << tileInfo(bel)->bel_data[bel.index].name.get();
|
||||||
return id(name.str());
|
return IdStringList(id(name.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Loc getBelLocation(BelId bel) const
|
Loc getBelLocation(BelId bel) const override
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bel != BelId());
|
NPNR_ASSERT(bel != BelId());
|
||||||
Loc loc;
|
Loc loc;
|
||||||
@ -538,57 +460,11 @@ struct Arch : BaseCtx
|
|||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
BelId getBelByLocation(Loc loc) const;
|
BelId getBelByLocation(Loc loc) const override;
|
||||||
BelRange getBelsByTile(int x, int y) const;
|
BelRange getBelsByTile(int x, int y) const override;
|
||||||
bool getBelGlobalBuf(BelId bel) const;
|
bool getBelGlobalBuf(BelId bel) const override;
|
||||||
|
|
||||||
uint32_t getBelChecksum(BelId bel) const
|
BelRange getBels() const override
|
||||||
{
|
|
||||||
// FIXME- Copied from ECP5. Should be return val from getBelFlatIndex?
|
|
||||||
return bel.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(bel != BelId());
|
|
||||||
int idx = getBelFlatIndex(bel);
|
|
||||||
NPNR_ASSERT(bel_to_cell.at(idx) == nullptr);
|
|
||||||
bel_to_cell[idx] = cell;
|
|
||||||
cell->bel = bel;
|
|
||||||
cell->belStrength = strength;
|
|
||||||
refreshUiBel(bel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unbindBel(BelId bel)
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(bel != BelId());
|
|
||||||
int idx = getBelFlatIndex(bel);
|
|
||||||
NPNR_ASSERT(bel_to_cell.at(idx) != nullptr);
|
|
||||||
bel_to_cell[idx]->bel = BelId();
|
|
||||||
bel_to_cell[idx]->belStrength = STRENGTH_NONE;
|
|
||||||
bel_to_cell[idx] = nullptr;
|
|
||||||
refreshUiBel(bel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkBelAvail(BelId bel) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(bel != BelId());
|
|
||||||
return bel_to_cell[getBelFlatIndex(bel)] == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
CellInfo *getBoundBelCell(BelId bel) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(bel != BelId());
|
|
||||||
return bel_to_cell[getBelFlatIndex(bel)];
|
|
||||||
}
|
|
||||||
|
|
||||||
CellInfo *getConflictingBelCell(BelId bel) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(bel != BelId());
|
|
||||||
return bel_to_cell[getBelFlatIndex(bel)];
|
|
||||||
}
|
|
||||||
|
|
||||||
BelRange getBels() const
|
|
||||||
{
|
{
|
||||||
BelRange range;
|
BelRange range;
|
||||||
range.b.cursor_tile = 0;
|
range.b.cursor_tile = 0;
|
||||||
@ -601,7 +477,7 @@ struct Arch : BaseCtx
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString getBelType(BelId bel) const
|
IdString getBelType(BelId bel) const override
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bel != BelId());
|
NPNR_ASSERT(bel != BelId());
|
||||||
IdString id;
|
IdString id;
|
||||||
@ -609,106 +485,28 @@ struct Arch : BaseCtx
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId) const
|
WireId getBelPinWire(BelId bel, IdString pin) const override;
|
||||||
{
|
PortType getBelPinType(BelId bel, IdString pin) const override;
|
||||||
std::vector<std::pair<IdString, std::string>> ret;
|
std::vector<IdString> getBelPins(BelId bel) const override;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
WireId getBelPinWire(BelId bel, IdString pin) const;
|
|
||||||
PortType getBelPinType(BelId bel, IdString pin) const;
|
|
||||||
std::vector<IdString> getBelPins(BelId bel) const;
|
|
||||||
|
|
||||||
// Package
|
// Package
|
||||||
BelId getPackagePinBel(const std::string &pin) const;
|
BelId getPackagePinBel(const std::string &pin) const;
|
||||||
|
|
||||||
// Wires
|
// Wires
|
||||||
WireId getWireByName(IdString name) const;
|
WireId getWireByName(IdStringList name) const override;
|
||||||
|
|
||||||
IdString getWireName(WireId wire) const
|
IdStringList getWireName(WireId wire) const override
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
std::stringstream name;
|
std::stringstream name;
|
||||||
name << "X" << wire.location.x << "/Y" << wire.location.y << "/"
|
name << "X" << wire.location.x << "/Y" << wire.location.y << "/"
|
||||||
<< tileInfo(wire)->wire_data[wire.index].name.get();
|
<< tileInfo(wire)->wire_data[wire.index].name.get();
|
||||||
return id(name.str());
|
return IdStringList(id(name.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
IdString getWireType(WireId wire) const { return IdString(); }
|
DelayInfo getWireDelay(WireId wire) const override { return DelayInfo(); }
|
||||||
|
|
||||||
std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId) const
|
WireRange getWires() const override
|
||||||
{
|
|
||||||
std::vector<std::pair<IdString, std::string>> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
|
||||||
|
|
||||||
void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(wire != WireId());
|
|
||||||
NPNR_ASSERT(wire_to_net[wire] == nullptr);
|
|
||||||
wire_to_net[wire] = net;
|
|
||||||
|
|
||||||
// Needs to be set; bindWires is meant for source wires attached
|
|
||||||
// to a Bel.
|
|
||||||
net->wires[wire].pip = PipId();
|
|
||||||
net->wires[wire].strength = strength;
|
|
||||||
refreshUiWire(wire);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unbindWire(WireId wire)
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(wire != WireId());
|
|
||||||
NPNR_ASSERT(wire_to_net[wire] != nullptr);
|
|
||||||
|
|
||||||
auto &net_wires = wire_to_net[wire]->wires;
|
|
||||||
auto it = net_wires.find(wire);
|
|
||||||
NPNR_ASSERT(it != net_wires.end());
|
|
||||||
|
|
||||||
// If we have unbound a wire, then the upstream pip is no longer
|
|
||||||
// used either.
|
|
||||||
auto pip = it->second.pip;
|
|
||||||
if (pip != PipId()) {
|
|
||||||
// TODO: fanout
|
|
||||||
// wire_fanout[getPipSrcWire(pip)]--;
|
|
||||||
pip_to_net[pip] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
net_wires.erase(it);
|
|
||||||
wire_to_net[wire] = nullptr;
|
|
||||||
refreshUiWire(wire);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkWireAvail(WireId wire) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(wire != WireId());
|
|
||||||
return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetInfo *getBoundWireNet(WireId wire) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(wire != WireId());
|
|
||||||
if (wire_to_net.find(wire) == wire_to_net.end())
|
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
return wire_to_net.at(wire);
|
|
||||||
}
|
|
||||||
|
|
||||||
WireId getConflictingWireWire(WireId wire) const { return wire; }
|
|
||||||
|
|
||||||
NetInfo *getConflictingWireNet(WireId wire) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(wire != WireId());
|
|
||||||
if (wire_to_net.find(wire) == wire_to_net.end())
|
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
return wire_to_net.at(wire);
|
|
||||||
}
|
|
||||||
|
|
||||||
DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
|
|
||||||
|
|
||||||
WireRange getWires() const
|
|
||||||
{
|
{
|
||||||
WireRange range;
|
WireRange range;
|
||||||
range.b.cursor_tile = 0;
|
range.b.cursor_tile = 0;
|
||||||
@ -721,7 +519,7 @@ struct Arch : BaseCtx
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
BelPinRange getWireBelPins(WireId wire) const
|
BelPinRange getWireBelPins(WireId wire) const override
|
||||||
{
|
{
|
||||||
BelPinRange range;
|
BelPinRange range;
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
@ -733,85 +531,10 @@ struct Arch : BaseCtx
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pips
|
// Pips
|
||||||
PipId getPipByName(IdString name) const;
|
PipId getPipByName(IdStringList name) const override;
|
||||||
IdString getPipName(PipId pip) const;
|
IdStringList getPipName(PipId pip) const override;
|
||||||
|
|
||||||
IdString getPipType(PipId pip) const { return IdString(); }
|
AllPipRange getPips() const override
|
||||||
|
|
||||||
std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId) const
|
|
||||||
{
|
|
||||||
std::vector<std::pair<IdString, std::string>> ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
|
|
||||||
|
|
||||||
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(pip != PipId());
|
|
||||||
NPNR_ASSERT(pip_to_net[pip] == nullptr);
|
|
||||||
|
|
||||||
pip_to_net[pip] = net;
|
|
||||||
// wire_fanout[getPipSrcWire(pip)]++;
|
|
||||||
|
|
||||||
WireId dst;
|
|
||||||
dst.index = tileInfo(pip)->pips_data[pip.index].dst_idx;
|
|
||||||
dst.location = tileInfo(pip)->pips_data[pip.index].dst;
|
|
||||||
NPNR_ASSERT(wire_to_net[dst] == nullptr);
|
|
||||||
|
|
||||||
// Since NetInfo::wires holds info about uphill pips, bind info about
|
|
||||||
// this pip to the downhill wire.
|
|
||||||
wire_to_net[dst] = net;
|
|
||||||
net->wires[dst].pip = pip;
|
|
||||||
net->wires[dst].strength = strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unbindPip(PipId pip)
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(pip != PipId());
|
|
||||||
NPNR_ASSERT(pip_to_net[pip] == nullptr);
|
|
||||||
|
|
||||||
// wire_fanout[getPipSrcWire(pip)]--;
|
|
||||||
|
|
||||||
WireId dst;
|
|
||||||
dst.index = tileInfo(pip)->pips_data[pip.index].dst_idx;
|
|
||||||
dst.location = tileInfo(pip)->pips_data[pip.index].dst;
|
|
||||||
NPNR_ASSERT(wire_to_net[dst] != nullptr);
|
|
||||||
|
|
||||||
// If we unbind a pip, then the downstream wire is no longer in use
|
|
||||||
// either.
|
|
||||||
wire_to_net[dst] = nullptr;
|
|
||||||
pip_to_net[pip]->wires.erase(dst);
|
|
||||||
pip_to_net[pip] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkPipAvail(PipId pip) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(pip != PipId());
|
|
||||||
return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetInfo *getBoundPipNet(PipId pip) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(pip != PipId());
|
|
||||||
if (pip_to_net.find(pip) == pip_to_net.end())
|
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
return pip_to_net.at(pip);
|
|
||||||
}
|
|
||||||
|
|
||||||
WireId getConflictingPipWire(PipId pip) const { return WireId(); }
|
|
||||||
|
|
||||||
NetInfo *getConflictingPipNet(PipId pip) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(pip != PipId());
|
|
||||||
if (pip_to_net.find(pip) == pip_to_net.end())
|
|
||||||
return nullptr;
|
|
||||||
else
|
|
||||||
return pip_to_net.at(pip);
|
|
||||||
}
|
|
||||||
|
|
||||||
AllPipRange getPips() const
|
|
||||||
{
|
{
|
||||||
AllPipRange range;
|
AllPipRange range;
|
||||||
range.b.cursor_tile = 0;
|
range.b.cursor_tile = 0;
|
||||||
@ -824,7 +547,7 @@ struct Arch : BaseCtx
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loc getPipLocation(PipId pip) const
|
Loc getPipLocation(PipId pip) const override
|
||||||
{
|
{
|
||||||
Loc loc;
|
Loc loc;
|
||||||
loc.x = pip.location.x;
|
loc.x = pip.location.x;
|
||||||
@ -836,7 +559,7 @@ struct Arch : BaseCtx
|
|||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
WireId getPipSrcWire(PipId pip) const
|
WireId getPipSrcWire(PipId pip) const override
|
||||||
{
|
{
|
||||||
WireId wire;
|
WireId wire;
|
||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
@ -845,7 +568,7 @@ struct Arch : BaseCtx
|
|||||||
return wire;
|
return wire;
|
||||||
}
|
}
|
||||||
|
|
||||||
WireId getPipDstWire(PipId pip) const
|
WireId getPipDstWire(PipId pip) const override
|
||||||
{
|
{
|
||||||
WireId wire;
|
WireId wire;
|
||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
@ -854,7 +577,7 @@ struct Arch : BaseCtx
|
|||||||
return wire;
|
return wire;
|
||||||
}
|
}
|
||||||
|
|
||||||
DelayInfo getPipDelay(PipId pip) const
|
DelayInfo getPipDelay(PipId pip) const override
|
||||||
{
|
{
|
||||||
DelayInfo delay;
|
DelayInfo delay;
|
||||||
|
|
||||||
@ -863,7 +586,7 @@ struct Arch : BaseCtx
|
|||||||
return delay;
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipRange getPipsDownhill(WireId wire) const
|
PipRange getPipsDownhill(WireId wire) const override
|
||||||
{
|
{
|
||||||
PipRange range;
|
PipRange range;
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
@ -874,7 +597,7 @@ struct Arch : BaseCtx
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipRange getPipsUphill(WireId wire) const
|
PipRange getPipsUphill(WireId wire) const override
|
||||||
{
|
{
|
||||||
PipRange range;
|
PipRange range;
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
@ -898,56 +621,32 @@ struct Arch : BaseCtx
|
|||||||
NPNR_ASSERT_FALSE("failed to find Pip tile");
|
NPNR_ASSERT_FALSE("failed to find Pip tile");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group
|
|
||||||
GroupId getGroupByName(IdString name) const;
|
|
||||||
IdString getGroupName(GroupId group) const;
|
|
||||||
std::vector<GroupId> getGroups() const;
|
|
||||||
const std::vector<BelId> &getGroupBels(GroupId group) const;
|
|
||||||
const std::vector<WireId> &getGroupWires(GroupId group) const;
|
|
||||||
const std::vector<PipId> &getGroupPips(GroupId group) const;
|
|
||||||
const std::vector<GroupId> &getGroupGroups(GroupId group) const;
|
|
||||||
|
|
||||||
// Delay
|
// Delay
|
||||||
delay_t estimateDelay(WireId src, WireId dst) const;
|
delay_t estimateDelay(WireId src, WireId dst) const override;
|
||||||
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
|
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
|
||||||
delay_t getDelayEpsilon() const { return 0.001; }
|
delay_t getDelayEpsilon() const override { return 0.001; }
|
||||||
delay_t getRipupDelayPenalty() const { return 0.015; }
|
delay_t getRipupDelayPenalty() const override { return 0.015; }
|
||||||
float getDelayNS(delay_t v) const { return v; }
|
float getDelayNS(delay_t v) const override { return v; }
|
||||||
|
|
||||||
DelayInfo getDelayFromNS(float ns) const
|
DelayInfo getDelayFromNS(float ns) const override
|
||||||
{
|
{
|
||||||
DelayInfo del;
|
DelayInfo del;
|
||||||
del.delay = ns;
|
del.delay = ns;
|
||||||
return del;
|
return del;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getDelayChecksum(delay_t v) const { return 0; }
|
uint32_t getDelayChecksum(delay_t v) const override { return v; }
|
||||||
bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
|
|
||||||
|
|
||||||
ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
|
ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
|
||||||
|
|
||||||
// Flow
|
// Flow
|
||||||
bool pack();
|
bool pack() override;
|
||||||
bool place();
|
bool place() override;
|
||||||
bool route();
|
bool route() override;
|
||||||
|
|
||||||
// Graphics
|
|
||||||
const std::vector<GraphicElement> &getDecalGraphics(DecalId decal) const;
|
|
||||||
DecalXY getBelDecal(BelId bel) const;
|
|
||||||
DecalXY getWireDecal(WireId wire) const;
|
|
||||||
DecalXY getPipDecal(PipId pip) const;
|
|
||||||
DecalXY getGroupDecal(GroupId group) const;
|
|
||||||
|
|
||||||
// Cell Delay
|
|
||||||
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
|
|
||||||
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
|
|
||||||
TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
|
|
||||||
// Get the TimingClockingInfo of a port
|
|
||||||
TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
|
|
||||||
|
|
||||||
// Placer
|
// Placer
|
||||||
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
|
bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
|
||||||
bool isBelLocationValid(BelId bel) const;
|
bool isBelLocationValid(BelId bel) const override;
|
||||||
|
|
||||||
static const std::string defaultPlacer;
|
static const std::string defaultPlacer;
|
||||||
static const std::vector<std::string> availablePlacers;
|
static const std::vector<std::string> availablePlacers;
|
||||||
@ -956,7 +655,6 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Internal usage
|
// Internal usage
|
||||||
void assignArchInfo();
|
|
||||||
bool cellsCompatible(const CellInfo **cells, int count) const;
|
bool cellsCompatible(const CellInfo **cells, int count) const;
|
||||||
|
|
||||||
std::vector<std::pair<std::string, std::string>> getTilesAtLocation(int row, int col);
|
std::vector<std::pair<std::string, std::string>> getTilesAtLocation(int row, int col);
|
||||||
|
@ -119,6 +119,7 @@ struct PipId
|
|||||||
|
|
||||||
typedef IdString GroupId;
|
typedef IdString GroupId;
|
||||||
typedef IdString DecalId;
|
typedef IdString DecalId;
|
||||||
|
typedef IdString BelBucketId;
|
||||||
|
|
||||||
struct ArchNetInfo
|
struct ArchNetInfo
|
||||||
{
|
{
|
||||||
|
@ -60,24 +60,15 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire)
|
|||||||
// Handle MachXO2's wonderful naming quirks for wires in left/right tiles, whose
|
// Handle MachXO2's wonderful naming quirks for wires in left/right tiles, whose
|
||||||
// relative coords push them outside the bounds of the chip.
|
// relative coords push them outside the bounds of the chip.
|
||||||
auto is_pio_wire = [](std::string name) {
|
auto is_pio_wire = [](std::string name) {
|
||||||
return (
|
return (name.find("DI") != std::string::npos || name.find("JDI") != std::string::npos ||
|
||||||
name.find("DI") != std::string::npos ||
|
name.find("PADD") != std::string::npos || name.find("INDD") != std::string::npos ||
|
||||||
name.find("JDI") != std::string::npos ||
|
name.find("IOLDO") != std::string::npos || name.find("IOLTO") != std::string::npos ||
|
||||||
name.find("PADD") != std::string::npos ||
|
name.find("JCE") != std::string::npos || name.find("JCLK") != std::string::npos ||
|
||||||
name.find("INDD") != std::string::npos ||
|
name.find("JLSR") != std::string::npos || name.find("JONEG") != std::string::npos ||
|
||||||
name.find("IOLDO") != std::string::npos ||
|
name.find("JOPOS") != std::string::npos || name.find("JTS") != std::string::npos ||
|
||||||
name.find("IOLTO") != std::string::npos ||
|
name.find("JIN") != std::string::npos || name.find("JIP") != std::string::npos ||
|
||||||
name.find("JCE") != std::string::npos ||
|
// Connections to global mux
|
||||||
name.find("JCLK") != std::string::npos ||
|
name.find("JINCK") != std::string::npos);
|
||||||
name.find("JLSR") != std::string::npos ||
|
|
||||||
name.find("JONEG") != std::string::npos ||
|
|
||||||
name.find("JOPOS") != std::string::npos ||
|
|
||||||
name.find("JTS") != std::string::npos ||
|
|
||||||
name.find("JIN") != std::string::npos ||
|
|
||||||
name.find("JIP") != std::string::npos ||
|
|
||||||
// Connections to global mux
|
|
||||||
name.find("JINCK") != std::string::npos
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (prefix2 == "G_" || prefix2 == "L_" || prefix2 == "R_" || prefix2 == "U_" || prefix2 == "D_" ||
|
if (prefix2 == "G_" || prefix2 == "L_" || prefix2 == "R_" || prefix2 == "U_" || prefix2 == "D_" ||
|
||||||
@ -85,10 +76,10 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire)
|
|||||||
return basename;
|
return basename;
|
||||||
if (loc == wire.location) {
|
if (loc == wire.location) {
|
||||||
// TODO: JINCK is not currently handled by this.
|
// TODO: JINCK is not currently handled by this.
|
||||||
if(is_pio_wire(basename)) {
|
if (is_pio_wire(basename)) {
|
||||||
if(wire.location.x == 0)
|
if (wire.location.x == 0)
|
||||||
return "W1_" + basename;
|
return "W1_" + basename;
|
||||||
else if(wire.location.x == max_col)
|
else if (wire.location.x == max_col)
|
||||||
return "E1_" + basename;
|
return "E1_" + basename;
|
||||||
}
|
}
|
||||||
return basename;
|
return basename;
|
||||||
@ -200,7 +191,8 @@ void write_bitstream(Context *ctx, std::string text_config_file)
|
|||||||
for (auto &cell : ctx->cells) {
|
for (auto &cell : ctx->cells) {
|
||||||
CellInfo *ci = cell.second.get();
|
CellInfo *ci = cell.second.get();
|
||||||
if (ci->bel == BelId()) {
|
if (ci->bel == BelId()) {
|
||||||
log_warning("found unplaced cell '%s' during bitstream gen. Not writing to bitstream.\n", ci->name.c_str(ctx));
|
log_warning("found unplaced cell '%s' during bitstream gen. Not writing to bitstream.\n",
|
||||||
|
ci->name.c_str(ctx));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BelId bel = ci->bel;
|
BelId bel = ci->bel;
|
||||||
|
@ -165,8 +165,9 @@ void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_lut)
|
|||||||
|
|
||||||
// If a register's DI port is fed by a constant, options for placing are
|
// If a register's DI port is fed by a constant, options for placing are
|
||||||
// limited. Use the LUT to get around this.
|
// limited. Use the LUT to get around this.
|
||||||
if(pass_thru_lut) {
|
if (pass_thru_lut) {
|
||||||
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16);;
|
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16);
|
||||||
|
;
|
||||||
replace_port(dff, ctx->id("DI"), lc, ctx->id("A0"));
|
replace_port(dff, ctx->id("DI"), lc, ctx->id("A0"));
|
||||||
connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0"));
|
connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,7 +138,7 @@ static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, boo
|
|||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx));
|
log_info("%s user %s\n", orig->name.c_str(ctx), uc->name.c_str(ctx));
|
||||||
|
|
||||||
if(uc->type == id_FACADE_FF && user.port == id_DI) {
|
if (uc->type == id_FACADE_FF && user.port == id_DI) {
|
||||||
log_info("FACADE_FF %s is driven by a constant\n", uc->name.c_str(ctx));
|
log_info("FACADE_FF %s is driven by a constant\n", uc->name.c_str(ctx));
|
||||||
|
|
||||||
std::unique_ptr<CellInfo> lc = create_machxo2_cell(ctx, id_FACADE_SLICE, uc->name.str(ctx) + "_CONST");
|
std::unique_ptr<CellInfo> lc = create_machxo2_cell(ctx, id_FACADE_SLICE, uc->name.str(ctx) + "_CONST");
|
||||||
@ -262,8 +262,7 @@ static void pack_io(Context *ctx)
|
|||||||
log_error("IO buffer '%s' constrained to pin '%s', which does not exist for package '%s'.\n",
|
log_error("IO buffer '%s' constrained to pin '%s', which does not exist for package '%s'.\n",
|
||||||
ci->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
|
ci->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
|
||||||
} else {
|
} else {
|
||||||
log_info("pin '%s' constrained to Bel '%s'.\n", ci->name.c_str(ctx),
|
log_info("pin '%s' constrained to Bel '%s'.\n", ci->name.c_str(ctx), ctx->nameOfBel(pinBel));
|
||||||
ctx->getBelName(pinBel).c_str(ctx));
|
|
||||||
}
|
}
|
||||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
|
ci->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user