gowin: Add GUI.
* Items such as LUT, DFF, MUX, ALU, IOB are displayed; * Local wires, 1-2-4-8 wires are displayed; * The clock spines, taps and branches are displayed with some caveats. For now, you can not create a project in the GUI because of possible conflict with another PR (about GW1NR-9C support), but you can specify the board in the command line and load .JSON and .CST in the GUI. Although ALUs are displayed, but the CIN and COUT wires are not. This is still an unsolved problem. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
e069b3bc6a
commit
22e4081c73
@ -46,6 +46,8 @@ struct GraphicElement
|
||||
TYPE_BOX,
|
||||
TYPE_CIRCLE,
|
||||
TYPE_LABEL,
|
||||
TYPE_LOCAL_ARROW, // Located entirely within the cell boundaries, coordinates in the range [0., 1.]
|
||||
TYPE_LOCAL_LINE,
|
||||
|
||||
TYPE_MAX
|
||||
} type = TYPE_NONE;
|
||||
|
@ -57,6 +57,8 @@ struct SVGWriter
|
||||
switch (el.type) {
|
||||
case GraphicElement::TYPE_LINE:
|
||||
case GraphicElement::TYPE_ARROW:
|
||||
case GraphicElement::TYPE_LOCAL_LINE:
|
||||
case GraphicElement::TYPE_LOCAL_ARROW:
|
||||
out << stringf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"%s\"/>", (el.x1 + dxy.x) * scale,
|
||||
(el.y1 + dxy.y) * scale, (el.x2 + dxy.x) * scale, (el.y2 + dxy.y) * scale,
|
||||
get_stroke_colour(el.style))
|
||||
|
232
gowin/arch.cc
232
gowin/arch.cc
@ -23,6 +23,7 @@
|
||||
#include <math.h>
|
||||
#include <regex>
|
||||
#include "embed.h"
|
||||
#include "gfx.h"
|
||||
#include "nextpnr.h"
|
||||
#include "placer1.h"
|
||||
#include "placer_heap.h"
|
||||
@ -32,6 +33,148 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// GUI
|
||||
void Arch::fixClockSpineDecals(void)
|
||||
{
|
||||
for (auto sp : clockSpinesCache) {
|
||||
// row: (#of spine cells, wire_id)
|
||||
dict<int, std::pair<int, IdString>> rows;
|
||||
IdString min_x, max_x;
|
||||
min_x = max_x = *sp.second.begin();
|
||||
for (auto wire : sp.second) {
|
||||
WireInfo &wi = wire_info(wire);
|
||||
std::pair<int, IdString> &row = rows[wi.y];
|
||||
++row.first;
|
||||
row.second = wire;
|
||||
if (wi.x < wire_info(min_x).x) {
|
||||
min_x = wire;
|
||||
} else {
|
||||
if (wi.x > wire_info(max_x).x) {
|
||||
max_x = wire;
|
||||
}
|
||||
}
|
||||
}
|
||||
// central mux row owns the global decal
|
||||
int mux_row = -1;
|
||||
for (auto row : rows) {
|
||||
if (row.second.first == 1) {
|
||||
mux_row = row.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if there is no separate central mux than all decals are the same
|
||||
if (mux_row == -1) {
|
||||
mux_row = rows.begin()->first;
|
||||
WireInfo &wi = wire_info(rows.at(mux_row).second);
|
||||
GraphicElement &el_active = decal_graphics.at(wi.decalxy_active.decal).at(0);
|
||||
GraphicElement &el_inactive = decal_graphics.at(wi.decalxy_inactive.decal).at(0);
|
||||
el_active.y1 -= wi.y;
|
||||
el_active.y2 -= wi.y;
|
||||
el_inactive.y1 -= wi.y;
|
||||
el_inactive.y2 -= wi.y;
|
||||
el_active.x1 += wire_info(min_x).x;
|
||||
el_active.x2 += wire_info(max_x).x;
|
||||
el_inactive.x1 += wire_info(min_x).x;
|
||||
el_inactive.x2 += wire_info(max_x).x;
|
||||
} else {
|
||||
// change the global decal
|
||||
WireInfo &wi = wire_info(rows.at(mux_row).second);
|
||||
// clear spine decals
|
||||
float y = 0.;
|
||||
for (auto wire : sp.second) {
|
||||
if (wire == wi.name) {
|
||||
continue;
|
||||
}
|
||||
wire_info(wire).decalxy_active = DecalXY();
|
||||
wire_info(wire).decalxy_inactive = DecalXY();
|
||||
y = wire_info(wire).y;
|
||||
}
|
||||
GraphicElement &el_active = decal_graphics.at(wi.decalxy_active.decal).at(0);
|
||||
GraphicElement &el_inactive = decal_graphics.at(wi.decalxy_inactive.decal).at(0);
|
||||
el_active.y1 -= y;
|
||||
el_active.y2 -= y;
|
||||
el_inactive.y1 -= y;
|
||||
el_inactive.y2 -= y;
|
||||
el_active.x1 += wire_info(min_x).x;
|
||||
el_active.x2 += wire_info(max_x).x;
|
||||
el_inactive.x1 += wire_info(min_x).x;
|
||||
el_inactive.x2 += wire_info(max_x).x;
|
||||
}
|
||||
refreshUi();
|
||||
}
|
||||
}
|
||||
|
||||
void Arch::updateClockSpinesCache(IdString spine_id, IdString wire_id)
|
||||
{
|
||||
std::vector<IdString> &sp = clockSpinesCache[spine_id];
|
||||
if (std::find(sp.begin(), sp.end(), wire_id) == sp.end()) {
|
||||
sp.push_back(wire_id);
|
||||
}
|
||||
}
|
||||
|
||||
DecalXY Arch::getBelDecal(BelId bel) const
|
||||
{
|
||||
CellInfo *ci = getBoundBelCell(bel);
|
||||
if (ci == nullptr) {
|
||||
return bels.at(bel).decalxy_inactive;
|
||||
} else {
|
||||
// LUT + used/unused DFF
|
||||
if (bels.at(bel).type == id_SLICE) {
|
||||
DecalXY decalxy = bels.at(bel).decalxy_active;
|
||||
if (!ci->params.at(id_FF_USED).as_bool()) {
|
||||
decalxy.decal = id_DECAL_LUT_UNUSED_DFF_ACTIVE;
|
||||
if (ci->params.count(id_ALU_MODE) != 0) {
|
||||
decalxy.decal = id_DECAL_ALU_ACTIVE;
|
||||
}
|
||||
}
|
||||
return decalxy;
|
||||
}
|
||||
}
|
||||
return bels.at(bel).decalxy_active;
|
||||
}
|
||||
|
||||
DecalXY Arch::getGroupDecal(GroupId grp) const { return groups.at(grp).decalxy; }
|
||||
|
||||
DecalXY Arch::getPipDecal(PipId pip) const
|
||||
{
|
||||
if (getBoundPipNet(pip) == nullptr) {
|
||||
return pips.at(pip).decalxy_inactive;
|
||||
}
|
||||
return pips.at(pip).decalxy_active;
|
||||
}
|
||||
|
||||
DecalXY Arch::getWireDecal(WireId wire) const
|
||||
{
|
||||
static std::vector<IdString> clk_wires = {id_GB00, id_GB10, id_GB20, id_GB30, id_GB40, id_GB50, id_GB60, id_GB70};
|
||||
static std::vector<IdString> pip_dst = {id_CLK0, id_CLK1, id_CLK2, id_EW10, id_EW20, id_SN10, id_SN20};
|
||||
if (getBoundWireNet(wire) == nullptr) {
|
||||
if (std::find(clk_wires.begin(), clk_wires.end(), wires.at(wire).type) != clk_wires.end()) {
|
||||
for (auto dst : pip_dst) {
|
||||
// check if pip is used
|
||||
char pip_name[20];
|
||||
snprintf(pip_name, sizeof(pip_name), "%s_%s", wire.c_str(this), dst.c_str(this));
|
||||
if (pips.count(id(pip_name)) != 0) {
|
||||
if (getBoundPipNet(id(pip_name)) != nullptr) {
|
||||
return wires.at(wire).decalxy_active;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// spines
|
||||
if (clockSpinesCache.count(wires.at(wire).type) != 0) {
|
||||
std::vector<IdString> const &sp = clockSpinesCache.at(wires.at(wire).type);
|
||||
for (auto w : sp) {
|
||||
if (getBoundWireNet(w) != nullptr) {
|
||||
return wires.at(wire).decalxy_active;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return wires.at(wire).decalxy_inactive;
|
||||
}
|
||||
return wires.at(wire).decalxy_active;
|
||||
}
|
||||
|
||||
WireInfo &Arch::wire_info(IdString wire)
|
||||
{
|
||||
auto w = wires.find(wire);
|
||||
@ -58,7 +201,6 @@ BelInfo &Arch::bel_info(IdString bel)
|
||||
|
||||
void Arch::addWire(IdString name, IdString type, int x, int y)
|
||||
{
|
||||
// std::cout << name.str(this) << std::endl;
|
||||
NPNR_ASSERT(wires.count(name) == 0);
|
||||
WireInfo &wi = wires[name];
|
||||
wi.name = name;
|
||||
@ -105,6 +247,13 @@ void Arch::addPip(IdString name, IdString type, IdString srcWire, IdString dstWi
|
||||
tilePipDimZ[loc.x][loc.y] = std::max(tilePipDimZ[loc.x][loc.y], loc.z + 1);
|
||||
}
|
||||
|
||||
void Arch::addGroup(IdString name)
|
||||
{
|
||||
NPNR_ASSERT(groups.count(name) == 0);
|
||||
GroupInfo &gi = groups[name];
|
||||
gi.name = name;
|
||||
}
|
||||
|
||||
void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)
|
||||
{
|
||||
NPNR_ASSERT(bels.count(name) == 0);
|
||||
@ -189,24 +338,41 @@ void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
|
||||
refreshUi();
|
||||
}
|
||||
|
||||
void Arch::setWireDecal(WireId wire, DecalXY decalxy)
|
||||
void Arch::setWireDecal(WireId wire, DecalXY active, DecalXY inactive)
|
||||
{
|
||||
wire_info(wire).decalxy = decalxy;
|
||||
wire_info(wire).decalxy_active = active;
|
||||
wire_info(wire).decalxy_inactive = inactive;
|
||||
refreshUiWire(wire);
|
||||
}
|
||||
|
||||
void Arch::setPipDecal(PipId pip, DecalXY decalxy)
|
||||
void Arch::setPipDecal(PipId pip, DecalXY active, DecalXY inactive)
|
||||
{
|
||||
pip_info(pip).decalxy = decalxy;
|
||||
pip_info(pip).decalxy_active = active;
|
||||
pip_info(pip).decalxy_inactive = inactive;
|
||||
refreshUiPip(pip);
|
||||
}
|
||||
|
||||
void Arch::setBelDecal(BelId bel, DecalXY decalxy)
|
||||
void Arch::setBelDecal(BelId bel, DecalXY active, DecalXY inactive)
|
||||
{
|
||||
bel_info(bel).decalxy = decalxy;
|
||||
bel_info(bel).decalxy_active = active;
|
||||
bel_info(bel).decalxy_inactive = inactive;
|
||||
refreshUiBel(bel);
|
||||
}
|
||||
|
||||
void Arch::setDefaultDecals(void)
|
||||
{
|
||||
for (BelId bel : getBels()) {
|
||||
gfxSetBelDefaultDecal(this, bel_info(bel));
|
||||
}
|
||||
for (PipId pip : getPips()) {
|
||||
gfxSetPipDefaultDecal(this, pip_info(pip));
|
||||
}
|
||||
for (WireId wire : getWires()) {
|
||||
gfxSetWireDefaultDecal(this, wire_info(wire));
|
||||
}
|
||||
fixClockSpineDecals();
|
||||
}
|
||||
|
||||
void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
|
||||
{
|
||||
groups[group].decalxy = decalxy;
|
||||
@ -519,6 +685,7 @@ void Arch::read_cst(std::istream &in)
|
||||
insloc
|
||||
} cst_type;
|
||||
|
||||
settings.erase(id("cst"));
|
||||
while (!in.eof()) {
|
||||
std::getline(in, line);
|
||||
cst_type = ioloc;
|
||||
@ -584,6 +751,7 @@ void Arch::read_cst(std::istream &in)
|
||||
}
|
||||
}
|
||||
}
|
||||
settings[id("cst")] = 1;
|
||||
}
|
||||
|
||||
// Add all MUXes for the cell
|
||||
@ -689,6 +857,14 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
IdString::initialize_add(this, db->id_strs[i].get(), uint32_t(i) + db->num_constids);
|
||||
}
|
||||
|
||||
// Empty decal
|
||||
addDecalGraphic(IdString(), GraphicElement());
|
||||
|
||||
if (args.gui) {
|
||||
// decals
|
||||
gfxCreateBelDecals(this);
|
||||
}
|
||||
|
||||
// setup package
|
||||
IdString package_name;
|
||||
IdString device_id;
|
||||
@ -762,9 +938,17 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
// The reverse order of the enumeration simplifies the creation
|
||||
// of MUX2_LUT8s: they need the existence of the wire on the right.
|
||||
for (int i = db->rows * db->cols - 1; i >= 0; --i) {
|
||||
IdString grpname;
|
||||
int row = i / db->cols;
|
||||
int col = i % db->cols;
|
||||
const TilePOD *tile = db->grid[i].get();
|
||||
if (args.gui) {
|
||||
// CRU decal
|
||||
snprintf(buf, 32, "R%dC%d_CRU", row + 1, col + 1);
|
||||
grpname = id(buf);
|
||||
addGroup(grpname);
|
||||
setGroupDecal(grpname, gfxGetCruGroupDecalXY(col, row));
|
||||
}
|
||||
// setup wires
|
||||
const PairPOD *pips[2] = {tile->pips.get(), tile->clock_pips.get()};
|
||||
unsigned int num_pips[2] = {tile->num_pips, tile->num_clock_pips};
|
||||
@ -837,6 +1021,14 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
if (z == 0) {
|
||||
addMuxBels(db, row, col);
|
||||
}
|
||||
if (z % 2 == 0) {
|
||||
snprintf(buf, 32, "R%dC%d_LUT_GRP%d", row + 1, col + 1, z);
|
||||
grpname = id(buf);
|
||||
if (args.gui) {
|
||||
addGroup(grpname);
|
||||
setGroupDecal(grpname, gfxGetLutGroupDecalXY(col, row, z >> 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_IOBJ:
|
||||
z++; /* fall-through*/
|
||||
@ -933,7 +1125,6 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
DelayQuad delay = getWireTypeDelay(destid);
|
||||
// local alias
|
||||
auto local_alias = pairLookup(tile->aliases.get(), tile->num_aliases, srcid.index);
|
||||
// std::cout << "srcid " << srcid.str(this) << std::endl;
|
||||
if (local_alias != nullptr) {
|
||||
srcid = IdString(local_alias->src_id);
|
||||
gsrcname = wireToGlobal(srcrow, srccol, db, srcid);
|
||||
@ -950,12 +1141,14 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
srcrow = alias_src->src_row;
|
||||
srcid = IdString(alias_src->src_id);
|
||||
gsrcname = wireToGlobal(srcrow, srccol, db, srcid);
|
||||
// std::cout << buf << std::endl;
|
||||
}
|
||||
addPip(pipname, destid, gsrcname, gdestname, delay, Loc(col, row, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (args.gui) {
|
||||
setDefaultDecals();
|
||||
}
|
||||
|
||||
// Permissible combinations of modes in a single slice
|
||||
dff_comp_mode[id_DFF] = id_DFF;
|
||||
@ -1015,6 +1208,17 @@ BelId Arch::getBelByLocation(Loc loc) const
|
||||
|
||||
const std::vector<BelId> &Arch::getBelsByTile(int x, int y) const { return bels_by_tile.at(x).at(y); }
|
||||
|
||||
bool Arch::haveBelType(int x, int y, IdString bel_type)
|
||||
{
|
||||
for (auto bel : getBelsByTile(x, y)) {
|
||||
BelInfo bi = bel_info(bel);
|
||||
if (bi.type == bel_type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Arch::getBelGlobalBuf(BelId bel) const { return bels.at(bel).gb; }
|
||||
|
||||
void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
|
||||
@ -1303,6 +1507,16 @@ bool Arch::route()
|
||||
return result;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
||||
{
|
||||
if (!decal_graphics.count(decal)) {
|
||||
// XXX
|
||||
return std::vector<GraphicElement>();
|
||||
}
|
||||
return decal_graphics.at(decal);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayQuad &delay) const
|
||||
|
29
gowin/arch.h
29
gowin/arch.h
@ -176,6 +176,7 @@ struct ArchArgs
|
||||
// y = mx + c relationship between distance and delay for interconnect
|
||||
// delay estimates
|
||||
double delayScale = 0.4, delayOffset = 0.4;
|
||||
bool gui;
|
||||
};
|
||||
|
||||
struct WireInfo;
|
||||
@ -187,7 +188,7 @@ struct PipInfo
|
||||
NetInfo *bound_net;
|
||||
WireId srcWire, dstWire;
|
||||
DelayQuad delay;
|
||||
DecalXY decalxy;
|
||||
DecalXY decalxy_active, decalxy_inactive;
|
||||
Loc loc;
|
||||
};
|
||||
|
||||
@ -200,7 +201,7 @@ struct WireInfo
|
||||
BelPin uphill_bel_pin;
|
||||
std::vector<BelPin> downhill_bel_pins;
|
||||
std::vector<BelPin> bel_pins;
|
||||
DecalXY decalxy;
|
||||
DecalXY decalxy_active, decalxy_inactive;
|
||||
int x, y;
|
||||
};
|
||||
|
||||
@ -217,7 +218,7 @@ struct BelInfo
|
||||
std::map<IdString, std::string> attrs;
|
||||
CellInfo *bound_cell;
|
||||
dict<IdString, PinInfo> pins;
|
||||
DecalXY decalxy;
|
||||
DecalXY decalxy_active, decalxy_inactive;
|
||||
int x, y, z;
|
||||
bool gb;
|
||||
};
|
||||
@ -270,8 +271,6 @@ struct ArchRanges : BaseArchRanges
|
||||
using GroupWiresRangeT = const std::vector<WireId> &;
|
||||
using GroupPipsRangeT = const std::vector<PipId> &;
|
||||
using GroupGroupsRangeT = const std::vector<GroupId> &;
|
||||
// Decals
|
||||
using DecalGfxRangeT = const std::vector<GraphicElement> &;
|
||||
};
|
||||
|
||||
struct Arch : BaseArch<ArchRanges>
|
||||
@ -312,16 +311,23 @@ struct Arch : BaseArch<ArchRanges>
|
||||
void addBelOutput(IdString bel, IdString name, IdString wire);
|
||||
void addBelInout(IdString bel, IdString name, IdString wire);
|
||||
|
||||
void addGroup(IdString name);
|
||||
void addGroupBel(IdString group, IdString bel);
|
||||
void addGroupWire(IdString group, IdString wire);
|
||||
void addGroupPip(IdString group, IdString pip);
|
||||
void addGroupGroup(IdString group, IdString grp);
|
||||
|
||||
void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
|
||||
void setWireDecal(WireId wire, DecalXY decalxy);
|
||||
void setPipDecal(PipId pip, DecalXY decalxy);
|
||||
void setBelDecal(BelId bel, DecalXY decalxy);
|
||||
void setWireDecal(WireId wire, DecalXY active, DecalXY inactive);
|
||||
void setPipDecal(PipId pip, DecalXY active, DecalXY inactive);
|
||||
void setBelDecal(BelId bel, DecalXY active, DecalXY inactive);
|
||||
void setDefaultDecals(void);
|
||||
void setGroupDecal(GroupId group, DecalXY decalxy);
|
||||
std::vector<GraphicElement> getDecalGraphics(DecalId decal) const override;
|
||||
DecalXY getBelDecal(BelId bel) const override;
|
||||
DecalXY getGroupDecal(GroupId grp) const override;
|
||||
DecalXY getPipDecal(PipId pip) const override;
|
||||
DecalXY getWireDecal(WireId pip) const override;
|
||||
|
||||
void setWireAttr(IdString wire, IdString key, const std::string &value);
|
||||
void setPipAttr(IdString pip, IdString key, const std::string &value);
|
||||
@ -452,6 +458,7 @@ struct Arch : BaseArch<ArchRanges>
|
||||
// Internal usage
|
||||
void assignArchInfo() override;
|
||||
bool cellsCompatible(const CellInfo **cells, int count) const;
|
||||
bool haveBelType(int x, int y, IdString bel_type);
|
||||
// start Z for the MUX2LUT5 bels
|
||||
int const mux_0_z = 10;
|
||||
// chip db version
|
||||
@ -459,6 +466,12 @@ struct Arch : BaseArch<ArchRanges>
|
||||
|
||||
std::vector<IdString> cell_types;
|
||||
|
||||
// clock spines cache
|
||||
// spine_id : [wire_id, wire_id, ...]
|
||||
dict<IdString, std::vector<IdString>> clockSpinesCache;
|
||||
void updateClockSpinesCache(IdString spine_id, IdString wire_id);
|
||||
void fixClockSpineDecals(void);
|
||||
|
||||
// Permissible combinations of modes in a single slice
|
||||
std::map<const IdString, IdString> dff_comp_mode;
|
||||
};
|
||||
|
@ -313,6 +313,312 @@ X(COUT2)
|
||||
X(COUT3)
|
||||
X(COUT4)
|
||||
X(COUT5)
|
||||
|
||||
// wires
|
||||
// SN
|
||||
X(S10)
|
||||
X(S10_loop0)
|
||||
X(S13)
|
||||
X(S13_loop0)
|
||||
X(N10)
|
||||
X(N10_loop0)
|
||||
X(N13)
|
||||
X(N13_loop0)
|
||||
X(SN10_loop_n)
|
||||
X(SN10_loop_s)
|
||||
X(SN20_loop_n)
|
||||
X(SN20_loop_s)
|
||||
X(S20)
|
||||
X(S20_loop0)
|
||||
X(S20_loop1)
|
||||
X(S21)
|
||||
X(S21_loop0)
|
||||
X(S21_loop1)
|
||||
X(S22)
|
||||
X(S22_loop0)
|
||||
X(S22_loop1)
|
||||
X(S23)
|
||||
X(S23_loop0)
|
||||
X(S23_loop1)
|
||||
X(S24)
|
||||
X(S24_loop0)
|
||||
X(S24_loop1)
|
||||
X(S25)
|
||||
X(S25_loop0)
|
||||
X(S25_loop1)
|
||||
X(S26)
|
||||
X(S26_loop0)
|
||||
X(S26_loop1)
|
||||
X(S27)
|
||||
X(S27_loop0)
|
||||
X(S27_loop1)
|
||||
X(N20)
|
||||
X(N20_loop0)
|
||||
X(N20_loop1)
|
||||
X(N21)
|
||||
X(N21_loop0)
|
||||
X(N21_loop1)
|
||||
X(N22)
|
||||
X(N22_loop0)
|
||||
X(N22_loop1)
|
||||
X(N23)
|
||||
X(N23_loop0)
|
||||
X(N23_loop1)
|
||||
X(N24)
|
||||
X(N24_loop0)
|
||||
X(N24_loop1)
|
||||
X(N25)
|
||||
X(N25_loop0)
|
||||
X(N25_loop1)
|
||||
X(N26)
|
||||
X(N26_loop0)
|
||||
X(N26_loop1)
|
||||
X(N27)
|
||||
X(N27_loop0)
|
||||
X(N27_loop1)
|
||||
X(S80)
|
||||
X(S80_loop0)
|
||||
X(S80_loop1)
|
||||
X(S80_loop2)
|
||||
X(S80_loop3)
|
||||
X(S80_loop4)
|
||||
X(S80_loop5)
|
||||
X(S80_loop6)
|
||||
X(S80_loop7)
|
||||
X(N80)
|
||||
X(N80_loop0)
|
||||
X(N80_loop1)
|
||||
X(N80_loop2)
|
||||
X(N80_loop3)
|
||||
X(N80_loop4)
|
||||
X(N80_loop5)
|
||||
X(N80_loop6)
|
||||
X(N80_loop7)
|
||||
X(S81)
|
||||
X(S81_loop0)
|
||||
X(S81_loop1)
|
||||
X(S81_loop2)
|
||||
X(S81_loop3)
|
||||
X(S81_loop4)
|
||||
X(S81_loop5)
|
||||
X(S81_loop6)
|
||||
X(S81_loop7)
|
||||
X(N81)
|
||||
X(N81_loop0)
|
||||
X(N81_loop1)
|
||||
X(N81_loop2)
|
||||
X(N81_loop3)
|
||||
X(N81_loop4)
|
||||
X(N81_loop5)
|
||||
X(N81_loop6)
|
||||
X(N81_loop7)
|
||||
X(S82)
|
||||
X(S82_loop0)
|
||||
X(S82_loop1)
|
||||
X(S82_loop2)
|
||||
X(S82_loop3)
|
||||
X(S82_loop4)
|
||||
X(S82_loop5)
|
||||
X(S82_loop6)
|
||||
X(S82_loop7)
|
||||
X(N82)
|
||||
X(N82_loop0)
|
||||
X(N82_loop1)
|
||||
X(N82_loop2)
|
||||
X(N82_loop3)
|
||||
X(N82_loop4)
|
||||
X(N82_loop5)
|
||||
X(N82_loop6)
|
||||
X(N82_loop7)
|
||||
X(S83)
|
||||
X(S83_loop0)
|
||||
X(S83_loop1)
|
||||
X(S83_loop2)
|
||||
X(S83_loop3)
|
||||
X(S83_loop4)
|
||||
X(S83_loop5)
|
||||
X(S83_loop6)
|
||||
X(S83_loop7)
|
||||
X(N83)
|
||||
X(N83_loop0)
|
||||
X(N83_loop1)
|
||||
X(N83_loop2)
|
||||
X(N83_loop3)
|
||||
X(N83_loop4)
|
||||
X(N83_loop5)
|
||||
X(N83_loop6)
|
||||
X(N83_loop7)
|
||||
|
||||
// WE
|
||||
X(E10)
|
||||
X(E10_loop0)
|
||||
X(E13)
|
||||
X(E13_loop0)
|
||||
X(W10)
|
||||
X(W10_loop0)
|
||||
X(W13)
|
||||
X(W13_loop0)
|
||||
X(EW10_loop_w)
|
||||
X(EW10_loop_e)
|
||||
X(EW20_loop_w)
|
||||
X(EW20_loop_e)
|
||||
//
|
||||
X(E20)
|
||||
X(E20_loop0)
|
||||
X(E20_loop1)
|
||||
X(E21)
|
||||
X(E21_loop0)
|
||||
X(E21_loop1)
|
||||
X(E22)
|
||||
X(E22_loop0)
|
||||
X(E22_loop1)
|
||||
X(E23)
|
||||
X(E23_loop0)
|
||||
X(E23_loop1)
|
||||
X(E24)
|
||||
X(E24_loop0)
|
||||
X(E24_loop1)
|
||||
X(E25)
|
||||
X(E25_loop0)
|
||||
X(E25_loop1)
|
||||
X(E26)
|
||||
X(E26_loop0)
|
||||
X(E26_loop1)
|
||||
X(E27)
|
||||
X(E27_loop0)
|
||||
X(E27_loop1)
|
||||
X(W20)
|
||||
X(W20_loop0)
|
||||
X(W20_loop1)
|
||||
X(W21)
|
||||
X(W21_loop0)
|
||||
X(W21_loop1)
|
||||
X(W22)
|
||||
X(W22_loop0)
|
||||
X(W22_loop1)
|
||||
X(W23)
|
||||
X(W23_loop0)
|
||||
X(W23_loop1)
|
||||
X(W24)
|
||||
X(W24_loop0)
|
||||
X(W24_loop1)
|
||||
X(W25)
|
||||
X(W25_loop0)
|
||||
X(W25_loop1)
|
||||
X(W26)
|
||||
X(W26_loop0)
|
||||
X(W26_loop1)
|
||||
X(W27)
|
||||
X(W27_loop0)
|
||||
X(W27_loop1)
|
||||
//
|
||||
X(E80)
|
||||
X(E80_loop0)
|
||||
X(E80_loop1)
|
||||
X(E80_loop2)
|
||||
X(E80_loop3)
|
||||
X(E80_loop4)
|
||||
X(E80_loop5)
|
||||
X(E80_loop6)
|
||||
X(E80_loop7)
|
||||
X(W80)
|
||||
X(W80_loop0)
|
||||
X(W80_loop1)
|
||||
X(W80_loop2)
|
||||
X(W80_loop3)
|
||||
X(W80_loop4)
|
||||
X(W80_loop5)
|
||||
X(W80_loop6)
|
||||
X(W80_loop7)
|
||||
X(E81)
|
||||
X(E81_loop0)
|
||||
X(E81_loop1)
|
||||
X(E81_loop2)
|
||||
X(E81_loop3)
|
||||
X(E81_loop4)
|
||||
X(E81_loop5)
|
||||
X(E81_loop6)
|
||||
X(E81_loop7)
|
||||
X(W81)
|
||||
X(W81_loop0)
|
||||
X(W81_loop1)
|
||||
X(W81_loop2)
|
||||
X(W81_loop3)
|
||||
X(W81_loop4)
|
||||
X(W81_loop5)
|
||||
X(W81_loop6)
|
||||
X(W81_loop7)
|
||||
X(E82)
|
||||
X(E82_loop0)
|
||||
X(E82_loop1)
|
||||
X(E82_loop2)
|
||||
X(E82_loop3)
|
||||
X(E82_loop4)
|
||||
X(E82_loop5)
|
||||
X(E82_loop6)
|
||||
X(E82_loop7)
|
||||
X(W82)
|
||||
X(W82_loop0)
|
||||
X(W82_loop1)
|
||||
X(W82_loop2)
|
||||
X(W82_loop3)
|
||||
X(W82_loop4)
|
||||
X(W82_loop5)
|
||||
X(W82_loop6)
|
||||
X(W82_loop7)
|
||||
X(E83)
|
||||
X(E83_loop0)
|
||||
X(E83_loop1)
|
||||
X(E83_loop2)
|
||||
X(E83_loop3)
|
||||
X(E83_loop4)
|
||||
X(E83_loop5)
|
||||
X(E83_loop6)
|
||||
X(E83_loop7)
|
||||
X(W83)
|
||||
X(W83_loop0)
|
||||
X(W83_loop1)
|
||||
X(W83_loop2)
|
||||
X(W83_loop3)
|
||||
X(W83_loop4)
|
||||
X(W83_loop5)
|
||||
X(W83_loop6)
|
||||
X(W83_loop7)
|
||||
|
||||
// spines
|
||||
X(SPINE0)
|
||||
X(SPINE1)
|
||||
X(SPINE2)
|
||||
X(SPINE3)
|
||||
X(SPINE4)
|
||||
X(SPINE5)
|
||||
X(SPINE6)
|
||||
X(SPINE7)
|
||||
X(SPINE8)
|
||||
X(SPINE9)
|
||||
X(SPINE10)
|
||||
X(SPINE11)
|
||||
X(SPINE12)
|
||||
X(SPINE13)
|
||||
X(SPINE14)
|
||||
X(SPINE15)
|
||||
X(SPINE16)
|
||||
X(SPINE17)
|
||||
X(SPINE18)
|
||||
X(SPINE19)
|
||||
X(SPINE20)
|
||||
X(SPINE21)
|
||||
X(SPINE22)
|
||||
X(SPINE23)
|
||||
X(SPINE24)
|
||||
X(SPINE25)
|
||||
X(SPINE26)
|
||||
X(SPINE27)
|
||||
X(SPINE28)
|
||||
X(SPINE29)
|
||||
X(SPINE30)
|
||||
X(SPINE31)
|
||||
|
||||
// slice items
|
||||
X(SLICE)
|
||||
X(CLK)
|
||||
@ -380,6 +686,22 @@ X(GW_MUX2_LUT5)
|
||||
X(GW_MUX2_LUT6)
|
||||
X(GW_MUX2_LUT7)
|
||||
X(GW_MUX2_LUT8)
|
||||
X(I0MUX0)
|
||||
X(I1MUX0)
|
||||
X(I0MUX1)
|
||||
X(I1MUX1)
|
||||
X(I0MUX2)
|
||||
X(I1MUX2)
|
||||
X(I0MUX3)
|
||||
X(I1MUX3)
|
||||
X(I0MUX4)
|
||||
X(I1MUX4)
|
||||
X(I0MUX5)
|
||||
X(I1MUX5)
|
||||
X(I0MUX6)
|
||||
X(I1MUX6)
|
||||
X(I0MUX7)
|
||||
X(I1MUX7)
|
||||
|
||||
// ALU
|
||||
X(ALU)
|
||||
@ -464,3 +786,23 @@ X(d_f)
|
||||
X(fx_ofx1)
|
||||
X(I01)
|
||||
|
||||
// GUI
|
||||
X(DECAL_LUT_ACTIVE)
|
||||
X(DECAL_LUT_INACTIVE)
|
||||
X(DECAL_LUTDFF_ACTIVE)
|
||||
X(DECAL_LUTDFF_INACTIVE)
|
||||
X(DECAL_LUT_UNUSED_DFF_ACTIVE)
|
||||
X(DECAL_GRP_LUT)
|
||||
X(DECAL_CRU)
|
||||
X(DECAL_MUXUPPER_INACTIVE)
|
||||
X(DECAL_MUXUPPER_ACTIVE)
|
||||
X(DECAL_MUXLOWER_INACTIVE)
|
||||
X(DECAL_MUXLOWER_ACTIVE)
|
||||
X(DECAL_IOB_INACTIVE)
|
||||
X(DECAL_IOB_ACTIVE)
|
||||
X(DECAL_IOBS_INACTIVE)
|
||||
X(DECAL_IOBS_ACTIVE)
|
||||
X(DECAL_ALU_ACTIVE)
|
||||
|
||||
|
||||
|
||||
|
40
gowin/cst.cc
Normal file
40
gowin/cst.cc
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Claire Xenia Wolf <claire@yosyshq.com>
|
||||
* Copyright (C) 2018 gatecat <gatecat@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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cst.h"
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include "arch.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
bool read_cst(Context *ctx, std::istream &in)
|
||||
{
|
||||
try {
|
||||
ctx->read_cst(in);
|
||||
return true;
|
||||
} catch (log_execution_error_exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
34
gowin/cst.h
Normal file
34
gowin/cst.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Claire Xenia Wolf <claire@yosyshq.com>
|
||||
* Copyright (C) 2018 gatecat <gatecat@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 CST_H
|
||||
#define CST_H
|
||||
|
||||
#include <iostream>
|
||||
#include "nextpnr.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// Read the constraints file
|
||||
bool read_cst(Context *ctx, std::istream &in);
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
932
gowin/gfx.cc
Normal file
932
gowin/gfx.cc
Normal file
@ -0,0 +1,932 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 Claire Xenia Wolf <claire@yosyshq.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 <boost/algorithm/string.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
const int PIP_SRC_DST_LEN = 20;
|
||||
|
||||
static void get_pip_xy(CruSide side, float &off, float &x, float &y)
|
||||
{
|
||||
switch (side) {
|
||||
case Top:
|
||||
x = off;
|
||||
y = cru_y + cru_h;
|
||||
break;
|
||||
case Bottom:
|
||||
x = off;
|
||||
y = cru_y;
|
||||
break;
|
||||
case Left:
|
||||
x = cru_x;
|
||||
y = off;
|
||||
break;
|
||||
case Right:
|
||||
x = cru_x + cru_w;
|
||||
y = off;
|
||||
break;
|
||||
case Center:
|
||||
x = cru_x + cru_w / 2.f;
|
||||
y = off;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gfxSetPipDefaultDecal(Arch *arch, PipInfo &pip)
|
||||
{
|
||||
DecalXY active, inactive;
|
||||
std::vector<std::string> split_res;
|
||||
IdString src_loc_id, dst_loc_id;
|
||||
char buf[PIP_SRC_DST_LEN];
|
||||
|
||||
active.x = inactive.x = pip.loc.x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - pip.loc.y;
|
||||
boost::split(split_res, pip.name.str(arch), [](char c) { return c == '_'; });
|
||||
src_loc_id = arch->id(split_res.at(1));
|
||||
dst_loc_id = arch->id(split_res.at(2));
|
||||
snprintf(buf, PIP_SRC_DST_LEN, "%s_%s_active", src_loc_id.c_str(arch), dst_loc_id.c_str(arch));
|
||||
IdString active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, PIP_SRC_DST_LEN, "%s_%s_inactive", src_loc_id.c_str(arch), dst_loc_id.c_str(arch));
|
||||
IdString inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
// clock?
|
||||
if (dst_loc_id == id_GT00 || dst_loc_id == id_GT10) {
|
||||
WireInfo &wi = arch->wire_info(pip.srcWire);
|
||||
if (wi.type.str(arch).substr(0, 3) != "UNK") {
|
||||
// create pip
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::TYPE_LOCAL_LINE;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
if (dst_loc_id == id_GT00) {
|
||||
el.x1 = WIRE_X(CLK_GT00_X);
|
||||
} else {
|
||||
el.x1 = WIRE_X(CLK_GT10_X);
|
||||
}
|
||||
el.x2 = el.x1 + spine_pip_off;
|
||||
el.y2 = spineY.at(arch->wire_info(pip.srcWire).type);
|
||||
el.y1 = el.y2 - spine_pip_off;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
} else {
|
||||
// XXX
|
||||
if (pipPoint.count(src_loc_id) == 0 || pipPoint.count(dst_loc_id) == 0) {
|
||||
// std::cout << "*R" << pip.loc.y + 1 << "C" << pip.loc.x + 1 << " no " << pip.name.str(arch) << " " <<
|
||||
// buf << std::endl;
|
||||
} else {
|
||||
GraphicElement el;
|
||||
el.type = GraphicElement::TYPE_LOCAL_ARROW;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
CruSide srcSide = pipPoint.at(src_loc_id).first;
|
||||
float srcOff = pipPoint.at(src_loc_id).second;
|
||||
CruSide dstSide = pipPoint.at(dst_loc_id).first;
|
||||
float dstOff = pipPoint.at(dst_loc_id).second;
|
||||
if (srcSide != dstSide) {
|
||||
get_pip_xy(srcSide, srcOff, el.x1, el.y1);
|
||||
get_pip_xy(dstSide, dstOff, el.x2, el.y2);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
} else {
|
||||
get_pip_xy(srcSide, srcOff, el.x1, el.y1);
|
||||
float dst_x = 0, dst_y = 0, m_x = 0, m_y = 0;
|
||||
get_pip_xy(dstSide, dstOff, dst_x, dst_y);
|
||||
switch (dstSide) {
|
||||
case Top:
|
||||
m_x = el.x1 + (dst_x - el.x1) / 2.f;
|
||||
m_y = dst_y - std::max(cru_h * 0.1f, std::min(cru_h * 0.4f, std::abs(el.x1 - dst_x)));
|
||||
break;
|
||||
case Bottom:
|
||||
m_x = el.x1 + (dst_x - el.x1) / 2.f;
|
||||
m_y = dst_y + std::max(cru_h * 0.1f, std::min(cru_h * 0.4f, std::abs(el.x1 - dst_x)));
|
||||
break;
|
||||
case Right:
|
||||
m_x = dst_x - std::max(cru_w * 0.1f, std::min(cru_w * 0.4f, std::abs(el.y1 - dst_y)));
|
||||
m_y = el.y1 + (dst_y - el.y1) / 2.f;
|
||||
break;
|
||||
case Left:
|
||||
m_x = dst_x + std::max(cru_w * 0.1f, std::min(cru_w * 0.4f, std::abs(el.y1 - dst_y)));
|
||||
m_y = el.y1 + (dst_y - el.y1) / 2.f;
|
||||
break;
|
||||
default: // unreachable
|
||||
break;
|
||||
}
|
||||
el.x2 = m_x;
|
||||
el.y2 = m_y;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = m_x;
|
||||
el.y1 = m_y;
|
||||
el.x2 = dst_x;
|
||||
el.y2 = dst_y;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arch->setPipDecal(pip.name, active, inactive);
|
||||
}
|
||||
|
||||
const int WIRE_ID_LEN = 30;
|
||||
|
||||
void gfxSetWireDefaultDecal(Arch *arch, WireInfo &wire)
|
||||
{
|
||||
DecalXY active, inactive;
|
||||
IdString active_id, inactive_id;
|
||||
GraphicElement el;
|
||||
std::vector<std::string> split_res;
|
||||
char buf[WIRE_ID_LEN];
|
||||
|
||||
if (std::find(decalless_wires.begin(), decalless_wires.end(), wire.name) != decalless_wires.end()) {
|
||||
arch->setWireDecal(wire.type, DecalXY(), DecalXY());
|
||||
return;
|
||||
}
|
||||
// local to cell
|
||||
if (arch->haveBelType(wire.x, wire.y, id_SLICE) && sliceLocalWires.count(wire.type) != 0) {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.type.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "%s_inactive", wire.type.c_str(arch));
|
||||
inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = wire.x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - wire.y;
|
||||
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LOCAL_LINE;
|
||||
for (auto seg : sliceLocalWires.at(wire.type)) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = std::get<0>(seg);
|
||||
el.y1 = std::get<1>(seg);
|
||||
el.x2 = std::get<2>(seg);
|
||||
el.y2 = std::get<3>(seg);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
}
|
||||
// spines
|
||||
if (spineY.count(wire.type) != 0) {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.type.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "%s_inactive", wire.type.c_str(arch));
|
||||
inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = 0.;
|
||||
active.y = inactive.y = 0.;
|
||||
|
||||
// update clock spines cache
|
||||
arch->updateClockSpinesCache(wire.type, wire.name);
|
||||
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = 0.2; // cell's x will be added later in fixClockSpineDecals
|
||||
el.x2 = 0.7; // cell's x will be added later in fixClockSpineDecals
|
||||
el.y1 = spineY.at(wire.type) + arch->gridDimY - 1.; // cell's y will be added later in fixClockSpineDecals
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
}
|
||||
|
||||
// global simple wires like IMUX
|
||||
if (globalSimpleWires.count(wire.type) != 0) {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.name.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "%s_inactive", wire.name.c_str(arch));
|
||||
inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = 0;
|
||||
active.y = inactive.y = 0;
|
||||
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
for (auto seg : globalSimpleWires.at(wire.type)) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = std::get<0>(seg) + wire.x;
|
||||
el.y1 = std::get<1>(seg) + arch->gridDimY - 1. - wire.y;
|
||||
el.x2 = std::get<2>(seg) + wire.x;
|
||||
el.y2 = std::get<3>(seg) + arch->gridDimY - 1. - wire.y;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
}
|
||||
|
||||
// global
|
||||
boost::split(split_res, wire.name.str(arch), [](char c) { return c == '_'; });
|
||||
if (split_res.size() >= 2) {
|
||||
IdString wire_id = arch->id(split_res.at(1));
|
||||
// wrap
|
||||
if ((wire.y == (arch->gridDimY - 1) && split_res.at(1).at(0) == 'S') ||
|
||||
(wire.y == 0 && split_res.at(1).at(0) == 'N')) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop0");
|
||||
}
|
||||
if ((wire.x == (arch->gridDimX - 1) && split_res.at(1).at(0) == 'E') ||
|
||||
(wire.x == 0 && split_res.at(1).at(0) == 'W')) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop0");
|
||||
}
|
||||
// SN wires
|
||||
if (split_res.at(1).substr(0, 2) == "SN") {
|
||||
if (wire.y == 0) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop_n");
|
||||
} else {
|
||||
if (wire.y == (arch->gridDimY - 1)) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop_s");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// wrap 2 hop
|
||||
if ((wire.y == (arch->gridDimY - 2) && split_res.at(1).substr(0, 2) == "S2") ||
|
||||
(wire.y == 1 && split_res.at(1).substr(0, 2) == "N2")) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop1");
|
||||
}
|
||||
// wrap 4 hop
|
||||
if (split_res.at(1).substr(0, 2) == "S8" || split_res.at(1).substr(0, 2) == "N8") {
|
||||
char loop_buf[5 + 2];
|
||||
if (split_res.at(1).substr(0, 2) == "N8") {
|
||||
if (wire.y < 8) {
|
||||
snprintf(loop_buf, sizeof(loop_buf), "_loop%1u", wire.y);
|
||||
wire_id = arch->id(split_res.at(1) + loop_buf);
|
||||
}
|
||||
} else {
|
||||
if (arch->gridDimY - 1 - wire.y < 8) {
|
||||
snprintf(loop_buf, sizeof(loop_buf), "_loop%1u", arch->gridDimY - 1 - wire.y);
|
||||
wire_id = arch->id(split_res.at(1) + loop_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// EW wires
|
||||
if (split_res.at(1).substr(0, 2) == "EW") {
|
||||
if (wire.x == 0) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop_w");
|
||||
} else {
|
||||
if (wire.x == (arch->gridDimX - 1)) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop_e");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// wrap 2 hop
|
||||
if ((wire.x == (arch->gridDimX - 2) && split_res.at(1).substr(0, 2) == "E2") ||
|
||||
(wire.x == 1 && split_res.at(1).substr(0, 2) == "W2")) {
|
||||
wire_id = arch->id(split_res.at(1) + "_loop1");
|
||||
}
|
||||
// wrap 4 hop
|
||||
if (split_res.at(1).substr(0, 2) == "E8" || split_res.at(1).substr(0, 2) == "W8") {
|
||||
char loop_buf[5 + 2];
|
||||
if (split_res.at(1).substr(0, 2) == "W8") {
|
||||
if (wire.x < 8) {
|
||||
snprintf(loop_buf, sizeof(loop_buf), "_loop%1u", wire.x);
|
||||
wire_id = arch->id(split_res.at(1) + loop_buf);
|
||||
}
|
||||
} else {
|
||||
if (arch->gridDimX - 1 - wire.x < 8) {
|
||||
snprintf(loop_buf, sizeof(loop_buf), "_loop%1u", arch->gridDimX - 1 - wire.x);
|
||||
wire_id = arch->id(split_res.at(1) + loop_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// really create decal
|
||||
if (globalWires.count(wire_id) != 0) {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.name.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "%s_inactive", wire.name.c_str(arch));
|
||||
inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = 0;
|
||||
active.y = inactive.y = 0;
|
||||
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
for (auto seg : globalWires.at(wire_id)) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = std::get<0>(seg) + wire.x;
|
||||
el.y1 = std::get<1>(seg) + arch->gridDimY - 1. - wire.y;
|
||||
el.x2 = std::get<2>(seg) + wire.x;
|
||||
el.y2 = std::get<3>(seg) + arch->gridDimY - 1. - wire.y;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
}
|
||||
// clock branches
|
||||
// # of rows is unknown so generate wire ids at runtime
|
||||
if (split_res.at(1).substr(0, 3) == "GBO") {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.name.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
inactive_id = IdString();
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = 0;
|
||||
active.y = inactive.y = 0;
|
||||
|
||||
float pip_x = PIP_X(id_GBO0);
|
||||
float line_y = WIRE_Y(CLK_GBO0_Y) + arch->gridDimY - 1. - wire.y;
|
||||
float line_0 = WIRE_Y(0) + arch->gridDimY - 1. - wire.y;
|
||||
if (split_res.at(1).at(3) == '1') {
|
||||
pip_x = PIP_X(id_GBO1);
|
||||
line_y = WIRE_Y(CLK_GBO1_Y) + arch->gridDimY - 1. - wire.y;
|
||||
}
|
||||
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = wire.x + pip_x;
|
||||
el.y1 = line_y;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = line_0;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = pip_x;
|
||||
el.y1 = line_y;
|
||||
el.x2 = pip_x + arch->gridDimX - 1.;
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
} else {
|
||||
if (split_res.at(1).substr(0, 2) == "GT") {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.name.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
// snprintf(buf, sizeof(buf), "%s_inactive", wire.name.c_str(arch));
|
||||
// inactive_id = arch->id(buf);
|
||||
inactive_id = IdString();
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = 0;
|
||||
active.y = inactive.y = 0;
|
||||
|
||||
float pip_y = PIP_Y(id_GT00);
|
||||
float line_x = WIRE_X(CLK_GT00_X) + wire.x;
|
||||
float line_0 = WIRE_X(0) + wire.x;
|
||||
if (split_res.at(1).at(2) == '1') {
|
||||
pip_y = PIP_Y(id_GT10);
|
||||
line_x = WIRE_X(CLK_GT10_X) + wire.x;
|
||||
}
|
||||
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = line_x;
|
||||
el.y1 = pip_y + arch->gridDimY - 1.;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = pip_y;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
|
||||
for (int i = 0; i <= arch->gridDimY - 1; ++i) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = line_x;
|
||||
el.y1 = pip_y + arch->gridDimY - 1. - i;
|
||||
el.x2 = line_0;
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_HIDDEN;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
} else {
|
||||
if (split_res.at(1).substr(0, 2) == "GB") {
|
||||
snprintf(buf, sizeof(buf), "%s_active", wire.name.c_str(arch));
|
||||
active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "%s_inactive", wire.name.c_str(arch));
|
||||
inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = 0;
|
||||
active.y = inactive.y = 0;
|
||||
|
||||
float line_y = WIRE_Y(CLK_GBO0_Y) + arch->gridDimY - 1. - wire.y;
|
||||
float line_0 = WIRE_Y(0) + arch->gridDimY - 1. - wire.y;
|
||||
float pip_x = PIP_X(arch->id(split_res.at(1)));
|
||||
if (split_res.at(1).at(2) >= '4') {
|
||||
line_y = WIRE_Y(CLK_GBO1_Y) + arch->gridDimY - 1. - wire.y;
|
||||
}
|
||||
|
||||
// create if absent
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = wire.x + pip_x;
|
||||
el.y1 = line_y;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = line_0;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
arch->setWireDecal(wire.name, active, inactive);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// std::cout << wire.name.str(arch) << ":" << wire.type.str(arch) << " R" << wire.y + 1 << "C" << wire.x + 1 <<
|
||||
// std::endl;
|
||||
}
|
||||
|
||||
void gfxCreateBelDecals(Arch *arch)
|
||||
{
|
||||
GraphicElement el;
|
||||
// LUTs
|
||||
el.type = GraphicElement::TYPE_BOX;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = lut_x;
|
||||
el.x2 = el.x1 + lut_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = el.y1 + lut_h;
|
||||
arch->addDecalGraphic(id_DECAL_LUT_ACTIVE, el);
|
||||
arch->addDecalGraphic(id_DECAL_LUTDFF_ACTIVE, el);
|
||||
arch->addDecalGraphic(id_DECAL_LUT_UNUSED_DFF_ACTIVE, el);
|
||||
arch->addDecalGraphic(id_DECAL_ALU_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_LUT_INACTIVE, el);
|
||||
arch->addDecalGraphic(id_DECAL_LUTDFF_INACTIVE, el);
|
||||
el.x1 = dff_x;
|
||||
el.x2 = el.x1 + dff_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = el.y1 + lut_h;
|
||||
arch->addDecalGraphic(id_DECAL_LUTDFF_INACTIVE, el);
|
||||
arch->addDecalGraphic(id_DECAL_LUT_UNUSED_DFF_ACTIVE, el);
|
||||
arch->addDecalGraphic(id_DECAL_ALU_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_LUTDFF_ACTIVE, el);
|
||||
el.type = GraphicElement::TYPE_LOCAL_LINE;
|
||||
el.x1 = lut_x + 0.33f * lut_w;
|
||||
el.x2 = el.x1 + 0.33f * lut_w;
|
||||
el.y1 = 0.66f * lut_h;
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(id_DECAL_ALU_ACTIVE, el);
|
||||
el.y1 = 0.3f * lut_h;
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(id_DECAL_ALU_ACTIVE, el);
|
||||
el.x1 = lut_x + 0.5f * lut_w;
|
||||
el.x2 = el.x1;
|
||||
el.y1 = 0.5f * lut_h;
|
||||
el.y2 = el.y1 + 0.33f * lut_h;
|
||||
arch->addDecalGraphic(id_DECAL_ALU_ACTIVE, el);
|
||||
|
||||
// LUT group
|
||||
el.type = GraphicElement::TYPE_BOX;
|
||||
el.style = GraphicElement::STYLE_FRAME;
|
||||
el.x1 = grp_lut_x;
|
||||
el.x2 = el.x1 + grp_lut_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = el.y1 + grp_lut_h;
|
||||
arch->addDecalGraphic(id_DECAL_GRP_LUT, el);
|
||||
|
||||
// CRU group
|
||||
el.type = GraphicElement::TYPE_BOX;
|
||||
el.style = GraphicElement::STYLE_FRAME;
|
||||
el.x1 = cru_x;
|
||||
el.x2 = el.x1 + cru_w;
|
||||
el.y1 = cru_y;
|
||||
el.y2 = el.y1 + cru_h;
|
||||
arch->addDecalGraphic(id_DECAL_CRU, el);
|
||||
|
||||
// Mux with upper 1 input
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.;
|
||||
el.x2 = mux_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = mux_f;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = el.x2;
|
||||
el.y1 = el.y2;
|
||||
el.y2 = mux_h - mux_f;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x2 = 0.;
|
||||
el.y1 = el.y2;
|
||||
el.y2 = mux_h;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = el.x2;
|
||||
el.y1 = mux_h;
|
||||
el.y2 = 0.;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
// 1
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.0038;
|
||||
el.x2 = 0.0118;
|
||||
el.y1 = el.y2 = 0.0598;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = (el.x1 + el.x2) / 2.;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = 0.0808;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x2 = 0.0038;
|
||||
el.y1 = el.y2;
|
||||
el.y2 = 0.0797;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXUPPER_ACTIVE, el);
|
||||
|
||||
// Mux with lower 1 input
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.;
|
||||
el.x2 = mux_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = mux_f;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = el.x2;
|
||||
el.y1 = el.y2;
|
||||
el.y2 = mux_h - mux_f;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x2 = 0.;
|
||||
el.y1 = el.y2;
|
||||
el.y2 = mux_h;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = el.x2;
|
||||
el.y1 = mux_h;
|
||||
el.y2 = 0.;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
// 1
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.0038;
|
||||
el.x2 = 0.0118;
|
||||
el.y1 = el.y2 = 0.0140;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = (el.x1 + el.x2) / 2.;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = 0.0352;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x2 = 0.0038;
|
||||
el.y1 = el.y2;
|
||||
el.y2 = 0.0341;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_MUXLOWER_ACTIVE, el);
|
||||
|
||||
// IOB
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.;
|
||||
el.x2 = io_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = el.x2;
|
||||
el.y2 = io_h;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.;
|
||||
el.y1 = el.y2;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = 0.;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = io_w;
|
||||
el.x2 = io_w * 1.3f;
|
||||
el.y2 = el.y1 = io_h / 2.f;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOB_ACTIVE, el);
|
||||
|
||||
// IOBS
|
||||
el.type = GraphicElement::TYPE_LINE;
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.;
|
||||
el.x2 = ios_w;
|
||||
el.y1 = 0.;
|
||||
el.y2 = el.y1;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = el.x2;
|
||||
el.y2 = ios_h;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = 0.;
|
||||
el.y1 = el.y2;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = 0.;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_ACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
el.x1 = ios_w;
|
||||
el.x2 = ios_w * 1.3f;
|
||||
el.y2 = el.y1 = ios_h / 2.f;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_INACTIVE, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
arch->addDecalGraphic(id_DECAL_IOBS_ACTIVE, el);
|
||||
}
|
||||
|
||||
void gfxSetBelDefaultDecal(Arch *arch, BelInfo &bel)
|
||||
{
|
||||
DecalXY active, inactive;
|
||||
switch (bel.type.hash()) {
|
||||
case ID_SLICE:
|
||||
active.x = inactive.x = bel.x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + lut_y[bel.z];
|
||||
if (bel.z < 6) {
|
||||
active.decal = id_DECAL_LUTDFF_ACTIVE;
|
||||
inactive.decal = id_DECAL_LUTDFF_INACTIVE;
|
||||
} else {
|
||||
active.decal = id_DECAL_LUT_ACTIVE;
|
||||
inactive.decal = id_DECAL_LUT_INACTIVE;
|
||||
}
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
break;
|
||||
case ID_GW_MUX2_LUT5:
|
||||
active.x = inactive.x = bel.x + mux2lut5_x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + mux2lut5_y[(bel.z - arch->mux_0_z) >> 1];
|
||||
active.decal = id_DECAL_MUXUPPER_ACTIVE;
|
||||
inactive.decal = id_DECAL_MUXUPPER_INACTIVE;
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
break;
|
||||
case ID_GW_MUX2_LUT6:
|
||||
active.x = inactive.x = bel.x + mux2lut6_x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + mux2lut6_y[(bel.z - arch->mux_0_z) / 5];
|
||||
active.decal = id_DECAL_MUXLOWER_ACTIVE;
|
||||
inactive.decal = id_DECAL_MUXLOWER_INACTIVE;
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
break;
|
||||
case ID_GW_MUX2_LUT7:
|
||||
active.x = inactive.x = bel.x + mux2lut7_x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + mux2lut7_y;
|
||||
active.decal = id_DECAL_MUXLOWER_ACTIVE;
|
||||
inactive.decal = id_DECAL_MUXLOWER_INACTIVE;
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
break;
|
||||
case ID_GW_MUX2_LUT8:
|
||||
active.x = inactive.x = bel.x + mux2lut8_x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + mux2lut8_y;
|
||||
active.decal = id_DECAL_MUXUPPER_ACTIVE;
|
||||
inactive.decal = id_DECAL_MUXUPPER_INACTIVE;
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
break;
|
||||
case ID_IOB:
|
||||
active.x = inactive.x = bel.x + io_x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + io_y + bel.z * (2 * io_gap + io_h);
|
||||
active.decal = id_DECAL_IOB_ACTIVE;
|
||||
inactive.decal = id_DECAL_IOB_INACTIVE;
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
gfxSetIOBWireDecals(arch, bel);
|
||||
break;
|
||||
case ID_IOBS:
|
||||
active.x = inactive.x = bel.x + ios_x + (ios_w + ios_gap_x) * (bel.z % 3);
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y + ios_y + (ios_h + ios_gap_y) * (bel.z / 3);
|
||||
active.decal = id_DECAL_IOBS_ACTIVE;
|
||||
inactive.decal = id_DECAL_IOBS_INACTIVE;
|
||||
arch->setBelDecal(bel.name, active, inactive);
|
||||
gfxSetIOBSWireDecals(arch, bel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gfxSetIOBWireDecals(Arch *arch, BelInfo &bel)
|
||||
{
|
||||
DecalXY active, inactive;
|
||||
GraphicElement el;
|
||||
char buf[20];
|
||||
|
||||
// set decals for I, O and OE input wires
|
||||
for (auto pi : bel.pins) {
|
||||
WireInfo &wi = arch->wire_info(pi.second.wire);
|
||||
// decal name: wire_port_z_active|inactive
|
||||
snprintf(buf, sizeof(buf), "%s_%s_%u_active", wi.type.c_str(arch), pi.first.c_str(arch), bel.z);
|
||||
IdString active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "%s_%s_%u_inactive", wi.type.c_str(arch), pi.first.c_str(arch), bel.z);
|
||||
IdString inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = bel.x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y;
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
el.type = GraphicElement::TYPE_LOCAL_LINE;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = cru_x + cru_w;
|
||||
el.y1 = pipPoint.at(wi.type).second;
|
||||
el.x2 = io_x;
|
||||
el.y2 = portPoint.at(pi.first) + io_y + bel.z * (2 * io_gap + io_h);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
for (auto seg : portSign.at(pi.first)) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = std::get<0>(seg) + io_x;
|
||||
el.y1 = std::get<1>(seg) + io_y + bel.z * (2 * io_gap + io_h);
|
||||
el.x2 = std::get<2>(seg) + io_x;
|
||||
el.y2 = std::get<3>(seg) + io_y + bel.z * (2 * io_gap + io_h);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
arch->setWireDecal(wi.name, active, inactive);
|
||||
}
|
||||
}
|
||||
|
||||
void gfxSetIOBSWireDecals(Arch *arch, BelInfo &bel)
|
||||
{
|
||||
DecalXY active, inactive;
|
||||
GraphicElement el;
|
||||
char buf[20];
|
||||
|
||||
// set decals for I, O and OE input wires
|
||||
for (auto pi : bel.pins) {
|
||||
WireInfo &wi = arch->wire_info(pi.second.wire);
|
||||
// decal name: ios_wire_port_z_active|inactive
|
||||
snprintf(buf, sizeof(buf), "ios_%s_%s_%u_active", wi.type.c_str(arch), pi.first.c_str(arch), bel.z);
|
||||
IdString active_id = arch->id(buf);
|
||||
active.decal = active_id;
|
||||
snprintf(buf, sizeof(buf), "ios_%s_%s_%u_inactive", wi.type.c_str(arch), pi.first.c_str(arch), bel.z);
|
||||
IdString inactive_id = arch->id(buf);
|
||||
inactive.decal = inactive_id;
|
||||
active.x = inactive.x = bel.x;
|
||||
active.y = inactive.y = arch->gridDimY - 1. - bel.y;
|
||||
if (arch->decal_graphics.count(active_id) == 0) {
|
||||
// leftmost wires
|
||||
el.type = GraphicElement::TYPE_LOCAL_LINE;
|
||||
if (bel.z % 3 == 0) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = cru_x + cru_w;
|
||||
el.y1 = pipPoint.at(wi.type).second;
|
||||
el.x2 = ios_x;
|
||||
el.y2 = ios_scl * portPoint.at(pi.first) + ios_y + (ios_h + ios_gap_y) * (bel.z / 3);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
} else {
|
||||
float col = (bel.z % 3) - 1;
|
||||
float rel_port = portPoint.at(pi.first) / io_h;
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = cru_x + cru_w;
|
||||
el.y1 = pipPoint.at(wi.type).second;
|
||||
el.x2 = ios_x * (0.97 - 0.02 * col);
|
||||
el.y2 = (rel_port + col) * 0.5 * ios_gap_y + ios_y + ios_h + (ios_h + ios_gap_y) * (bel.z / 3);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = ios_x + (ios_w + ios_gap_x) * (col + 1) - ios_gap_x + ios_w * 0.3 +
|
||||
rel_port * (ios_gap_x - 0.3 * ios_w);
|
||||
el.y1 = el.y2;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x2 = el.x1;
|
||||
el.y2 = ios_scl * portPoint.at(pi.first) + ios_y + (ios_h + ios_gap_y) * (bel.z / 3);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = ios_x + (ios_w + ios_gap_x) * (col + 1);
|
||||
el.y1 = el.y2;
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
}
|
||||
// signs
|
||||
for (auto seg : portSign.at(pi.first)) {
|
||||
el.style = GraphicElement::STYLE_ACTIVE;
|
||||
el.x1 = ios_scl * std::get<0>(seg) + ios_x + (ios_w + ios_gap_x) * (bel.z % 3);
|
||||
el.y1 = ios_scl * std::get<1>(seg) + ios_y + (ios_h + ios_gap_y) * (bel.z / 3);
|
||||
el.x2 = ios_scl * std::get<2>(seg) + ios_x + (ios_w + ios_gap_x) * (bel.z % 3);
|
||||
el.y2 = ios_scl * std::get<3>(seg) + ios_y + (ios_h + ios_gap_y) * (bel.z / 3);
|
||||
arch->addDecalGraphic(active_id, el);
|
||||
el.style = GraphicElement::STYLE_INACTIVE;
|
||||
arch->addDecalGraphic(inactive_id, el);
|
||||
}
|
||||
}
|
||||
arch->setWireDecal(wi.name, active, inactive);
|
||||
}
|
||||
}
|
||||
|
||||
DecalXY gfxGetLutGroupDecalXY(int x, int y, int z)
|
||||
{
|
||||
DecalXY decalxy;
|
||||
decalxy.decal = id_DECAL_GRP_LUT;
|
||||
decalxy.x = x;
|
||||
decalxy.y = y + grp_lut_y[z];
|
||||
return decalxy;
|
||||
}
|
||||
|
||||
DecalXY gfxGetCruGroupDecalXY(int x, int y)
|
||||
{
|
||||
DecalXY decalxy;
|
||||
decalxy.decal = id_DECAL_CRU;
|
||||
decalxy.x = x;
|
||||
decalxy.y = y;
|
||||
return decalxy;
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
4935
gowin/gfx.h
Normal file
4935
gowin/gfx.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -61,6 +61,7 @@ std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Pr
|
||||
log_error("Invalid device %s\n", device.c_str());
|
||||
}
|
||||
ArchArgs chipArgs;
|
||||
chipArgs.gui = vm.count("gui") != 0;
|
||||
char buf[36];
|
||||
// GW1N and GW1NR variants share the same database.
|
||||
// Most Gowin devices are a System in Package with some SDRAM wirebonded to a GPIO bank.
|
||||
|
@ -317,6 +317,12 @@ void DesignWidget::newContext(Context *ctx)
|
||||
for (const auto &wire : ctx->getWires()) {
|
||||
wireMap[std::pair<int, int>(wire.location.x, wire.location.y)].push_back(wire);
|
||||
}
|
||||
#endif
|
||||
#ifdef ARCH_GOWIN
|
||||
for (const auto &wire : ctx->getWires()) {
|
||||
WireInfo wi = ctx->wire_info(wire);
|
||||
wireMap[std::pair<int, int>(wi.x, wi.y)].push_back(wire);
|
||||
}
|
||||
#endif
|
||||
auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
|
||||
getTreeByElementType(ElementType::WIRE)
|
||||
|
@ -129,40 +129,47 @@ float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy)
|
||||
|
||||
// Go over its' GraphicElements, and calculate the distance to them.
|
||||
std::vector<float> distances;
|
||||
std::transform(graphics.begin(), graphics.end(), std::back_inserter(distances),
|
||||
[&](const GraphicElement &ge) -> float {
|
||||
switch (ge.type) {
|
||||
case GraphicElement::TYPE_BOX: {
|
||||
// If outside the box, return unit distance to closest border.
|
||||
float outside_x = -1, outside_y = -1;
|
||||
if (dx < ge.x1 || dx > ge.x2) {
|
||||
outside_x = std::min(std::abs(dx - ge.x1), std::abs(dx - ge.x2));
|
||||
}
|
||||
if (dy < ge.y1 || dy > ge.y2) {
|
||||
outside_y = std::min(std::abs(dy - ge.y1), std::abs(dy - ge.y2));
|
||||
}
|
||||
if (outside_x != -1 && outside_y != -1)
|
||||
return std::min(outside_x, outside_y);
|
||||
std::transform(
|
||||
graphics.begin(), graphics.end(), std::back_inserter(distances), [&](const GraphicElement &ge) -> float {
|
||||
switch (ge.type) {
|
||||
case GraphicElement::TYPE_BOX: {
|
||||
// If outside the box, return unit distance to closest border.
|
||||
float outside_x = -1, outside_y = -1;
|
||||
if (dx < ge.x1 || dx > ge.x2) {
|
||||
outside_x = std::min(std::abs(dx - ge.x1), std::abs(dx - ge.x2));
|
||||
}
|
||||
if (dy < ge.y1 || dy > ge.y2) {
|
||||
outside_y = std::min(std::abs(dy - ge.y1), std::abs(dy - ge.y2));
|
||||
}
|
||||
if (outside_x != -1 && outside_y != -1)
|
||||
return std::min(outside_x, outside_y);
|
||||
|
||||
// If in box, return 0.
|
||||
return 0;
|
||||
}
|
||||
case GraphicElement::TYPE_LINE:
|
||||
case GraphicElement::TYPE_ARROW: {
|
||||
// Return somewhat primitively calculated distance to segment.
|
||||
// TODO(q3k): consider coming up with a better algorithm
|
||||
QVector2D w(wx, wy);
|
||||
QVector2D a(ge.x1, ge.y1);
|
||||
QVector2D b(ge.x2, ge.y2);
|
||||
float dw = a.distanceToPoint(w) + b.distanceToPoint(w);
|
||||
float dab = a.distanceToPoint(b);
|
||||
return std::abs(dw - dab) / dab;
|
||||
}
|
||||
default:
|
||||
// Not close to anything.
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
// If in box, return 0.
|
||||
return 0;
|
||||
}
|
||||
case GraphicElement::TYPE_LOCAL_LINE:
|
||||
case GraphicElement::TYPE_LOCAL_ARROW:
|
||||
case GraphicElement::TYPE_LINE:
|
||||
case GraphicElement::TYPE_ARROW: {
|
||||
// Return somewhat primitively calculated distance to segment.
|
||||
// TODO(q3k): consider coming up with a better algorithm
|
||||
QVector2D w;
|
||||
if (ge.type == GraphicElement::TYPE_LOCAL_LINE || ge.type == GraphicElement::TYPE_LOCAL_ARROW) {
|
||||
w = QVector2D(dx, dy);
|
||||
} else {
|
||||
w = QVector2D(wx, wy);
|
||||
}
|
||||
QVector2D a(ge.x1, ge.y1);
|
||||
QVector2D b(ge.x2, ge.y2);
|
||||
float dw = a.distanceToPoint(w) + b.distanceToPoint(w);
|
||||
float dab = a.distanceToPoint(b);
|
||||
return std::abs(dw - dab) / dab;
|
||||
}
|
||||
default:
|
||||
// Not close to anything.
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
|
||||
// Find smallest non -1 distance.
|
||||
// Find closest element.
|
||||
@ -193,7 +200,8 @@ void FPGAViewWidget::renderGraphicElement(LineShaderData &out, PickQuadTree::Bou
|
||||
return;
|
||||
}
|
||||
|
||||
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) {
|
||||
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW ||
|
||||
el.type == GraphicElement::TYPE_LOCAL_LINE || el.type == GraphicElement::TYPE_LOCAL_ARROW) {
|
||||
PolyLine(x + el.x1, y + el.y1, x + el.x2, y + el.y2).build(out);
|
||||
bb.setX0(std::min(bb.x0(), x + el.x1));
|
||||
bb.setY0(std::min(bb.y0(), y + el.y1));
|
||||
@ -251,7 +259,8 @@ void FPGAViewWidget::populateQuadTree(RendererData *data, const DecalXY &decal,
|
||||
res = data->qt->insert(PickQuadTree::BoundingBox(x + el.x1, y + el.y1, x + el.x2, y + el.y2), element);
|
||||
}
|
||||
|
||||
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) {
|
||||
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW ||
|
||||
el.type == GraphicElement::TYPE_LOCAL_LINE || el.type == GraphicElement::TYPE_LOCAL_ARROW) {
|
||||
// Lines are bounded by their AABB slightly enlarged.
|
||||
float x0 = x + el.x1;
|
||||
float y0 = y + el.y1;
|
||||
@ -540,7 +549,7 @@ void FPGAViewWidget::renderLines(void)
|
||||
QMutexLocker lock(&rendererDataLock_);
|
||||
|
||||
// If we're not re-rendering any highlights/selections, let's
|
||||
// copy them over from teh current object.
|
||||
// copy them over from the current object.
|
||||
data->gfxGrid = rendererData_->gfxGrid;
|
||||
if (!highlightedOrSelectedChanged) {
|
||||
data->gfxSelected = rendererData_->gfxSelected;
|
||||
|
@ -19,9 +19,12 @@
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cst.h"
|
||||
|
||||
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
@ -30,8 +33,10 @@ MainWindow::MainWindow(std::unique_ptr<Context> context, CommandHandler *handler
|
||||
: BaseMainWindow(std::move(context), handler, parent)
|
||||
{
|
||||
initMainResource();
|
||||
QMessageBox::critical(0, "Error - FIXME", "No GUI support for nextpnr-gowin");
|
||||
std::exit(1);
|
||||
std::string title = "nextpnr-gowin - [EMPTY]";
|
||||
setWindowTitle(title.c_str());
|
||||
connect(this, &BaseMainWindow::contextChanged, this, &MainWindow::newContext);
|
||||
createMenu();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {}
|
||||
@ -42,8 +47,57 @@ void MainWindow::newContext(Context *ctx)
|
||||
setWindowTitle(title.c_str());
|
||||
}
|
||||
|
||||
void MainWindow::createMenu() {}
|
||||
void MainWindow::load_cst(std::string filename)
|
||||
{
|
||||
disableActions();
|
||||
std::ifstream f(filename);
|
||||
if (read_cst(ctx.get(), f)) {
|
||||
log("Loading CST successful.\n");
|
||||
actionPack->setEnabled(true);
|
||||
} else {
|
||||
actionLoadCST->setEnabled(true);
|
||||
log("Loading CST failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::createMenu()
|
||||
{
|
||||
actionLoadCST = new QAction("Open CST", this);
|
||||
actionLoadCST->setIcon(QIcon(":/icons/resources/open_cst.png"));
|
||||
actionLoadCST->setStatusTip("Open CST file");
|
||||
actionLoadCST->setEnabled(false);
|
||||
connect(actionLoadCST, &QAction::triggered, this, &MainWindow::open_cst);
|
||||
|
||||
// Add actions in menus
|
||||
mainActionBar->addSeparator();
|
||||
mainActionBar->addAction(actionLoadCST);
|
||||
|
||||
menuDesign->addSeparator();
|
||||
menuDesign->addAction(actionLoadCST);
|
||||
}
|
||||
|
||||
void MainWindow::new_proj() {}
|
||||
|
||||
void MainWindow::open_cst()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, QString("Open CST"), QString(), QString("*.cst"));
|
||||
if (!fileName.isEmpty()) {
|
||||
load_cst(fileName.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onDisableActions() { actionLoadCST->setEnabled(false); }
|
||||
|
||||
void MainWindow::onUpdateActions()
|
||||
{
|
||||
if (ctx->settings.find(ctx->id("synth")) != ctx->settings.end()) {
|
||||
actionLoadCST->setEnabled(true);
|
||||
}
|
||||
if (ctx->settings.find(ctx->id("cst")) != ctx->settings.end()) {
|
||||
actionLoadCST->setEnabled(false);
|
||||
}
|
||||
if (ctx->settings.find(ctx->id("pack")) != ctx->settings.end()) {
|
||||
actionLoadCST->setEnabled(false);
|
||||
}
|
||||
}
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -35,9 +35,21 @@ class MainWindow : public BaseMainWindow
|
||||
public:
|
||||
void createMenu();
|
||||
|
||||
protected:
|
||||
void onDisableActions() override;
|
||||
void onUpdateActions() override;
|
||||
|
||||
void load_cst(std::string filename);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void new_proj() override;
|
||||
|
||||
void open_cst();
|
||||
|
||||
void newContext(Context *ctx);
|
||||
|
||||
private:
|
||||
QAction *actionLoadCST;
|
||||
};
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -1,2 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>resources/open_cst.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
gui/gowin/resources/open_cst.png
Normal file
BIN
gui/gowin/resources/open_cst.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
Loading…
Reference in New Issue
Block a user