ecp5: Implementing core arch.h functions
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
c4af52dd5b
commit
7862d1b84b
386
ecp5/arch.cc
Normal file
386
ecp5/arch.cc
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include "log.h"
|
||||
#include "nextpnr.h"
|
||||
#include "util.h"
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
IdString Arch::belTypeToId(BelType type) const
|
||||
{
|
||||
if (type == TYPE_ICESTORM_LC)
|
||||
return id("ICESTORM_LC");
|
||||
if (type == TYPE_ICESTORM_RAM)
|
||||
return id("ICESTORM_RAM");
|
||||
if (type == TYPE_SB_IO)
|
||||
return id("SB_IO");
|
||||
if (type == TYPE_SB_GB)
|
||||
return id("SB_GB");
|
||||
if (type == TYPE_ICESTORM_PLL)
|
||||
return id("ICESTORM_PLL");
|
||||
if (type == TYPE_SB_WARMBOOT)
|
||||
return id("SB_WARMBOOT");
|
||||
if (type == TYPE_SB_MAC16)
|
||||
return id("SB_MAC16");
|
||||
if (type == TYPE_ICESTORM_HFOSC)
|
||||
return id("ICESTORM_HFOSC");
|
||||
if (type == TYPE_ICESTORM_LFOSC)
|
||||
return id("ICESTORM_LFOSC");
|
||||
if (type == TYPE_SB_I2C)
|
||||
return id("SB_I2C");
|
||||
if (type == TYPE_SB_SPI)
|
||||
return id("SB_SPI");
|
||||
if (type == TYPE_IO_I3C)
|
||||
return id("IO_I3C");
|
||||
if (type == TYPE_SB_LEDDA_IP)
|
||||
return id("SB_LEDDA_IP");
|
||||
if (type == TYPE_SB_RGBA_DRV)
|
||||
return id("SB_RGBA_DRV");
|
||||
if (type == TYPE_ICESTORM_SPRAM)
|
||||
return id("ICESTORM_SPRAM");
|
||||
return IdString();
|
||||
}
|
||||
|
||||
BelType Arch::belTypeFromId(IdString type) const
|
||||
{
|
||||
if (type == id("ICESTORM_LC"))
|
||||
return TYPE_ICESTORM_LC;
|
||||
if (type == id("ICESTORM_RAM"))
|
||||
return TYPE_ICESTORM_RAM;
|
||||
if (type == id("SB_IO"))
|
||||
return TYPE_SB_IO;
|
||||
if (type == id("SB_GB"))
|
||||
return TYPE_SB_GB;
|
||||
if (type == id("ICESTORM_PLL"))
|
||||
return TYPE_ICESTORM_PLL;
|
||||
if (type == id("SB_WARMBOOT"))
|
||||
return TYPE_SB_WARMBOOT;
|
||||
if (type == id("SB_MAC16"))
|
||||
return TYPE_SB_MAC16;
|
||||
if (type == id("ICESTORM_HFOSC"))
|
||||
return TYPE_ICESTORM_HFOSC;
|
||||
if (type == id("ICESTORM_LFOSC"))
|
||||
return TYPE_ICESTORM_LFOSC;
|
||||
if (type == id("SB_I2C"))
|
||||
return TYPE_SB_I2C;
|
||||
if (type == id("SB_SPI"))
|
||||
return TYPE_SB_SPI;
|
||||
if (type == id("IO_I3C"))
|
||||
return TYPE_IO_I3C;
|
||||
if (type == id("SB_LEDDA_IP"))
|
||||
return TYPE_SB_LEDDA_IP;
|
||||
if (type == id("SB_RGBA_DRV"))
|
||||
return TYPE_SB_RGBA_DRV;
|
||||
if (type == id("ICESTORM_SPRAM"))
|
||||
return TYPE_ICESTORM_SPRAM;
|
||||
return TYPE_NONE;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void IdString::initialize_arch(const BaseCtx *ctx)
|
||||
{
|
||||
#define X(t) initialize_add(ctx, #t, PIN_##t);
|
||||
#include "portpins.inc"
|
||||
#undef X
|
||||
}
|
||||
|
||||
IdString Arch::portPinToId(PortPin type) const
|
||||
{
|
||||
IdString ret;
|
||||
if (type > 0 && type < PIN_MAXIDX)
|
||||
ret.index = type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PortPin Arch::portPinFromId(IdString type) const
|
||||
{
|
||||
if (type.index > 0 && type.index < PIN_MAXIDX)
|
||||
return PortPin(type.index);
|
||||
return PIN_NONE;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
void load_chipdb();
|
||||
#endif
|
||||
|
||||
Arch::Arch(ArchArgs args) : args(args)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
load_chipdb();
|
||||
#endif
|
||||
|
||||
#ifdef ICE40_HX1K_ONLY
|
||||
if (args.type == ArchArgs::HX1K) {
|
||||
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
|
||||
} else {
|
||||
log_error("Unsupported iCE40 chip type.\n");
|
||||
}
|
||||
#else
|
||||
if (args.type == ArchArgs::LP384) {
|
||||
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_384));
|
||||
} else if (args.type == ArchArgs::LP1K || args.type == ArchArgs::HX1K) {
|
||||
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_1k));
|
||||
} else if (args.type == ArchArgs::UP5K) {
|
||||
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_5k));
|
||||
} else if (args.type == ArchArgs::LP8K || args.type == ArchArgs::HX8K) {
|
||||
chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_8k));
|
||||
} else {
|
||||
log_error("Unsupported iCE40 chip type.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
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_to_cell.resize(chip_info->num_bels);
|
||||
wire_to_net.resize(chip_info->num_wires);
|
||||
pip_to_net.resize(chip_info->num_pips);
|
||||
switches_locked.resize(chip_info->num_switches);
|
||||
|
||||
// Initialise regularly used IDStrings for performance
|
||||
id_glb_buf_out = id("GLOBAL_BUFFER_OUTPUT");
|
||||
id_icestorm_lc = id("ICESTORM_LC");
|
||||
id_sb_io = id("SB_IO");
|
||||
id_sb_gb = id("SB_GB");
|
||||
id_cen = id("CEN");
|
||||
id_clk = id("CLK");
|
||||
id_sr = id("SR");
|
||||
id_i0 = id("I0");
|
||||
id_i1 = id("I1");
|
||||
id_i2 = id("I2");
|
||||
id_i3 = id("I3");
|
||||
id_dff_en = id("DFF_ENABLE");
|
||||
id_neg_clk = id("NEG_CLK");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
std::string Arch::getChipName()
|
||||
{
|
||||
#ifdef ICE40_HX1K_ONLY
|
||||
if (args.type == ArchArgs::HX1K) {
|
||||
return "Lattice LP1K";
|
||||
} else {
|
||||
log_error("Unsupported iCE40 chip type.\n");
|
||||
}
|
||||
#else
|
||||
if (args.type == ArchArgs::LP384) {
|
||||
return "Lattice LP384";
|
||||
} else if (args.type == ArchArgs::LP1K) {
|
||||
return "Lattice LP1K";
|
||||
} else if (args.type == ArchArgs::HX1K) {
|
||||
return "Lattice HX1K";
|
||||
} else if (args.type == ArchArgs::UP5K) {
|
||||
return "Lattice UP5K";
|
||||
} else if (args.type == ArchArgs::LP8K) {
|
||||
return "Lattice LP8K";
|
||||
} else if (args.type == ArchArgs::HX8K) {
|
||||
return "Lattice HX8K";
|
||||
} else {
|
||||
log_error("Unknown chip\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
IdString Arch::archArgsToId(ArchArgs args) const
|
||||
{
|
||||
if (args.type == ArchArgs::LP384)
|
||||
return id("lp384");
|
||||
if (args.type == ArchArgs::LP1K)
|
||||
return id("lp1k");
|
||||
if (args.type == ArchArgs::HX1K)
|
||||
return id("hx1k");
|
||||
if (args.type == ArchArgs::UP5K)
|
||||
return id("up5k");
|
||||
if (args.type == ArchArgs::LP8K)
|
||||
return id("lp8k");
|
||||
if (args.type == ArchArgs::HX8K)
|
||||
return id("hx8k");
|
||||
return IdString();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
BelId Arch::getBelByName(IdString name) const
|
||||
{
|
||||
BelId ret;
|
||||
|
||||
if (bel_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info->num_bels; i++)
|
||||
bel_by_name[id(chip_info->bel_data[i].name.get())] = i;
|
||||
}
|
||||
|
||||
auto it = bel_by_name.find(name);
|
||||
if (it != bel_by_name.end())
|
||||
ret.index = it->second;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BelRange Arch::getBelsAtSameTile(BelId bel) const
|
||||
{
|
||||
BelRange br;
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
// This requires Bels at the same tile are consecutive
|
||||
int x = chip_info->bel_data[bel.index].x;
|
||||
int y = chip_info->bel_data[bel.index].y;
|
||||
int start = bel.index, end = bel.index;
|
||||
while (start >= 0 && chip_info->bel_data[start].x == x && chip_info->bel_data[start].y == y)
|
||||
start--;
|
||||
start++;
|
||||
br.b.cursor = start;
|
||||
while (end < chip_info->num_bels && chip_info->bel_data[end].x == x && chip_info->bel_data[end].y == y)
|
||||
end++;
|
||||
br.e.cursor = end;
|
||||
return br;
|
||||
}
|
||||
|
||||
WireId Arch::getWireBelPin(BelId bel, PortPin pin) const
|
||||
{
|
||||
WireId 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++)
|
||||
if (bel_wires[i].port == pin) {
|
||||
ret.index = bel_wires[i].wire_index;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
IdString Arch::getPipName(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
BelId Arch::getPackagePinBel(const std::string &pin) const { return BelId(); }
|
||||
|
||||
std::string Arch::getBelPackagePin(BelId bel) const { return ""; }
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const {}
|
||||
|
||||
delay_t Arch::estimateDelay(WireId src, WireId dst) const { return 1; }
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
std::vector<GraphicElement> Arch::getFrameGraphics() const
|
||||
{
|
||||
std::vector<GraphicElement> ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<GraphicElement> Arch::getBelGraphics(BelId bel) const
|
||||
{
|
||||
std::vector<GraphicElement> ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<GraphicElement> Arch::getWireGraphics(WireId wire) const
|
||||
{
|
||||
std::vector<GraphicElement> ret;
|
||||
// FIXME
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<GraphicElement> Arch::getPipGraphics(PipId pip) const
|
||||
{
|
||||
std::vector<GraphicElement> ret;
|
||||
// FIXME
|
||||
return ret;
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
199
ecp5/arch.h
199
ecp5/arch.h
@ -44,7 +44,7 @@ template <typename T> struct RelPtr
|
||||
};
|
||||
|
||||
NPNR_PACKED_STRUCT(struct BelWirePOD {
|
||||
Location rel_wire_loc;
|
||||
LocationPOD rel_wire_loc;
|
||||
int32_t wire_index;
|
||||
PortPin port;
|
||||
});
|
||||
@ -59,23 +59,23 @@ NPNR_PACKED_STRUCT(struct BelInfoPOD {
|
||||
});
|
||||
|
||||
NPNR_PACKED_STRUCT(struct BelPortPOD {
|
||||
Location rel_bel_loc;
|
||||
LocationPOD rel_bel_loc;
|
||||
int32_t bel_index;
|
||||
PortPin port;
|
||||
});
|
||||
|
||||
NPNR_PACKED_STRUCT(struct PipInfoPOD {
|
||||
Location rel_src_loc, rel_dst_loc;
|
||||
LocationPOD rel_src_loc, rel_dst_loc;
|
||||
int32_t src_idx, dst_idx;
|
||||
int32_t delay;
|
||||
Location rel_tile_loc;
|
||||
LocationPOD rel_tile_loc;
|
||||
int16_t tile_type;
|
||||
int8_t pip_type;
|
||||
int8_t padding_0;
|
||||
});
|
||||
|
||||
NPNR_PACKED_STRUCT(struct PipLocatorPOD {
|
||||
Location rel_loc;
|
||||
LocationPOD rel_loc;
|
||||
int32_t index;
|
||||
});
|
||||
|
||||
@ -98,21 +98,20 @@ NPNR_PACKED_STRUCT(struct LocationTypePOD {
|
||||
|
||||
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||
int32_t width, height;
|
||||
int32_t num_tiles;
|
||||
int32_t num_location_types;
|
||||
RelPtr<LocationTypePOD> locations;
|
||||
RelPtr<int32_t> location_type;
|
||||
});
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
extern const char *chipdb_blob_384;
|
||||
extern const char *chipdb_blob_1k;
|
||||
extern const char *chipdb_blob_5k;
|
||||
extern const char *chipdb_blob_8k;
|
||||
extern const char *chipdb_blob_25k;
|
||||
extern const char *chipdb_blob_45k;
|
||||
extern const char *chipdb_blob_85k;
|
||||
#else
|
||||
extern const char chipdb_blob_384[];
|
||||
extern const char chipdb_blob_1k[];
|
||||
extern const char chipdb_blob_5k[];
|
||||
extern const char chipdb_blob_8k[];
|
||||
extern const char chipdb_blob_25k[];
|
||||
extern const char chipdb_blob_45k[];
|
||||
extern const char chipdb_blob_85k[];
|
||||
#endif
|
||||
|
||||
/************************ End of chipdb section. ************************/
|
||||
@ -126,7 +125,8 @@ struct BelIterator
|
||||
BelIterator operator++()
|
||||
{
|
||||
cursor_index++;
|
||||
while (cursor_index >= ci->locations[ci->location_type[cursor_tile]]->num_bels) {
|
||||
while (cursor_tile < chip->num_tiles &&
|
||||
cursor_index >= chip->locations[chip->location_type[cursor_tile]].num_bels) {
|
||||
cursor_index = 0;
|
||||
cursor_tile++;
|
||||
}
|
||||
@ -135,7 +135,7 @@ struct BelIterator
|
||||
BelIterator operator++(int)
|
||||
{
|
||||
BelIterator prior(*this);
|
||||
cursor++;
|
||||
++(*this);
|
||||
return prior;
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ struct BelRange
|
||||
struct BelPinIterator
|
||||
{
|
||||
const BelPortPOD *ptr = nullptr;
|
||||
const Location wire_loc;
|
||||
Location wire_loc;
|
||||
void operator++() { ptr++; }
|
||||
bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; }
|
||||
|
||||
@ -203,7 +203,8 @@ struct WireIterator
|
||||
WireIterator operator++()
|
||||
{
|
||||
cursor_index++;
|
||||
while (cursor_index >= ci->locations[ci->location_type[cursor_tile]]->num_wires) {
|
||||
while (cursor_tile < chip->num_tiles &&
|
||||
cursor_index >= chip->locations[chip->location_type[cursor_tile]].num_wires) {
|
||||
cursor_index = 0;
|
||||
cursor_tile++;
|
||||
}
|
||||
@ -212,7 +213,7 @@ struct WireIterator
|
||||
WireIterator operator++(int)
|
||||
{
|
||||
WireIterator prior(*this);
|
||||
cursor++;
|
||||
++(*this);
|
||||
return prior;
|
||||
}
|
||||
|
||||
@ -254,7 +255,8 @@ struct AllPipIterator
|
||||
AllPipIterator operator++()
|
||||
{
|
||||
cursor_index++;
|
||||
while (cursor_index >= ci->locations[ci->location_type[cursor_tile]]->num_pips) {
|
||||
while (cursor_tile < chip->num_tiles &&
|
||||
cursor_index >= chip->locations[chip->location_type[cursor_tile]].num_pips) {
|
||||
cursor_index = 0;
|
||||
cursor_tile++;
|
||||
}
|
||||
@ -262,8 +264,8 @@ struct AllPipIterator
|
||||
}
|
||||
AllPipIterator operator++(int)
|
||||
{
|
||||
WireIterator prior(*this);
|
||||
cursor++;
|
||||
AllPipIterator prior(*this);
|
||||
++(*this);
|
||||
return prior;
|
||||
}
|
||||
|
||||
@ -309,7 +311,7 @@ struct PipIterator
|
||||
{
|
||||
PipId ret;
|
||||
ret.index = cursor->index;
|
||||
ret.location = wire_loc + cursor->location;
|
||||
ret.location = wire_loc + cursor->rel_loc;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
@ -337,7 +339,6 @@ struct ArchArgs
|
||||
struct Arch : BaseCtx
|
||||
{
|
||||
const ChipInfoPOD *chip_info;
|
||||
const PackageInfoPOD *package_info;
|
||||
|
||||
mutable std::unordered_map<IdString, int> bel_by_name;
|
||||
mutable std::unordered_map<IdString, int> wire_by_name;
|
||||
@ -366,10 +367,15 @@ struct Arch : BaseCtx
|
||||
|
||||
BelId getBelByName(IdString name) const;
|
||||
|
||||
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
|
||||
{
|
||||
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
|
||||
}
|
||||
|
||||
IdString getBelName(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return id(chip_info->bel_data[bel.index].name.get());
|
||||
return id(locInfo(bel)->bel_data[bel.index].name.get());
|
||||
}
|
||||
|
||||
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
|
||||
@ -386,35 +392,46 @@ struct Arch : BaseCtx
|
||||
void unbindBel(BelId bel)
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
NPNR_ASSERT(bel_to_cell[bel.index] != IdString());
|
||||
cells[bel_to_cell[bel.index]]->bel = BelId();
|
||||
cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE;
|
||||
bel_to_cell[bel.index] = IdString();
|
||||
NPNR_ASSERT(bel_to_cell[bel] != IdString());
|
||||
cells[bel_to_cell[bel]]->bel = BelId();
|
||||
cells[bel_to_cell[bel]]->belStrength = STRENGTH_NONE;
|
||||
bel_to_cell[bel] = IdString();
|
||||
}
|
||||
|
||||
bool checkBelAvail(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel_to_cell[bel.index] == IdString();
|
||||
return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString();
|
||||
}
|
||||
|
||||
IdString getBoundBelCell(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel_to_cell.at(bel);
|
||||
if (bel_to_cell.find(bel) == bel_to_cell.end())
|
||||
return IdString();
|
||||
else
|
||||
return bel_to_cell.at(bel);
|
||||
}
|
||||
|
||||
IdString getConflictingBelCell(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return bel_to_cell.at(bel);
|
||||
if (bel_to_cell.find(bel) == bel_to_cell.end())
|
||||
return IdString();
|
||||
else
|
||||
return bel_to_cell.at(bel);
|
||||
}
|
||||
|
||||
BelRange getBels() const
|
||||
{
|
||||
BelRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info->num_bels;
|
||||
range.b.cursor_tile = 0;
|
||||
range.b.cursor_index = -1;
|
||||
range.b.chip = chip_info;
|
||||
++range.b; //-1 and then ++ deals with the case of no Bels in the first tile
|
||||
range.e.cursor_tile = chip_info->width * chip_info->height;
|
||||
range.e.cursor_index = 0;
|
||||
range.e.chip = chip_info;
|
||||
return range;
|
||||
}
|
||||
|
||||
@ -437,7 +454,7 @@ struct Arch : BaseCtx
|
||||
BelType getBelType(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return chip_info->bel_data[bel.index].type;
|
||||
return locInfo(bel)->bel_data[bel.index].type;
|
||||
}
|
||||
|
||||
WireId getWireBelPin(BelId bel, PortPin pin) const;
|
||||
@ -447,9 +464,10 @@ struct Arch : BaseCtx
|
||||
BelPin ret;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
|
||||
if (chip_info->wire_data[wire.index].bel_uphill.bel_index >= 0) {
|
||||
ret.bel.index = chip_info->wire_data[wire.index].bel_uphill.bel_index;
|
||||
ret.pin = chip_info->wire_data[wire.index].bel_uphill.port;
|
||||
if (locInfo(wire)->wire_data[wire.index].bel_uphill.bel_index >= 0) {
|
||||
ret.bel.index = locInfo(wire)->wire_data[wire.index].bel_uphill.bel_index;
|
||||
ret.bel.location = wire.location + locInfo(wire)->wire_data[wire.index].bel_uphill.rel_bel_loc;
|
||||
ret.pin = locInfo(wire)->wire_data[wire.index].bel_uphill.port;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -459,8 +477,10 @@ struct Arch : BaseCtx
|
||||
{
|
||||
BelPinRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
range.b.ptr = chip_info->wire_data[wire.index].bels_downhill.get();
|
||||
range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bels_downhill;
|
||||
range.b.ptr = locInfo(wire)->wire_data[wire.index].bels_downhill.get();
|
||||
range.b.wire_loc = wire.location;
|
||||
range.e.ptr = range.b.ptr + locInfo(wire)->wire_data[wire.index].num_bels_downhill;
|
||||
range.e.wire_loc = wire.location;
|
||||
return range;
|
||||
}
|
||||
|
||||
@ -471,7 +491,7 @@ struct Arch : BaseCtx
|
||||
IdString getWireName(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return id(chip_info->wire_data[wire.index].name.get());
|
||||
return id(locInfo(wire)->wire_data[wire.index].name.get());
|
||||
}
|
||||
|
||||
uint32_t getWireChecksum(WireId wire) const { return wire.index; }
|
||||
@ -479,8 +499,8 @@ struct Arch : BaseCtx
|
||||
void bindWire(WireId wire, IdString net, PlaceStrength strength)
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
NPNR_ASSERT(wire_to_net[wire.index] == IdString());
|
||||
wire_to_net[wire.index] = net;
|
||||
NPNR_ASSERT(wire_to_net[wire] == IdString());
|
||||
wire_to_net[wire] = net;
|
||||
nets[net]->wires[wire].pip = PipId();
|
||||
nets[net]->wires[wire].strength = strength;
|
||||
}
|
||||
@ -488,45 +508,55 @@ struct Arch : BaseCtx
|
||||
void unbindWire(WireId wire)
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
NPNR_ASSERT(wire_to_net[wire.index] != IdString());
|
||||
NPNR_ASSERT(wire_to_net[wire] != IdString());
|
||||
|
||||
auto &net_wires = nets[wire_to_net[wire.index]]->wires;
|
||||
auto &net_wires = nets[wire_to_net[wire]]->wires;
|
||||
auto it = net_wires.find(wire);
|
||||
NPNR_ASSERT(it != net_wires.end());
|
||||
|
||||
auto pip = it->second.pip;
|
||||
if (pip != PipId()) {
|
||||
pip_to_net[pip.index] = IdString();
|
||||
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
|
||||
pip_to_net[pip] = IdString();
|
||||
}
|
||||
|
||||
net_wires.erase(it);
|
||||
wire_to_net[wire.index] = IdString();
|
||||
wire_to_net[wire] = IdString();
|
||||
}
|
||||
|
||||
bool checkWireAvail(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return wire_to_net[wire.index] == IdString();
|
||||
return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString();
|
||||
}
|
||||
|
||||
IdString getBoundWireNet(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return wire_to_net[wire.index];
|
||||
if (wire_to_net.find(wire) == wire_to_net.end())
|
||||
return IdString();
|
||||
else
|
||||
return wire_to_net.at(wire);
|
||||
}
|
||||
|
||||
IdString getConflictingWireNet(WireId wire) const
|
||||
{
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
return wire_to_net[wire.index];
|
||||
if (wire_to_net.find(wire) == wire_to_net.end())
|
||||
return IdString();
|
||||
else
|
||||
return wire_to_net.at(wire);
|
||||
}
|
||||
|
||||
WireRange getWires() const
|
||||
{
|
||||
WireRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info->num_wires;
|
||||
range.b.cursor_tile = 0;
|
||||
range.b.cursor_index = -1;
|
||||
range.b.chip = chip_info;
|
||||
++range.b; //-1 and then ++ deals with the case of no wries in the first tile
|
||||
range.e.cursor_tile = chip_info->width * chip_info->height;
|
||||
range.e.cursor_index = 0;
|
||||
range.e.chip = chip_info;
|
||||
return range;
|
||||
}
|
||||
|
||||
@ -540,16 +570,15 @@ struct Arch : BaseCtx
|
||||
void bindPip(PipId pip, IdString net, PlaceStrength strength)
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
NPNR_ASSERT(pip_to_net[pip.index] == IdString());
|
||||
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString());
|
||||
NPNR_ASSERT(pip_to_net[pip] == IdString());
|
||||
|
||||
pip_to_net[pip.index] = net;
|
||||
switches_locked[chip_info->pip_data[pip.index].switch_index] = net;
|
||||
pip_to_net[pip] = net;
|
||||
|
||||
WireId dst;
|
||||
dst.index = chip_info->pip_data[pip.index].dst;
|
||||
NPNR_ASSERT(wire_to_net[dst.index] == IdString());
|
||||
wire_to_net[dst.index] = net;
|
||||
dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
|
||||
dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
|
||||
NPNR_ASSERT(wire_to_net[dst] == IdString());
|
||||
wire_to_net[dst] = net;
|
||||
nets[net]->wires[dst].pip = pip;
|
||||
nets[net]->wires[dst].strength = strength;
|
||||
}
|
||||
@ -557,42 +586,52 @@ struct Arch : BaseCtx
|
||||
void unbindPip(PipId pip)
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
NPNR_ASSERT(pip_to_net[pip.index] != IdString());
|
||||
NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString());
|
||||
NPNR_ASSERT(pip_to_net[pip] != IdString());
|
||||
|
||||
WireId dst;
|
||||
dst.index = chip_info->pip_data[pip.index].dst;
|
||||
NPNR_ASSERT(wire_to_net[dst.index] != IdString());
|
||||
wire_to_net[dst.index] = IdString();
|
||||
nets[pip_to_net[pip.index]]->wires.erase(dst);
|
||||
dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
|
||||
dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
|
||||
NPNR_ASSERT(wire_to_net[dst] != IdString());
|
||||
wire_to_net[dst] = IdString();
|
||||
nets[pip_to_net[pip]]->wires.erase(dst);
|
||||
|
||||
pip_to_net[pip.index] = IdString();
|
||||
switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString();
|
||||
pip_to_net[pip] = IdString();
|
||||
}
|
||||
|
||||
bool checkPipAvail(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString();
|
||||
return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString();
|
||||
}
|
||||
|
||||
IdString getBoundPipNet(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return pip_to_net[pip.index];
|
||||
if (pip_to_net.find(pip) == pip_to_net.end())
|
||||
return IdString();
|
||||
else
|
||||
return pip_to_net.at(pip);
|
||||
}
|
||||
|
||||
IdString getConflictingPipNet(PipId pip) const
|
||||
{
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
return switches_locked[chip_info->pip_data[pip.index].switch_index];
|
||||
if (pip_to_net.find(pip) == pip_to_net.end())
|
||||
return IdString();
|
||||
else
|
||||
return pip_to_net.at(pip);
|
||||
}
|
||||
|
||||
AllPipRange getPips() const
|
||||
{
|
||||
AllPipRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info->num_pips;
|
||||
range.b.cursor_tile = 0;
|
||||
range.b.cursor_index = -1;
|
||||
range.b.chip = chip_info;
|
||||
++range.b; //-1 and then ++ deals with the case of no wries in the first tile
|
||||
range.e.cursor_tile = chip_info->width * chip_info->height;
|
||||
range.e.cursor_index = 0;
|
||||
range.e.chip = chip_info;
|
||||
return range;
|
||||
}
|
||||
|
||||
@ -600,7 +639,8 @@ struct Arch : BaseCtx
|
||||
{
|
||||
WireId wire;
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
wire.index = chip_info->pip_data[pip.index].src;
|
||||
wire.index = locInfo(pip)->pip_data[pip.index].src_idx;
|
||||
wire.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_src_loc;
|
||||
return wire;
|
||||
}
|
||||
|
||||
@ -608,7 +648,8 @@ struct Arch : BaseCtx
|
||||
{
|
||||
WireId wire;
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
wire.index = chip_info->pip_data[pip.index].dst;
|
||||
wire.index = locInfo(pip)->pip_data[pip.index].dst_idx;
|
||||
wire.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
|
||||
return wire;
|
||||
}
|
||||
|
||||
@ -616,7 +657,7 @@ struct Arch : BaseCtx
|
||||
{
|
||||
DelayInfo delay;
|
||||
NPNR_ASSERT(pip != PipId());
|
||||
delay.delay = chip_info->pip_data[pip.index].delay;
|
||||
delay.delay = locInfo(pip)->pip_data[pip.index].delay;
|
||||
return delay;
|
||||
}
|
||||
|
||||
@ -624,8 +665,8 @@ struct Arch : BaseCtx
|
||||
{
|
||||
PipRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
range.b.cursor = chip_info->wire_data[wire.index].pips_downhill.get();
|
||||
range.e.cursor = range.b.cursor + chip_info->wire_data[wire.index].num_downhill;
|
||||
range.b.cursor = locInfo(wire)->wire_data[wire.index].pips_downhill.get();
|
||||
range.e.cursor = range.b.cursor + locInfo(wire)->wire_data[wire.index].num_downhill;
|
||||
return range;
|
||||
}
|
||||
|
||||
@ -633,8 +674,8 @@ struct Arch : BaseCtx
|
||||
{
|
||||
PipRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
range.b.cursor = chip_info->wire_data[wire.index].pips_uphill.get();
|
||||
range.e.cursor = range.b.cursor + chip_info->wire_data[wire.index].num_uphill;
|
||||
range.b.cursor = locInfo(wire)->wire_data[wire.index].pips_uphill.get();
|
||||
range.e.cursor = range.b.cursor + locInfo(wire)->wire_data[wire.index].num_uphill;
|
||||
return range;
|
||||
}
|
||||
|
||||
|
32
ecp5/arch_pybindings.cc
Normal file
32
ecp5/arch_pybindings.cc
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
|
||||
* Copyright (C) 2018 David Shah <dave@ds0.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NO_PYTHON
|
||||
|
||||
#include "nextpnr.h"
|
||||
#include "pybindings.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
void arch_wrap_python() {}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
31
ecp5/arch_pybindings.h
Normal file
31
ecp5/arch_pybindings.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
|
||||
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef ARCH_PYBINDINGS_H
|
||||
#define ARCH_PYBINDINGS_H
|
||||
#ifndef NO_PYTHON
|
||||
|
||||
#include "nextpnr.h"
|
||||
#include "pybindings.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
#endif
|
||||
#endif
|
@ -60,13 +60,21 @@ enum PortPin : int32_t
|
||||
PIN_MAXIDX
|
||||
};
|
||||
|
||||
NPNR_PACKED_STRUCT(struct Location {
|
||||
NPNR_PACKED_STRUCT(struct LocationPOD { int16_t x, y; });
|
||||
|
||||
struct Location
|
||||
{
|
||||
int16_t x = -1, y = -1;
|
||||
Location() : x(-1), y(-1){};
|
||||
Location(int16_t x, int16_t y) : x(x), y(y){};
|
||||
Location(const LocationPOD &pod) : x(pod.x), y(pod.y){};
|
||||
Location(const Location &loc) : x(loc.x), y(loc.y){};
|
||||
|
||||
bool operator==(const Location &other) const { return x == other.x && y == other.y; }
|
||||
bool operator!=(const Location &other) const { return x != other.x || y == other.y; }
|
||||
});
|
||||
};
|
||||
|
||||
Location operator+(const Location &a, const Location &b) { return Location{a.x + b.x, a.y + b.y};}
|
||||
Location operator+(const Location &a, const Location &b) { return Location(a.x + b.x, a.y + b.y); }
|
||||
|
||||
struct BelId
|
||||
{
|
||||
@ -91,29 +99,51 @@ struct PipId
|
||||
Location location;
|
||||
int32_t index = -1;
|
||||
|
||||
bool operator==(const WireId &other) const { return index == other.index && location == other.location; }
|
||||
bool operator!=(const WireId &other) const { return index != other.index || location != other.location; }
|
||||
bool operator==(const PipId &other) const { return index == other.index && location == other.location; }
|
||||
bool operator!=(const PipId &other) const { return index != other.index || location != other.location; }
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
namespace std {
|
||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Location>
|
||||
{
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX Location &loc) const noexcept
|
||||
{
|
||||
std::size_t seed = std::hash<int>()(loc.x);
|
||||
seed ^= std::hash<int>()(loc.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelId>
|
||||
{
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept { return hash<int>()(bel.index); }
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept
|
||||
{
|
||||
std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(bel.location);
|
||||
seed ^= std::hash<int>()(bel.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX WireId>
|
||||
{
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX WireId &wire) const noexcept
|
||||
{
|
||||
return hash<int>()(wire.index);
|
||||
std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(wire.location);
|
||||
seed ^= std::hash<int>()(wire.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PipId>
|
||||
{
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PipId &pip) const noexcept { return hash<int>()(pip.index); }
|
||||
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PipId &pip) const noexcept
|
||||
{
|
||||
std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(pip.location);
|
||||
seed ^= std::hash<int>()(pip.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelType> : hash<int>
|
||||
|
139
ecp5/main.cc
Normal file
139
ecp5/main.cc
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef MAIN_EXECUTABLE
|
||||
|
||||
#ifndef NO_GUI
|
||||
#include <QApplication>
|
||||
#include "application.h"
|
||||
#include "mainwindow.h"
|
||||
#endif
|
||||
#ifndef NO_PYTHON
|
||||
#include "pybindings.h"
|
||||
#endif
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <iostream>
|
||||
#include "log.h"
|
||||
#include "nextpnr.h"
|
||||
#include "version.h"
|
||||
|
||||
USING_NEXTPNR_NAMESPACE
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
try {
|
||||
|
||||
namespace po = boost::program_options;
|
||||
int rc = 0;
|
||||
|
||||
log_files.push_back(stdout);
|
||||
|
||||
po::options_description options("Allowed options");
|
||||
options.add_options()("help,h", "show help");
|
||||
options.add_options()("verbose,v", "verbose output");
|
||||
options.add_options()("force,f", "keep running after errors");
|
||||
#ifndef NO_GUI
|
||||
options.add_options()("gui", "start gui");
|
||||
#endif
|
||||
|
||||
po::positional_options_description pos;
|
||||
#ifndef NO_PYTHON
|
||||
options.add_options()("run", po::value<std::vector<std::string>>(), "python file to execute");
|
||||
pos.add("run", -1);
|
||||
#endif
|
||||
options.add_options()("version,V", "show version");
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::parsed_options parsed = po::command_line_parser(argc, argv).options(options).positional(pos).run();
|
||||
|
||||
po::store(parsed, vm);
|
||||
|
||||
po::notify(vm);
|
||||
}
|
||||
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("help") || argc == 1) {
|
||||
std::cout << boost::filesystem::basename(argv[0])
|
||||
<< " -- Next Generation Place and Route (git "
|
||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||
std::cout << "\n";
|
||||
std::cout << options << "\n";
|
||||
return argc != 1;
|
||||
}
|
||||
|
||||
if (vm.count("version")) {
|
||||
std::cout << boost::filesystem::basename(argv[0])
|
||||
<< " -- Next Generation Place and Route (git "
|
||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Context ctx(ArchArgs{});
|
||||
|
||||
if (vm.count("verbose")) {
|
||||
ctx.verbose = true;
|
||||
}
|
||||
|
||||
if (vm.count("force")) {
|
||||
ctx.force = true;
|
||||
}
|
||||
|
||||
if (vm.count("seed")) {
|
||||
ctx.rngseed(vm["seed"].as<int>());
|
||||
}
|
||||
|
||||
#ifndef NO_PYTHON
|
||||
if (vm.count("run")) {
|
||||
init_python(argv[0], true);
|
||||
python_export_global("ctx", ctx);
|
||||
|
||||
std::vector<std::string> files = vm["run"].as<std::vector<std::string>>();
|
||||
for (auto filename : files)
|
||||
execute_python_file(filename.c_str());
|
||||
|
||||
deinit_python();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_GUI
|
||||
if (vm.count("gui")) {
|
||||
Application a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
rc = a.exec();
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
} catch (log_execution_error_exception) {
|
||||
#if defined(_MSC_VER)
|
||||
_exit(EXIT_FAILURE);
|
||||
#else
|
||||
_Exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user