viaduct: Add support for GUIs
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
9bcefe46a8
commit
6455b5dd26
@ -56,14 +56,14 @@ Adds an input, output or inout pin to a bel, with an associated wire. Note that
|
||||
|
||||
Add a bel, wire, pip or subgroup to a group, which will be created if it doesn't already exist. Groups are purely for visual presentation purposes in the user interface and are not used by any place-and-route algorithms.
|
||||
|
||||
### void addDecalGraphic(DecalId decal, const GraphicElement &graphic);
|
||||
### void addDecalGraphic(IdStringList decal, const GraphicElement &graphic);
|
||||
|
||||
Add a graphic element to a _decal_, a reusable drawing that may be used to represent multiple wires, pips, bels or groups in the UI (with different offsets). The decal will be created if it doesn't already exist
|
||||
|
||||
### 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 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);
|
||||
|
||||
Sets the decal ID and offset for a wire, bel, pip or group in the UI.
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -30,8 +30,6 @@ 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-generic");
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {}
|
||||
@ -44,6 +42,9 @@ void MainWindow::newContext(Context *ctx)
|
||||
|
||||
void MainWindow::createMenu() {}
|
||||
|
||||
void MainWindow::new_proj() {}
|
||||
void MainWindow::new_proj() {
|
||||
QMessageBox::critical(0, "Error", "Creating a new project not supported in Viaduct mode, please re-start from command line.");
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -315,9 +315,9 @@ IdStringList Arch::getPipName(PipId pip) const
|
||||
{
|
||||
auto &pip_data = tile_info(pip)->pip_data[pip.index];
|
||||
WireId src = getPipSrcWire(pip), dst = getPipDstWire(pip);
|
||||
std::string pip_name = stringf("%d_%d_%s->%d_%d_%s", pip_data.src.x, pip_data.src.y,
|
||||
get_wire_basename(src).c_str(this), pip_data.dst.x, pip_data.dst.y,
|
||||
get_wire_basename(dst).c_str(this));
|
||||
std::string pip_name =
|
||||
stringf("%d_%d_%s->%d_%d_%s", pip_data.src.x, pip_data.src.y, get_wire_basename(src).c_str(this),
|
||||
pip_data.dst.x, pip_data.dst.y, get_wire_basename(dst).c_str(this));
|
||||
|
||||
std::array<IdString, 3> ids{x_ids.at(pip.location.x), y_ids.at(pip.location.y), id(pip_name)};
|
||||
return IdStringList(ids);
|
||||
@ -490,8 +490,7 @@ std::vector<std::pair<std::string, std::string>> Arch::get_tiles_at_loc(int row,
|
||||
std::vector<std::pair<std::string, std::string>> ret;
|
||||
auto &tileloc = chip_info->tile_info[row * chip_info->width + col];
|
||||
for (auto &tn : tileloc.tile_names) {
|
||||
ret.push_back(std::make_pair(tn.name.get(),
|
||||
chip_info->tiletype_names[tn.type_idx].get()));
|
||||
ret.push_back(std::make_pair(tn.name.get(), chip_info->tiletype_names[tn.type_idx].get()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -176,12 +176,11 @@ static std::string get_pic_tile(Context *ctx, BelId bel)
|
||||
{
|
||||
static const std::set<std::string> pio_t = {"PIC_T0", "PIC_T0_256", "PIC_TS0"};
|
||||
static const std::set<std::string> pio_b = {"PIC_B0", "PIC_B0_256", "PIC_BS0_256"};
|
||||
static const std::set<std::string> pio_l = {"PIC_L0", "PIC_L1", "PIC_L2", "PIC_L3", "PIC_LS0",
|
||||
"PIC_L0_VREF3", "PIC_L0_VREF4", "PIC_L0_VREF5",
|
||||
"PIC_L1_VREF3", "PIC_L1_VREF4", "PIC_L1_VREF5",
|
||||
"PIC_L2_VREF4", "PIC_L2_VREF5",
|
||||
"PIC_L3_VREF4", "PIC_L3_VREF5"};
|
||||
static const std::set<std::string> pio_r = {"PIC_R0", "PIC_R1", "PIC_RS0",
|
||||
static const std::set<std::string> pio_l = {"PIC_L0", "PIC_L1", "PIC_L2", "PIC_L3",
|
||||
"PIC_LS0", "PIC_L0_VREF3", "PIC_L0_VREF4", "PIC_L0_VREF5",
|
||||
"PIC_L1_VREF3", "PIC_L1_VREF4", "PIC_L1_VREF5", "PIC_L2_VREF4",
|
||||
"PIC_L2_VREF5", "PIC_L3_VREF4", "PIC_L3_VREF5"};
|
||||
static const std::set<std::string> pio_r = {"PIC_R0", "PIC_R1", "PIC_RS0",
|
||||
"PIC_R0_256", "PIC_R1_640", "PIC_RS0_256"};
|
||||
|
||||
std::string pio_name = ctx->tile_info(bel)->bel_data[bel.index].name.get();
|
||||
|
Loading…
Reference in New Issue
Block a user