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-fpga_interchange*
|
||||
/nextpnr-gowin*
|
||||
/nextpnr-machxo2*
|
||||
cmake-build-*/
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
|
@ -39,9 +39,8 @@ namespace std {
|
||||
|
||||
template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString>>
|
||||
{
|
||||
std::size_t
|
||||
operator()(const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const
|
||||
noexcept
|
||||
std::size_t operator()(
|
||||
const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const noexcept
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
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>>
|
||||
{
|
||||
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)
|
||||
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; }
|
||||
@ -172,16 +173,18 @@ IdString Arch::archArgsToId(ArchArgs args) const
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
BelId Arch::getBelByName(IdStringList name) const
|
||||
{
|
||||
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())
|
||||
return it->second;
|
||||
|
||||
Location loc;
|
||||
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;
|
||||
const TileTypePOD *tilei = tileInfo(ret);
|
||||
for (int i = 0; i < tilei->num_bels; i++) {
|
||||
@ -191,7 +194,7 @@ BelId Arch::getBelByName(IdString name) const
|
||||
}
|
||||
}
|
||||
if (ret.index >= 0)
|
||||
bel_by_name[name] = ret;
|
||||
bel_by_name[name_id] = 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;
|
||||
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())
|
||||
return it->second;
|
||||
|
||||
Location loc;
|
||||
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;
|
||||
|
||||
const TileTypePOD *tilei = tileInfo(ret);
|
||||
@ -324,23 +328,24 @@ WireId Arch::getWireByName(IdString name) const
|
||||
}
|
||||
}
|
||||
if (ret.index >= 0)
|
||||
wire_by_name[name] = ret;
|
||||
wire_by_name[name_id] = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
PipId Arch::getPipByName(IdString name) const
|
||||
PipId Arch::getPipByName(IdStringList name) const
|
||||
{
|
||||
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())
|
||||
return it->second;
|
||||
|
||||
Location loc;
|
||||
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;
|
||||
|
||||
const TileTypePOD *tilei = tileInfo(ret);
|
||||
@ -348,51 +353,31 @@ PipId Arch::getPipByName(IdString name) const
|
||||
PipId curr;
|
||||
curr.location = loc;
|
||||
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())
|
||||
NPNR_ASSERT_FALSE_STR("no pip named " + name.str(this));
|
||||
return pip_by_name[name];
|
||||
if (pip_by_name.find(name_id) == pip_by_name.end())
|
||||
NPNR_ASSERT_FALSE_STR("no pip named " + name_id.str(this));
|
||||
return pip_by_name[name_id];
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const
|
||||
IdStringList Arch::getPipName(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
|
||||
int x = pip.location.x;
|
||||
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::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(), '/', '.');
|
||||
|
||||
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
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
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 bb;
|
||||
@ -432,6 +415,13 @@ bool Arch::place()
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
archInfoToAttributes();
|
||||
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 {
|
||||
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
|
||||
{
|
||||
// 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::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
||||
|
||||
void Arch::assignArchInfo() {}
|
||||
|
||||
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)
|
||||
|
426
machxo2/arch.h
426
machxo2/arch.h
@ -377,109 +377,31 @@ struct ArchArgs
|
||||
} speed = SPEED_4;
|
||||
};
|
||||
|
||||
struct WireInfo;
|
||||
|
||||
struct PipInfo
|
||||
struct ArchRanges : BaseArchRanges
|
||||
{
|
||||
IdString name, type;
|
||||
std::map<IdString, std::string> attrs;
|
||||
NetInfo *bound_net;
|
||||
WireId srcWire, dstWire;
|
||||
DelayInfo delay;
|
||||
DecalXY decalxy;
|
||||
Loc loc;
|
||||
using ArchArgsT = ArchArgs;
|
||||
// Bels
|
||||
using AllBelsRangeT = BelRange;
|
||||
using TileBelsRangeT = BelRange;
|
||||
using BelPinsRangeT = std::vector<IdString>;
|
||||
// Wires
|
||||
using AllWiresRangeT = WireRange;
|
||||
using DownhillPipRangeT = PipRange;
|
||||
using UphillPipRangeT = PipRange;
|
||||
using WireBelPinRangeT = BelPinRange;
|
||||
// Pips
|
||||
using AllPipsRangeT = AllPipRange;
|
||||
};
|
||||
|
||||
struct WireInfo
|
||||
{
|
||||
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
|
||||
struct Arch : BaseArch<ArchRanges>
|
||||
{
|
||||
const ChipInfoPOD *chip_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, WireId> wire_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
|
||||
template <typename Id> const TileTypePOD *tileInfo(Id &id) const
|
||||
{
|
||||
@ -500,35 +422,35 @@ struct Arch : BaseCtx
|
||||
|
||||
static bool isAvailable(ArchArgs::ArchArgsTypes chip);
|
||||
|
||||
std::string getChipName() const;
|
||||
std::string getChipName() const override;
|
||||
// Extra helper
|
||||
std::string getFullChipName() const;
|
||||
|
||||
IdString archId() const { return id("machxo2"); }
|
||||
ArchArgs archArgs() const { return args; }
|
||||
IdString archArgsToId(ArchArgs args) const;
|
||||
IdString archId() const override { return id("machxo2"); }
|
||||
ArchArgs archArgs() const override { return args; }
|
||||
IdString archArgsToId(ArchArgs args) const override;
|
||||
|
||||
static const int max_loc_bels = 20;
|
||||
|
||||
int getGridDimX() const { return chip_info->width; }
|
||||
int getGridDimY() const { return chip_info->height; }
|
||||
int getTileBelDimZ(int x, int y) const { return max_loc_bels; }
|
||||
int getGridDimX() const override { return chip_info->width; }
|
||||
int getGridDimY() const override { return chip_info->height; }
|
||||
int getTileBelDimZ(int x, int y) const override { return max_loc_bels; }
|
||||
// TODO: Make more precise? The CENTER MUX having config bits across
|
||||
// tiles can complicate this?
|
||||
int getTilePipDimZ(int x, int y) const { return 2; }
|
||||
int getTilePipDimZ(int x, int y) const override { return 2; }
|
||||
|
||||
// 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());
|
||||
std::stringstream name;
|
||||
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());
|
||||
Loc loc;
|
||||
@ -538,57 +460,11 @@ struct Arch : BaseCtx
|
||||
return loc;
|
||||
}
|
||||
|
||||
BelId getBelByLocation(Loc loc) const;
|
||||
BelRange getBelsByTile(int x, int y) const;
|
||||
bool getBelGlobalBuf(BelId bel) const;
|
||||
BelId getBelByLocation(Loc loc) const override;
|
||||
BelRange getBelsByTile(int x, int y) const override;
|
||||
bool getBelGlobalBuf(BelId bel) const override;
|
||||
|
||||
uint32_t getBelChecksum(BelId bel) const
|
||||
{
|
||||
// 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 getBels() const override
|
||||
{
|
||||
BelRange range;
|
||||
range.b.cursor_tile = 0;
|
||||
@ -601,7 +477,7 @@ struct Arch : BaseCtx
|
||||
return range;
|
||||
}
|
||||
|
||||
IdString getBelType(BelId bel) const
|
||||
IdString getBelType(BelId bel) const override
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
IdString id;
|
||||
@ -609,106 +485,28 @@ struct Arch : BaseCtx
|
||||
return id;
|
||||
}
|
||||
|
||||
std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId) const
|
||||
{
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
WireId getBelPinWire(BelId bel, IdString pin) const;
|
||||
PortType getBelPinType(BelId bel, IdString pin) const;
|
||||
std::vector<IdString> getBelPins(BelId bel) const;
|
||||
WireId getBelPinWire(BelId bel, IdString pin) const override;
|
||||
PortType getBelPinType(BelId bel, IdString pin) const override;
|
||||
std::vector<IdString> getBelPins(BelId bel) const override;
|
||||
|
||||
// Package
|
||||
BelId getPackagePinBel(const std::string &pin) const;
|
||||
|
||||
// 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());
|
||||
std::stringstream name;
|
||||
name << "X" << wire.location.x << "/Y" << wire.location.y << "/"
|
||||
<< 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
|
||||
{
|
||||
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 getWires() const override
|
||||
{
|
||||
WireRange range;
|
||||
range.b.cursor_tile = 0;
|
||||
@ -721,7 +519,7 @@ struct Arch : BaseCtx
|
||||
return range;
|
||||
}
|
||||
|
||||
BelPinRange getWireBelPins(WireId wire) const
|
||||
BelPinRange getWireBelPins(WireId wire) const override
|
||||
{
|
||||
BelPinRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
@ -733,85 +531,10 @@ struct Arch : BaseCtx
|
||||
}
|
||||
|
||||
// Pips
|
||||
PipId getPipByName(IdString name) const;
|
||||
IdString getPipName(PipId pip) const;
|
||||
PipId getPipByName(IdStringList name) const override;
|
||||
IdStringList getPipName(PipId pip) const override;
|
||||
|
||||
IdString getPipType(PipId pip) const { return IdString(); }
|
||||
|
||||
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 getPips() const override
|
||||
{
|
||||
AllPipRange range;
|
||||
range.b.cursor_tile = 0;
|
||||
@ -824,7 +547,7 @@ struct Arch : BaseCtx
|
||||
return range;
|
||||
}
|
||||
|
||||
Loc getPipLocation(PipId pip) const
|
||||
Loc getPipLocation(PipId pip) const override
|
||||
{
|
||||
Loc loc;
|
||||
loc.x = pip.location.x;
|
||||
@ -836,7 +559,7 @@ struct Arch : BaseCtx
|
||||
return loc;
|
||||
}
|
||||
|
||||
WireId getPipSrcWire(PipId pip) const
|
||||
WireId getPipSrcWire(PipId pip) const override
|
||||
{
|
||||
WireId wire;
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
@ -845,7 +568,7 @@ struct Arch : BaseCtx
|
||||
return wire;
|
||||
}
|
||||
|
||||
WireId getPipDstWire(PipId pip) const
|
||||
WireId getPipDstWire(PipId pip) const override
|
||||
{
|
||||
WireId wire;
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
@ -854,7 +577,7 @@ struct Arch : BaseCtx
|
||||
return wire;
|
||||
}
|
||||
|
||||
DelayInfo getPipDelay(PipId pip) const
|
||||
DelayInfo getPipDelay(PipId pip) const override
|
||||
{
|
||||
DelayInfo delay;
|
||||
|
||||
@ -863,7 +586,7 @@ struct Arch : BaseCtx
|
||||
return delay;
|
||||
}
|
||||
|
||||
PipRange getPipsDownhill(WireId wire) const
|
||||
PipRange getPipsDownhill(WireId wire) const override
|
||||
{
|
||||
PipRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
@ -874,7 +597,7 @@ struct Arch : BaseCtx
|
||||
return range;
|
||||
}
|
||||
|
||||
PipRange getPipsUphill(WireId wire) const
|
||||
PipRange getPipsUphill(WireId wire) const override
|
||||
{
|
||||
PipRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
@ -898,56 +621,32 @@ struct Arch : BaseCtx
|
||||
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_t estimateDelay(WireId src, WireId dst) const;
|
||||
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
|
||||
delay_t getDelayEpsilon() const { return 0.001; }
|
||||
delay_t getRipupDelayPenalty() const { return 0.015; }
|
||||
float getDelayNS(delay_t v) const { return v; }
|
||||
delay_t estimateDelay(WireId src, WireId dst) const override;
|
||||
delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const override;
|
||||
delay_t getDelayEpsilon() const override { return 0.001; }
|
||||
delay_t getRipupDelayPenalty() const override { return 0.015; }
|
||||
float getDelayNS(delay_t v) const override { return v; }
|
||||
|
||||
DelayInfo getDelayFromNS(float ns) const
|
||||
DelayInfo getDelayFromNS(float ns) const override
|
||||
{
|
||||
DelayInfo del;
|
||||
del.delay = ns;
|
||||
return del;
|
||||
}
|
||||
|
||||
uint32_t getDelayChecksum(delay_t v) const { return 0; }
|
||||
bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
|
||||
uint32_t getDelayChecksum(delay_t v) const override { return v; }
|
||||
|
||||
ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
|
||||
ArcBounds getRouteBoundingBox(WireId src, WireId dst) const override;
|
||||
|
||||
// Flow
|
||||
bool pack();
|
||||
bool place();
|
||||
bool route();
|
||||
|
||||
// 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;
|
||||
bool pack() override;
|
||||
bool place() override;
|
||||
bool route() override;
|
||||
|
||||
// Placer
|
||||
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
|
||||
bool isBelLocationValid(BelId bel) const;
|
||||
bool isValidBelForCell(CellInfo *cell, BelId bel) const override;
|
||||
bool isBelLocationValid(BelId bel) const override;
|
||||
|
||||
static const std::string defaultPlacer;
|
||||
static const std::vector<std::string> availablePlacers;
|
||||
@ -956,7 +655,6 @@ struct Arch : BaseCtx
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal usage
|
||||
void assignArchInfo();
|
||||
bool cellsCompatible(const CellInfo **cells, int count) const;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> getTilesAtLocation(int row, int col);
|
||||
|
@ -119,6 +119,7 @@ struct PipId
|
||||
|
||||
typedef IdString GroupId;
|
||||
typedef IdString DecalId;
|
||||
typedef IdString BelBucketId;
|
||||
|
||||
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
|
||||
// relative coords push them outside the bounds of the chip.
|
||||
auto is_pio_wire = [](std::string name) {
|
||||
return (
|
||||
name.find("DI") != std::string::npos ||
|
||||
name.find("JDI") != std::string::npos ||
|
||||
name.find("PADD") != std::string::npos ||
|
||||
name.find("INDD") != std::string::npos ||
|
||||
name.find("IOLDO") != std::string::npos ||
|
||||
name.find("IOLTO") != std::string::npos ||
|
||||
name.find("JCE") != std::string::npos ||
|
||||
name.find("JCLK") != 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
|
||||
);
|
||||
return (name.find("DI") != std::string::npos || name.find("JDI") != std::string::npos ||
|
||||
name.find("PADD") != std::string::npos || name.find("INDD") != std::string::npos ||
|
||||
name.find("IOLDO") != std::string::npos || name.find("IOLTO") != std::string::npos ||
|
||||
name.find("JCE") != std::string::npos || name.find("JCLK") != 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_" ||
|
||||
@ -85,10 +76,10 @@ static std::string get_trellis_wirename(Context *ctx, Location loc, WireId wire)
|
||||
return basename;
|
||||
if (loc == wire.location) {
|
||||
// TODO: JINCK is not currently handled by this.
|
||||
if(is_pio_wire(basename)) {
|
||||
if(wire.location.x == 0)
|
||||
if (is_pio_wire(basename)) {
|
||||
if (wire.location.x == 0)
|
||||
return "W1_" + basename;
|
||||
else if(wire.location.x == max_col)
|
||||
else if (wire.location.x == max_col)
|
||||
return "E1_" + basename;
|
||||
}
|
||||
return basename;
|
||||
@ -200,7 +191,8 @@ void write_bitstream(Context *ctx, std::string text_config_file)
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
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;
|
||||
}
|
||||
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
|
||||
// limited. Use the LUT to get around this.
|
||||
if(pass_thru_lut) {
|
||||
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16);;
|
||||
if (pass_thru_lut) {
|
||||
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16);
|
||||
;
|
||||
replace_port(dff, ctx->id("DI"), lc, ctx->id("A0"));
|
||||
connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0"));
|
||||
} else {
|
||||
|
@ -138,7 +138,7 @@ static void set_net_constant(Context *ctx, NetInfo *orig, NetInfo *constnet, boo
|
||||
if (ctx->verbose)
|
||||
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));
|
||||
|
||||
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",
|
||||
ci->name.c_str(ctx), pin.c_str(), ctx->args.package.c_str());
|
||||
} else {
|
||||
log_info("pin '%s' constrained to Bel '%s'.\n", ci->name.c_str(ctx),
|
||||
ctx->getBelName(pinBel).c_str(ctx));
|
||||
log_info("pin '%s' constrained to Bel '%s'.\n", ci->name.c_str(ctx), ctx->nameOfBel(pinBel));
|
||||
}
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user