aboutsummaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2023-04-11 10:05:33 +0200
committermyrtle <gatecat@ds0.me>2023-04-11 19:11:54 +0200
commit6455b5dd2661fd76bccc32a42577fecd4e43752d (patch)
treec6f2e8e3536b3024f4652a78000d49c2215a1b78 /generic
parent9bcefe46a89a1fb55ab86f2e0a3319baf1b92807 (diff)
downloadnextpnr-6455b5dd2661fd76bccc32a42577fecd4e43752d.tar.gz
nextpnr-6455b5dd2661fd76bccc32a42577fecd4e43752d.tar.bz2
nextpnr-6455b5dd2661fd76bccc32a42577fecd4e43752d.zip
viaduct: Add support for GUIs
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'generic')
-rw-r--r--generic/arch.cc60
-rw-r--r--generic/arch.h10
-rw-r--r--generic/arch_pybindings.cc44
-rw-r--r--generic/archdefs.h12
-rw-r--r--generic/main.cc4
-rw-r--r--generic/viaduct/example/example.cc28
-rw-r--r--generic/viaduct_api.h1
7 files changed, 117 insertions, 42 deletions
diff --git a/generic/arch.cc b/generic/arch.cc
index c0575b87..238fb9fc 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -161,33 +161,47 @@ void Arch::addGroupPip(IdStringList group, PipId pip) { groups[group].pips.push_
void Arch::addGroupGroup(IdStringList group, IdStringList grp) { groups[group].groups.push_back(grp); }
-void Arch::addDecalGraphic(DecalId decal, const GraphicElement &graphic)
+void Arch::addDecalGraphic(IdStringList decal, const GraphicElement &graphic)
{
- decal_graphics[decal].push_back(graphic);
+ decal_graphics[DecalId(decal, false)].push_back(graphic); // inactive variant
+ decal_graphics[DecalId(decal, true)].push_back(graphic); // active variant
+
+ GraphicElement &active = decal_graphics[DecalId(decal, true)].back();
+ if (active.style == GraphicElement::STYLE_INACTIVE)
+ active.style = GraphicElement::STYLE_ACTIVE;
+
refreshUi();
}
-void Arch::setWireDecal(WireId wire, DecalXY decalxy)
+void Arch::setWireDecal(WireId wire, float x, float y, IdStringList decal)
{
- wires.at(wire.index).decalxy = decalxy;
+ wires.at(wire.index).decalxy.x = x;
+ wires.at(wire.index).decalxy.y = y;
+ wires.at(wire.index).decalxy.decal = DecalId(decal, false);
refreshUiWire(wire);
}
-void Arch::setPipDecal(PipId pip, DecalXY decalxy)
+void Arch::setPipDecal(PipId pip, float x, float y, IdStringList decal)
{
- pips.at(pip.index).decalxy = decalxy;
+ pips.at(pip.index).decalxy.x = x;
+ pips.at(pip.index).decalxy.y = y;
+ pips.at(pip.index).decalxy.decal = DecalId(decal, false);
refreshUiPip(pip);
}
-void Arch::setBelDecal(BelId bel, DecalXY decalxy)
+void Arch::setBelDecal(BelId bel, float x, float y, IdStringList decal)
{
- bels.at(bel.index).decalxy = decalxy;
+ bels.at(bel.index).decalxy.x = x;
+ bels.at(bel.index).decalxy.y = y;
+ bels.at(bel.index).decalxy.decal = DecalId(decal, false);
refreshUiBel(bel);
}
-void Arch::setGroupDecal(GroupId group, DecalXY decalxy)
+void Arch::setGroupDecal(GroupId group, float x, float y, IdStringList decal)
{
- groups[group].decalxy = decalxy;
+ groups.at(group).decalxy.x = x;
+ groups.at(group).decalxy.y = y;
+ groups.at(group).decalxy.decal = DecalId(decal, false);
refreshUiGroup(group);
}
@@ -248,7 +262,8 @@ void Arch::addCellBelPinMapping(IdString cell, IdString cell_pin, IdString bel_p
Arch::Arch(ArchArgs args) : chipName("generic"), args(args)
{
// Dummy for empty decals
- decal_graphics[DecalId()];
+ decal_graphics[DecalId(IdStringList(), false)];
+ decal_graphics[DecalId(IdStringList(), true)];
}
void IdString::initialize_arch(const BaseCtx *ctx) {}
@@ -643,16 +658,31 @@ bool Arch::route()
const std::vector<GraphicElement> &Arch::getDecalGraphics(DecalId decal) const
{
if (!decal_graphics.count(decal)) {
- std::cerr << "No decal named " << decal.str(getCtx()) << std::endl;
+ std::cerr << "No decal named " << decal.name.str(getCtx()) << std::endl;
}
return decal_graphics.at(decal);
}
-DecalXY Arch::getBelDecal(BelId bel) const { return bel_info(bel).decalxy; }
+DecalXY Arch::getBelDecal(BelId bel) const
+{
+ DecalXY result = bel_info(bel).decalxy;
+ result.decal.active = getBoundBelCell(bel) != nullptr;
+ return result;
+}
-DecalXY Arch::getWireDecal(WireId wire) const { return wire_info(wire).decalxy; }
+DecalXY Arch::getWireDecal(WireId wire) const
+{
+ DecalXY result = wire_info(wire).decalxy;
+ result.decal.active = getBoundWireNet(wire) != nullptr;
+ return result;
+}
-DecalXY Arch::getPipDecal(PipId pip) const { return pip_info(pip).decalxy; }
+DecalXY Arch::getPipDecal(PipId pip) const
+{
+ DecalXY result = pip_info(pip).decalxy;
+ result.decal.active = getBoundPipNet(pip) != nullptr;
+ return result;
+}
DecalXY Arch::getGroupDecal(GroupId group) const { return groups.at(group).decalxy; }
diff --git a/generic/arch.h b/generic/arch.h
index 19a0a078..40994ad0 100644
--- a/generic/arch.h
+++ b/generic/arch.h
@@ -211,11 +211,11 @@ struct Arch : BaseArch<ArchRanges>
void addGroupPip(IdStringList group, PipId pip);
void addGroupGroup(IdStringList group, IdStringList 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 setGroupDecal(GroupId group, DecalXY decalxy);
+ void addDecalGraphic(IdStringList decal, const GraphicElement &graphic);
+ void setWireDecal(WireId wire, float x, float y, IdStringList decal);
+ void setPipDecal(PipId pip, float x, float y, IdStringList decal);
+ void setBelDecal(BelId bel, float x, float y, IdStringList decal);
+ void setGroupDecal(GroupId group, float x, float y, IdStringList decal);
void setWireAttr(WireId wire, IdString key, const std::string &value);
void setPipAttr(PipId pip, IdString key, const std::string &value);
diff --git a/generic/arch_pybindings.cc b/generic/arch_pybindings.cc
index a5a0bed9..f067936c 100644
--- a/generic/arch_pybindings.cc
+++ b/generic/arch_pybindings.cc
@@ -55,14 +55,6 @@ void arch_wrap_python(py::module &m)
auto arch_cls = py::class_<Arch, BaseCtx>(m, "Arch").def(py::init<ArchArgs>());
- auto dxy_cls = py::class_<ContextualWrapper<DecalXY>>(m, "DecalXY_");
- readwrite_wrapper<DecalXY, decltype(&DecalXY::decal), &DecalXY::decal, conv_to_str<DecalId>,
- conv_from_str<DecalId>>::def_wrap(dxy_cls, "decal");
- readwrite_wrapper<DecalXY, decltype(&DecalXY::x), &DecalXY::x, pass_through<float>, pass_through<float>>::def_wrap(
- dxy_cls, "x");
- readwrite_wrapper<DecalXY, decltype(&DecalXY::y), &DecalXY::y, pass_through<float>, pass_through<float>>::def_wrap(
- dxy_cls, "y");
-
auto ctx_cls = py::class_<Context, Arch>(m, "Context")
.def("checksum", &Context::checksum)
.def("pack", &Context::pack)
@@ -72,9 +64,6 @@ void arch_wrap_python(py::module &m)
auto belpin_cls =
py::class_<BelPin>(m, "BelPin").def_readwrite("bel", &BelPin::bel).def_readwrite("pin", &BelPin::pin);
- fn_wrapper_3a<Context, decltype(&Context::constructDecalXY), &Context::constructDecalXY, wrap_context<DecalXY>,
- conv_from_str<DecalId>, pass_through<float>, pass_through<float>>::def_wrap(ctx_cls, "DecalXY");
-
typedef dict<IdString, std::unique_ptr<CellInfo>> CellMap;
typedef dict<IdString, std::unique_ptr<NetInfo>> NetMap;
typedef dict<IdString, HierarchicalCell> HierarchyMap;
@@ -121,16 +110,29 @@ void arch_wrap_python(py::module &m)
fn_wrapper_2a_v<Context, decltype(&Context::addGroupGroup), &Context::addGroupGroup, conv_from_str<IdStringList>,
conv_from_str<IdStringList>>::def_wrap(ctx_cls, "addGroupGroup", "group"_a, "grp"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic, conv_from_str<DecalId>,
- pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic", (py::arg("decal"), "graphic"));
- fn_wrapper_2a_v<Context, decltype(&Context::setWireDecal), &Context::setWireDecal, conv_from_str<WireId>,
- unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setWireDecal", "wire"_a, "decalxy"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::setPipDecal), &Context::setPipDecal, conv_from_str<PipId>,
- unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setPipDecal", "pip"_a, "decalxy"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::setBelDecal), &Context::setBelDecal, conv_from_str<BelId>,
- unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setBelDecal", "bel"_a, "decalxy"_a);
- fn_wrapper_2a_v<Context, decltype(&Context::setGroupDecal), &Context::setGroupDecal, conv_from_str<DecalId>,
- unwrap_context<DecalXY>>::def_wrap(ctx_cls, "setGroupDecal", "group"_a, "decalxy"_a);
+ fn_wrapper_2a_v<Context, decltype(&Context::addDecalGraphic), &Context::addDecalGraphic,
+ conv_from_str<IdStringList>, pass_through<GraphicElement>>::def_wrap(ctx_cls, "addDecalGraphic",
+ (py::arg("decal"), "graphic"));
+ fn_wrapper_4a_v<Context, decltype(&Context::setWireDecal), &Context::setWireDecal, conv_from_str<WireId>,
+ pass_through<float>, pass_through<float>, conv_from_str<IdStringList>>::def_wrap(ctx_cls,
+ "setWireDecal",
+ "wire"_a, "x"_a,
+ "y"_a, "decal"_a);
+ fn_wrapper_4a_v<Context, decltype(&Context::setPipDecal), &Context::setPipDecal, conv_from_str<PipId>,
+ pass_through<float>, pass_through<float>, conv_from_str<IdStringList>>::def_wrap(ctx_cls,
+ "setPipDecal",
+ "pip"_a, "x"_a,
+ "y"_a, "decal"_a);
+ fn_wrapper_4a_v<Context, decltype(&Context::setBelDecal), &Context::setBelDecal, conv_from_str<BelId>,
+ pass_through<float>, pass_through<float>, conv_from_str<IdStringList>>::def_wrap(ctx_cls,
+ "setBelDecal",
+ "bel"_a, "x"_a,
+ "y"_a, "decal"_a);
+ fn_wrapper_4a_v<Context, decltype(&Context::setGroupDecal), &Context::setGroupDecal, conv_from_str<GroupId>,
+ pass_through<float>, pass_through<float>, conv_from_str<IdStringList>>::def_wrap(ctx_cls,
+ "setGroupDecal",
+ "group"_a, "x"_a,
+ "y"_a, "decal"_a);
fn_wrapper_3a_v<Context, decltype(&Context::setWireAttr), &Context::setWireAttr, conv_from_str<WireId>,
conv_from_str<IdString>, pass_through<std::string>>::def_wrap(ctx_cls, "setWireAttr", "wire"_a,
diff --git a/generic/archdefs.h b/generic/archdefs.h
index 4e91ffd3..374ddeb0 100644
--- a/generic/archdefs.h
+++ b/generic/archdefs.h
@@ -64,8 +64,18 @@ struct PipId
unsigned int hash() const { return index; }
};
+struct DecalId
+{
+ IdStringList name;
+ bool active = false;
+ DecalId() : name(), active(false){};
+ DecalId(IdStringList name, bool active) : name(name), active(active){};
+ bool operator==(const DecalId &other) const { return name == other.name && active == other.active; }
+ bool operator!=(const DecalId &other) const { return name != other.name || active != other.active; }
+ unsigned int hash() const { return mkhash(name.hash(), active); }
+};
+
typedef IdStringList GroupId;
-typedef IdStringList DecalId;
typedef IdString BelBucketId;
typedef IdString ClusterId;
diff --git a/generic/main.cc b/generic/main.cc
index 3ee1c790..7aece569 100644
--- a/generic/main.cc
+++ b/generic/main.cc
@@ -86,9 +86,13 @@ std::unique_ptr<Context> GenericCommandHandler::createContext(dict<std::string,
log_error("Unknown viaduct uarch '%s'; available options: '%s'\n", uarch_name.c_str(), all_uarches.c_str());
}
ctx->uarch = std::move(uarch);
+ if (vm.count("gui"))
+ ctx->uarch->with_gui = true;
ctx->uarch->init(ctx.get());
} else if (vm.count("vopt")) {
log_error("Viaduct options passed in non-viaduct mode!\n");
+ } else if (vm.count("gui")) {
+ log_error("nextpnr-generic GUI only supported in viaduct mode!\n");
}
return ctx;
}
diff --git a/generic/viaduct/example/example.cc b/generic/viaduct/example/example.cc
index 7a61a594..7de0404b 100644
--- a/generic/viaduct/example/example.cc
+++ b/generic/viaduct/example/example.cc
@@ -38,6 +38,8 @@ struct ExampleImpl : ViaductAPI
init_uarch_constids(ctx);
ViaductAPI::init(ctx);
h.init(ctx);
+ if (with_gui)
+ init_bel_decals();
init_wires();
init_bels();
init_pips();
@@ -150,6 +152,28 @@ struct ExampleImpl : ViaductAPI
IdStringList name = IdStringList::concat(ctx->getWireName(dst), ctx->getWireName(src));
return ctx->addPip(name, ctx->id("PIP"), src, dst, delay, loc);
}
+
+ static constexpr float lut_x1 = 0.8f;
+ static constexpr float lut_w = 0.07f;
+ static constexpr float ff_x1 = 0.9f;
+ static constexpr float ff_w = 0.05f;
+ static constexpr float bel_y1 = 0.2f;
+ static constexpr float bel_h = 0.03f;
+ static constexpr float bel_dy = 0.05f;
+ void init_bel_decals()
+ {
+ for (int z = 0; z < N; z++) {
+ float y1 = bel_y1 + z * bel_dy;
+ float y2 = y1 + bel_h;
+ ctx->addDecalGraphic(IdStringList(ctx->idf("LUT%d", z)),
+ GraphicElement(GraphicElement::TYPE_BOX, GraphicElement::STYLE_INACTIVE, lut_x1, y1,
+ lut_x1 + lut_w, y2, 10.0));
+ ctx->addDecalGraphic(IdStringList(ctx->idf("FF%d", z)),
+ GraphicElement(GraphicElement::TYPE_BOX, GraphicElement::STYLE_INACTIVE, ff_x1, y1,
+ ff_x1 + ff_w, y2, 10.0));
+ }
+ }
+
// Create LUT and FF bels in a logic tile
void add_slice_bels(int x, int y)
{
@@ -169,6 +193,10 @@ struct ExampleImpl : ViaductAPI
ctx->addBelInput(dff, id_CLK, w.clk.at(z));
ctx->addBelInput(dff, id_D, w.d.at(z));
ctx->addBelOutput(dff, id_Q, w.q.at(z));
+ if (with_gui) {
+ ctx->setBelDecal(lut, x, y, IdStringList(ctx->idf("LUT%d", z)));
+ ctx->setBelDecal(dff, x, y, IdStringList(ctx->idf("FF%d", z)));
+ }
}
}
// Create bels according to tile type
diff --git a/generic/viaduct_api.h b/generic/viaduct_api.h
index 3caa0ba1..6d6423b6 100644
--- a/generic/viaduct_api.h
+++ b/generic/viaduct_api.h
@@ -55,6 +55,7 @@ struct ViaductAPI
{
virtual void init(Context *ctx);
Context *ctx;
+ bool with_gui = false;
// --- Bel functions ---
// Called when a bel is placed/unplaced (with cell=nullptr for a unbind)