commit
a78719ecc1
@ -46,6 +46,8 @@ struct GraphicElement
|
|||||||
TYPE_BOX,
|
TYPE_BOX,
|
||||||
TYPE_CIRCLE,
|
TYPE_CIRCLE,
|
||||||
TYPE_LABEL,
|
TYPE_LABEL,
|
||||||
|
TYPE_LOCAL_ARROW, // Located entirely within the cell boundaries, coordinates in the range [0., 1.]
|
||||||
|
TYPE_LOCAL_LINE,
|
||||||
|
|
||||||
TYPE_MAX
|
TYPE_MAX
|
||||||
} type = TYPE_NONE;
|
} type = TYPE_NONE;
|
||||||
|
@ -57,6 +57,8 @@ struct SVGWriter
|
|||||||
switch (el.type) {
|
switch (el.type) {
|
||||||
case GraphicElement::TYPE_LINE:
|
case GraphicElement::TYPE_LINE:
|
||||||
case GraphicElement::TYPE_ARROW:
|
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,
|
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,
|
(el.y1 + dxy.y) * scale, (el.x2 + dxy.x) * scale, (el.y2 + dxy.y) * scale,
|
||||||
get_stroke_colour(el.style))
|
get_stroke_colour(el.style))
|
||||||
|
232
gowin/arch.cc
232
gowin/arch.cc
@ -23,6 +23,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include "embed.h"
|
#include "embed.h"
|
||||||
|
#include "gfx.h"
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
#include "placer1.h"
|
#include "placer1.h"
|
||||||
#include "placer_heap.h"
|
#include "placer_heap.h"
|
||||||
@ -32,6 +33,148 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
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)
|
WireInfo &Arch::wire_info(IdString wire)
|
||||||
{
|
{
|
||||||
auto w = wires.find(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)
|
void Arch::addWire(IdString name, IdString type, int x, int y)
|
||||||
{
|
{
|
||||||
// std::cout << name.str(this) << std::endl;
|
|
||||||
NPNR_ASSERT(wires.count(name) == 0);
|
NPNR_ASSERT(wires.count(name) == 0);
|
||||||
WireInfo &wi = wires[name];
|
WireInfo &wi = wires[name];
|
||||||
wi.name = 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);
|
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)
|
void Arch::addBel(IdString name, IdString type, Loc loc, bool gb)
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(bels.count(name) == 0);
|
NPNR_ASSERT(bels.count(name) == 0);
|
||||||
@ -189,24 +338,41 @@ void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
|
|||||||
refreshUi();
|
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);
|
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);
|
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);
|
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)
|
void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
|
||||||
{
|
{
|
||||||
groups[group].decalxy = decalxy;
|
groups[group].decalxy = decalxy;
|
||||||
@ -519,6 +685,7 @@ void Arch::read_cst(std::istream &in)
|
|||||||
insloc
|
insloc
|
||||||
} cst_type;
|
} cst_type;
|
||||||
|
|
||||||
|
settings.erase(id("cst"));
|
||||||
while (!in.eof()) {
|
while (!in.eof()) {
|
||||||
std::getline(in, line);
|
std::getline(in, line);
|
||||||
cst_type = ioloc;
|
cst_type = ioloc;
|
||||||
@ -584,6 +751,7 @@ void Arch::read_cst(std::istream &in)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
settings[id("cst")] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all MUXes for the cell
|
// 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);
|
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
|
// setup package
|
||||||
IdString package_name;
|
IdString package_name;
|
||||||
IdString device_id;
|
IdString device_id;
|
||||||
@ -762,9 +938,17 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
// The reverse order of the enumeration simplifies the creation
|
// The reverse order of the enumeration simplifies the creation
|
||||||
// of MUX2_LUT8s: they need the existence of the wire on the right.
|
// of MUX2_LUT8s: they need the existence of the wire on the right.
|
||||||
for (int i = db->rows * db->cols - 1; i >= 0; --i) {
|
for (int i = db->rows * db->cols - 1; i >= 0; --i) {
|
||||||
|
IdString grpname;
|
||||||
int row = i / db->cols;
|
int row = i / db->cols;
|
||||||
int col = i % db->cols;
|
int col = i % db->cols;
|
||||||
const TilePOD *tile = db->grid[i].get();
|
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
|
// setup wires
|
||||||
const PairPOD *pips[2] = {tile->pips.get(), tile->clock_pips.get()};
|
const PairPOD *pips[2] = {tile->pips.get(), tile->clock_pips.get()};
|
||||||
unsigned int num_pips[2] = {tile->num_pips, tile->num_clock_pips};
|
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) {
|
if (z == 0) {
|
||||||
addMuxBels(db, row, col);
|
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;
|
break;
|
||||||
case ID_IOBJ:
|
case ID_IOBJ:
|
||||||
z++; /* fall-through*/
|
z++; /* fall-through*/
|
||||||
@ -933,7 +1125,6 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
DelayQuad delay = getWireTypeDelay(destid);
|
DelayQuad delay = getWireTypeDelay(destid);
|
||||||
// local alias
|
// local alias
|
||||||
auto local_alias = pairLookup(tile->aliases.get(), tile->num_aliases, srcid.index);
|
auto local_alias = pairLookup(tile->aliases.get(), tile->num_aliases, srcid.index);
|
||||||
// std::cout << "srcid " << srcid.str(this) << std::endl;
|
|
||||||
if (local_alias != nullptr) {
|
if (local_alias != nullptr) {
|
||||||
srcid = IdString(local_alias->src_id);
|
srcid = IdString(local_alias->src_id);
|
||||||
gsrcname = wireToGlobal(srcrow, srccol, db, srcid);
|
gsrcname = wireToGlobal(srcrow, srccol, db, srcid);
|
||||||
@ -950,12 +1141,14 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
srcrow = alias_src->src_row;
|
srcrow = alias_src->src_row;
|
||||||
srcid = IdString(alias_src->src_id);
|
srcid = IdString(alias_src->src_id);
|
||||||
gsrcname = wireToGlobal(srcrow, srccol, db, srcid);
|
gsrcname = wireToGlobal(srcrow, srccol, db, srcid);
|
||||||
// std::cout << buf << std::endl;
|
|
||||||
}
|
}
|
||||||
addPip(pipname, destid, gsrcname, gdestname, delay, Loc(col, row, j));
|
addPip(pipname, destid, gsrcname, gdestname, delay, Loc(col, row, j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (args.gui) {
|
||||||
|
setDefaultDecals();
|
||||||
|
}
|
||||||
|
|
||||||
// Permissible combinations of modes in a single slice
|
// Permissible combinations of modes in a single slice
|
||||||
dff_comp_mode[id_DFF] = id_DFF;
|
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); }
|
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; }
|
bool Arch::getBelGlobalBuf(BelId bel) const { return bels.at(bel).gb; }
|
||||||
|
|
||||||
void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
|
void Arch::bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
|
||||||
@ -1303,6 +1507,16 @@ bool Arch::route()
|
|||||||
return result;
|
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
|
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
|
// y = mx + c relationship between distance and delay for interconnect
|
||||||
// delay estimates
|
// delay estimates
|
||||||
double delayScale = 0.4, delayOffset = 0.4;
|
double delayScale = 0.4, delayOffset = 0.4;
|
||||||
|
bool gui;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WireInfo;
|
struct WireInfo;
|
||||||
@ -187,7 +188,7 @@ struct PipInfo
|
|||||||
NetInfo *bound_net;
|
NetInfo *bound_net;
|
||||||
WireId srcWire, dstWire;
|
WireId srcWire, dstWire;
|
||||||
DelayQuad delay;
|
DelayQuad delay;
|
||||||
DecalXY decalxy;
|
DecalXY decalxy_active, decalxy_inactive;
|
||||||
Loc loc;
|
Loc loc;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -200,7 +201,7 @@ struct WireInfo
|
|||||||
BelPin uphill_bel_pin;
|
BelPin uphill_bel_pin;
|
||||||
std::vector<BelPin> downhill_bel_pins;
|
std::vector<BelPin> downhill_bel_pins;
|
||||||
std::vector<BelPin> bel_pins;
|
std::vector<BelPin> bel_pins;
|
||||||
DecalXY decalxy;
|
DecalXY decalxy_active, decalxy_inactive;
|
||||||
int x, y;
|
int x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ struct BelInfo
|
|||||||
std::map<IdString, std::string> attrs;
|
std::map<IdString, std::string> attrs;
|
||||||
CellInfo *bound_cell;
|
CellInfo *bound_cell;
|
||||||
dict<IdString, PinInfo> pins;
|
dict<IdString, PinInfo> pins;
|
||||||
DecalXY decalxy;
|
DecalXY decalxy_active, decalxy_inactive;
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
bool gb;
|
bool gb;
|
||||||
};
|
};
|
||||||
@ -270,8 +271,6 @@ struct ArchRanges : BaseArchRanges
|
|||||||
using GroupWiresRangeT = const std::vector<WireId> &;
|
using GroupWiresRangeT = const std::vector<WireId> &;
|
||||||
using GroupPipsRangeT = const std::vector<PipId> &;
|
using GroupPipsRangeT = const std::vector<PipId> &;
|
||||||
using GroupGroupsRangeT = const std::vector<GroupId> &;
|
using GroupGroupsRangeT = const std::vector<GroupId> &;
|
||||||
// Decals
|
|
||||||
using DecalGfxRangeT = const std::vector<GraphicElement> &;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Arch : BaseArch<ArchRanges>
|
struct Arch : BaseArch<ArchRanges>
|
||||||
@ -312,16 +311,23 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
void addBelOutput(IdString bel, IdString name, IdString wire);
|
void addBelOutput(IdString bel, IdString name, IdString wire);
|
||||||
void addBelInout(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 addGroupBel(IdString group, IdString bel);
|
||||||
void addGroupWire(IdString group, IdString wire);
|
void addGroupWire(IdString group, IdString wire);
|
||||||
void addGroupPip(IdString group, IdString pip);
|
void addGroupPip(IdString group, IdString pip);
|
||||||
void addGroupGroup(IdString group, IdString grp);
|
void addGroupGroup(IdString group, IdString grp);
|
||||||
|
|
||||||
void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
|
void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
|
||||||
void setWireDecal(WireId wire, DecalXY decalxy);
|
void setWireDecal(WireId wire, DecalXY active, DecalXY inactive);
|
||||||
void setPipDecal(PipId pip, DecalXY decalxy);
|
void setPipDecal(PipId pip, DecalXY active, DecalXY inactive);
|
||||||
void setBelDecal(BelId bel, DecalXY decalxy);
|
void setBelDecal(BelId bel, DecalXY active, DecalXY inactive);
|
||||||
|
void setDefaultDecals(void);
|
||||||
void setGroupDecal(GroupId group, DecalXY decalxy);
|
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 setWireAttr(IdString wire, IdString key, const std::string &value);
|
||||||
void setPipAttr(IdString pip, 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
|
// Internal usage
|
||||||
void assignArchInfo() override;
|
void assignArchInfo() override;
|
||||||
bool cellsCompatible(const CellInfo **cells, int count) const;
|
bool cellsCompatible(const CellInfo **cells, int count) const;
|
||||||
|
bool haveBelType(int x, int y, IdString bel_type);
|
||||||
// start Z for the MUX2LUT5 bels
|
// start Z for the MUX2LUT5 bels
|
||||||
int const mux_0_z = 10;
|
int const mux_0_z = 10;
|
||||||
// chip db version
|
// chip db version
|
||||||
@ -459,6 +466,12 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
std::vector<IdString> cell_types;
|
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
|
// Permissible combinations of modes in a single slice
|
||||||
std::map<const IdString, IdString> dff_comp_mode;
|
std::map<const IdString, IdString> dff_comp_mode;
|
||||||
};
|
};
|
||||||
|
@ -313,6 +313,312 @@ X(COUT2)
|
|||||||
X(COUT3)
|
X(COUT3)
|
||||||
X(COUT4)
|
X(COUT4)
|
||||||
X(COUT5)
|
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
|
// slice items
|
||||||
X(SLICE)
|
X(SLICE)
|
||||||
X(CLK)
|
X(CLK)
|
||||||
@ -380,6 +686,22 @@ X(GW_MUX2_LUT5)
|
|||||||
X(GW_MUX2_LUT6)
|
X(GW_MUX2_LUT6)
|
||||||
X(GW_MUX2_LUT7)
|
X(GW_MUX2_LUT7)
|
||||||
X(GW_MUX2_LUT8)
|
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
|
// ALU
|
||||||
X(ALU)
|
X(ALU)
|
||||||
@ -464,3 +786,23 @@ X(d_f)
|
|||||||
X(fx_ofx1)
|
X(fx_ofx1)
|
||||||
X(I01)
|
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
|
5828
gowin/gfx.cc
Normal file
5828
gowin/gfx.cc
Normal file
File diff suppressed because it is too large
Load Diff
39
gowin/gfx.h
Normal file
39
gowin/gfx.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GFX_H
|
||||||
|
#define GFX_H
|
||||||
|
|
||||||
|
#include "nextpnr.h"
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
void gfxCreateBelDecals(Arch *arch);
|
||||||
|
void gfxSetBelDefaultDecal(Arch *arch, BelInfo &bel);
|
||||||
|
void gfxSetIOBWireDecals(Arch *arch, BelInfo &bel);
|
||||||
|
void gfxSetIOBSWireDecals(Arch *arch, BelInfo &bel);
|
||||||
|
void gfxSetPipDefaultDecal(Arch *arch, PipInfo &pip);
|
||||||
|
void gfxSetWireDefaultDecal(Arch *arch, WireInfo &wire);
|
||||||
|
DecalXY gfxGetLutGroupDecalXY(int x, int y, int z);
|
||||||
|
DecalXY gfxGetCruGroupDecalXY(int x, int y);
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif // GFX_H
|
@ -61,6 +61,7 @@ std::unique_ptr<Context> GowinCommandHandler::createContext(dict<std::string, Pr
|
|||||||
log_error("Invalid device %s\n", device.c_str());
|
log_error("Invalid device %s\n", device.c_str());
|
||||||
}
|
}
|
||||||
ArchArgs chipArgs;
|
ArchArgs chipArgs;
|
||||||
|
chipArgs.gui = vm.count("gui") != 0;
|
||||||
char buf[36];
|
char buf[36];
|
||||||
// GW1N and GW1NR variants share the same database.
|
// GW1N and GW1NR variants share the same database.
|
||||||
// Most Gowin devices are a System in Package with some SDRAM wirebonded to a GPIO bank.
|
// 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()) {
|
for (const auto &wire : ctx->getWires()) {
|
||||||
wireMap[std::pair<int, int>(wire.location.x, wire.location.y)].push_back(wire);
|
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
|
#endif
|
||||||
auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
|
auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
|
||||||
getTreeByElementType(ElementType::WIRE)
|
getTreeByElementType(ElementType::WIRE)
|
||||||
|
@ -129,8 +129,8 @@ float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy)
|
|||||||
|
|
||||||
// Go over its' GraphicElements, and calculate the distance to them.
|
// Go over its' GraphicElements, and calculate the distance to them.
|
||||||
std::vector<float> distances;
|
std::vector<float> distances;
|
||||||
std::transform(graphics.begin(), graphics.end(), std::back_inserter(distances),
|
std::transform(
|
||||||
[&](const GraphicElement &ge) -> float {
|
graphics.begin(), graphics.end(), std::back_inserter(distances), [&](const GraphicElement &ge) -> float {
|
||||||
switch (ge.type) {
|
switch (ge.type) {
|
||||||
case GraphicElement::TYPE_BOX: {
|
case GraphicElement::TYPE_BOX: {
|
||||||
// If outside the box, return unit distance to closest border.
|
// If outside the box, return unit distance to closest border.
|
||||||
@ -147,11 +147,18 @@ float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy)
|
|||||||
// If in box, return 0.
|
// If in box, return 0.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case GraphicElement::TYPE_LOCAL_LINE:
|
||||||
|
case GraphicElement::TYPE_LOCAL_ARROW:
|
||||||
case GraphicElement::TYPE_LINE:
|
case GraphicElement::TYPE_LINE:
|
||||||
case GraphicElement::TYPE_ARROW: {
|
case GraphicElement::TYPE_ARROW: {
|
||||||
// Return somewhat primitively calculated distance to segment.
|
// Return somewhat primitively calculated distance to segment.
|
||||||
// TODO(q3k): consider coming up with a better algorithm
|
// TODO(q3k): consider coming up with a better algorithm
|
||||||
QVector2D w(wx, wy);
|
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 a(ge.x1, ge.y1);
|
||||||
QVector2D b(ge.x2, ge.y2);
|
QVector2D b(ge.x2, ge.y2);
|
||||||
float dw = a.distanceToPoint(w) + b.distanceToPoint(w);
|
float dw = a.distanceToPoint(w) + b.distanceToPoint(w);
|
||||||
@ -193,7 +200,8 @@ void FPGAViewWidget::renderGraphicElement(LineShaderData &out, PickQuadTree::Bou
|
|||||||
return;
|
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);
|
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.setX0(std::min(bb.x0(), x + el.x1));
|
||||||
bb.setY0(std::min(bb.y0(), y + el.y1));
|
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);
|
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.
|
// Lines are bounded by their AABB slightly enlarged.
|
||||||
float x0 = x + el.x1;
|
float x0 = x + el.x1;
|
||||||
float y0 = y + el.y1;
|
float y0 = y + el.y1;
|
||||||
@ -540,7 +549,7 @@ void FPGAViewWidget::renderLines(void)
|
|||||||
QMutexLocker lock(&rendererDataLock_);
|
QMutexLocker lock(&rendererDataLock_);
|
||||||
|
|
||||||
// If we're not re-rendering any highlights/selections, let's
|
// 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;
|
data->gfxGrid = rendererData_->gfxGrid;
|
||||||
if (!highlightedOrSelectedChanged) {
|
if (!highlightedOrSelectedChanged) {
|
||||||
data->gfxSelected = rendererData_->gfxSelected;
|
data->gfxSelected = rendererData_->gfxSelected;
|
||||||
|
@ -19,9 +19,12 @@
|
|||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "cst.h"
|
||||||
|
|
||||||
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
|
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
@ -30,8 +33,10 @@ MainWindow::MainWindow(std::unique_ptr<Context> context, CommandHandler *handler
|
|||||||
: BaseMainWindow(std::move(context), handler, parent)
|
: BaseMainWindow(std::move(context), handler, parent)
|
||||||
{
|
{
|
||||||
initMainResource();
|
initMainResource();
|
||||||
QMessageBox::critical(0, "Error - FIXME", "No GUI support for nextpnr-gowin");
|
std::string title = "nextpnr-gowin - [EMPTY]";
|
||||||
std::exit(1);
|
setWindowTitle(title.c_str());
|
||||||
|
connect(this, &BaseMainWindow::contextChanged, this, &MainWindow::newContext);
|
||||||
|
createMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {}
|
MainWindow::~MainWindow() {}
|
||||||
@ -42,8 +47,57 @@ void MainWindow::newContext(Context *ctx)
|
|||||||
setWindowTitle(title.c_str());
|
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::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
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -35,9 +35,21 @@ class MainWindow : public BaseMainWindow
|
|||||||
public:
|
public:
|
||||||
void createMenu();
|
void createMenu();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onDisableActions() override;
|
||||||
|
void onUpdateActions() override;
|
||||||
|
|
||||||
|
void load_cst(std::string filename);
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void new_proj() override;
|
void new_proj() override;
|
||||||
|
|
||||||
|
void open_cst();
|
||||||
|
|
||||||
void newContext(Context *ctx);
|
void newContext(Context *ctx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QAction *actionLoadCST;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
|
<qresource prefix="/icons">
|
||||||
|
<file>resources/open_cst.png</file>
|
||||||
|
</qresource>
|
||||||
</RCC>
|
</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