mirror of https://github.com/YosysHQ/nextpnr.git
gatemate: add IOSEL as separate primitive (#1533)
This commit is contained in:
parent
b0626280e9
commit
95ab16f380
|
|
@ -289,6 +289,8 @@ struct BitstreamBackend
|
|||
case id_CPE_LVDS_TOBUF.index:
|
||||
case id_CPE_LVDS_OBUF.index:
|
||||
case id_CPE_LVDS_IOBUF.index:
|
||||
break;
|
||||
case id_IOSEL.index:
|
||||
for (auto &p : params) {
|
||||
bank[loc.die][ctx->get_bel_package_pin(cell.second.get()->bel)->pad_bank] = 1;
|
||||
cc.tiles[loc].add_word(stringf("GPIO.%s", p.first.c_str(ctx)), p.second.as_bits());
|
||||
|
|
|
|||
|
|
@ -106,6 +106,22 @@ CellInfo *GateMatePacker::create_cell_ptr(IdString type, IdString name)
|
|||
add_port(id_POUTY1, PORT_OUT);
|
||||
add_port(id_COUTY2, PORT_OUT);
|
||||
add_port(id_POUTY2, PORT_OUT);
|
||||
} else if (type.in(id_IOSEL)) {
|
||||
add_port(id_GPIO_OUT, PORT_OUT);
|
||||
add_port(id_GPIO_EN, PORT_OUT);
|
||||
add_port(id_GPIO_IN, PORT_IN);
|
||||
|
||||
add_port(id_IN1, PORT_OUT);
|
||||
add_port(id_IN2, PORT_OUT);
|
||||
add_port(id_OUT1, PORT_IN);
|
||||
add_port(id_OUT2, PORT_IN);
|
||||
add_port(id_OUT3, PORT_IN);
|
||||
add_port(id_OUT4, PORT_IN);
|
||||
add_port(id_DDR, PORT_IN);
|
||||
add_port(id_CLOCK1, PORT_IN);
|
||||
add_port(id_CLOCK2, PORT_IN);
|
||||
add_port(id_CLOCK3, PORT_IN);
|
||||
add_port(id_CLOCK4, PORT_IN);
|
||||
} else {
|
||||
log_error("Trying to create unknown cell type %s\n", type.c_str(ctx));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1030,9 +1030,12 @@ X(CPE_CPLINES)
|
|||
//X(COUTY2)
|
||||
//X(POUTY2)
|
||||
|
||||
// hardware primitive GPIO
|
||||
X(GPIO)
|
||||
// GPIO pins
|
||||
// hardware primitive IOSEL
|
||||
X(IOSEL)
|
||||
// IOSEL pins
|
||||
X(GPIO_OUT)
|
||||
X(GPIO_EN)
|
||||
X(GPIO_IN)
|
||||
//X(IN1)
|
||||
//X(IN2)
|
||||
//X(OUT1)
|
||||
|
|
@ -1044,6 +1047,13 @@ X(CLOCK1)
|
|||
X(CLOCK2)
|
||||
X(CLOCK3)
|
||||
X(CLOCK4)
|
||||
|
||||
// hardware primitive GPIO
|
||||
X(GPIO)
|
||||
// GPIO pins
|
||||
//X(Y)
|
||||
//X(T)
|
||||
//X(A)
|
||||
//X(I)
|
||||
//X(O)
|
||||
//X(IO)
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ def set_timings(ch):
|
|||
lut.add_comb_arc("I", "RAM_O", TimingValue(0, 0))
|
||||
lut.add_comb_arc("RAM_I", "OUT", TimingValue(0, 0))
|
||||
|
||||
EXPECTED_VERSION = 1.3
|
||||
EXPECTED_VERSION = 1.4
|
||||
|
||||
def main():
|
||||
# Range needs to be +1, but we are adding +2 more to coordinates, since
|
||||
|
|
|
|||
|
|
@ -130,13 +130,15 @@ void GateMatePacker::pack_bufg()
|
|||
int die = uarch->preferred_die;
|
||||
if (in_net) {
|
||||
if (in_net->driver.cell) {
|
||||
if (ctx->getBelBucketForCellType(in_net->driver.cell->type) == id_GPIO) {
|
||||
if (ctx->getBelBucketForCellType(in_net->driver.cell->type) == id_IOSEL) {
|
||||
auto pad_info = uarch->bel_to_pad[in_net->driver.cell->bel];
|
||||
if (pad_info->flags) {
|
||||
int index = pad_info->flags - 1;
|
||||
die = uarch->tile_extra_data(in_net->driver.cell->bel.tile)->die;
|
||||
if (!clkin[die]->getPort(ctx->idf("CLK%d", index)))
|
||||
clkin[die]->connectPort(ctx->idf("CLK%d", index), in_net->driver.cell->getPort(id_I));
|
||||
if (!clkin[die]->getPort(ctx->idf("CLK%d", index))) {
|
||||
CellInfo *gpio = in_net->driver.cell->getPort(id_GPIO_IN)->driver.cell;
|
||||
clkin[die]->connectPort(ctx->idf("CLK%d", index), gpio->getPort(id_I));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -167,7 +169,7 @@ void GateMatePacker::pack_bufg()
|
|||
int die = uarch->preferred_die;
|
||||
if (in_net->driver.cell) {
|
||||
bool user_glb = true;
|
||||
if (ctx->getBelBucketForCellType(in_net->driver.cell->type) == id_GPIO) {
|
||||
if (ctx->getBelBucketForCellType(in_net->driver.cell->type) == id_IOSEL) {
|
||||
auto pad_info = uarch->bel_to_pad[in_net->driver.cell->bel];
|
||||
if (pad_info->flags) {
|
||||
die = uarch->tile_extra_data(in_net->driver.cell->bel.tile)->die;
|
||||
|
|
@ -355,7 +357,7 @@ void GateMatePacker::pack_pll()
|
|||
if (ctx->getBelBucketForCellType(clk->driver.cell->type) == id_CC_BUFG) {
|
||||
clk = clk->driver.cell->getPort(id_I);
|
||||
}
|
||||
if (ctx->getBelBucketForCellType(clk->driver.cell->type) == id_GPIO) {
|
||||
if (ctx->getBelBucketForCellType(clk->driver.cell->type) == id_IOSEL) {
|
||||
auto pad_info = uarch->bel_to_pad[clk->driver.cell->bel];
|
||||
if (pad_info->flags != 0) {
|
||||
die = uarch->tile_extra_data(clk->driver.cell->bel.tile)->die;
|
||||
|
|
@ -390,7 +392,7 @@ void GateMatePacker::pack_pll()
|
|||
ci.connectPort(id_CLK_REF, in);
|
||||
clk = in;
|
||||
}
|
||||
if (ctx->getBelBucketForCellType(clk->driver.cell->type) != id_GPIO)
|
||||
if (ctx->getBelBucketForCellType(clk->driver.cell->type) != id_IOSEL)
|
||||
log_error("CLK_REF must be driven with GPIO pin.\n");
|
||||
auto pad_info = uarch->bel_to_pad[clk->driver.cell->bel];
|
||||
if (pad_info->flags == 0)
|
||||
|
|
|
|||
|
|
@ -318,7 +318,32 @@ void GateMatePacker::pack_io()
|
|||
log_error("Can't place %s at %s because it's already taken by %s\n", ctx->nameOf(&ci), ctx->nameOfBel(bel),
|
||||
ctx->nameOf(ctx->getBoundBelCell(bel)));
|
||||
}
|
||||
|
||||
// Place IOSEL
|
||||
CellInfo *iosel = create_cell_ptr(id_IOSEL, ctx->idf("%s$iosel", ci.name.c_str(ctx)));
|
||||
iosel->params = ci.params;
|
||||
ctx->bindBel(bel, iosel, PlaceStrength::STRENGTH_FIXED);
|
||||
|
||||
// Rewire
|
||||
ci.movePortTo(id_A, iosel, id_A);
|
||||
ci.movePortTo(id_T, iosel, id_T);
|
||||
ci.movePortTo(id_Y, iosel, id_Y);
|
||||
|
||||
// Place GPIO
|
||||
Loc l = ctx->getBelLocation(bel);
|
||||
bel = ctx->getBelByLocation({l.x, l.y, 0});
|
||||
ctx->bindBel(bel, &ci, PlaceStrength::STRENGTH_FIXED);
|
||||
|
||||
// Remove not needed params
|
||||
ci.params.clear();
|
||||
|
||||
// Add connections between GPIO and IOSEL
|
||||
if (iosel->getPort(id_A))
|
||||
ci.connectPorts(id_A, iosel, id_GPIO_OUT);
|
||||
if (iosel->getPort(id_Y))
|
||||
ci.connectPorts(id_Y, iosel, id_GPIO_IN);
|
||||
if (iosel->getPort(id_T))
|
||||
ci.connectPorts(id_T, iosel, id_GPIO_EN);
|
||||
}
|
||||
flush_cells();
|
||||
}
|
||||
|
|
@ -329,7 +354,7 @@ void GateMatePacker::pack_io_sel()
|
|||
std::vector<CellInfo *> cells;
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo &ci = *cell.second;
|
||||
if (!uarch->getBelBucketForCellType(ci.type).in(id_GPIO))
|
||||
if (!uarch->getBelBucketForCellType(ci.type).in(id_IOSEL))
|
||||
continue;
|
||||
|
||||
cells.push_back(&ci);
|
||||
|
|
@ -457,7 +482,8 @@ void GateMatePacker::pack_io_sel()
|
|||
} else {
|
||||
ci.params[id_OUT_SIGNAL] = Property(Property::State::S1);
|
||||
bool ff_obf_merged = false;
|
||||
if (ff_obf && do_net->driver.cell->type == id_CC_DFF && do_net->users.entries() == 1) {
|
||||
if (ff_obf && do_net->driver.cell && do_net->driver.cell->type == id_CC_DFF &&
|
||||
do_net->users.entries() == 1) {
|
||||
CellInfo *dff = do_net->driver.cell;
|
||||
if (is_gpio_valid_dff(dff)) {
|
||||
ci.params[id_OUT1_FF] = Property(Property::State::S1);
|
||||
|
|
@ -477,7 +503,7 @@ void GateMatePacker::pack_io_sel()
|
|||
}
|
||||
}
|
||||
bool oddr_merged = false;
|
||||
if (do_net->driver.cell->type == id_CC_ODDR && do_net->users.entries() == 1) {
|
||||
if (do_net->driver.cell && do_net->driver.cell->type == id_CC_ODDR && do_net->users.entries() == 1) {
|
||||
CellInfo *oddr = do_net->driver.cell;
|
||||
ci.params[id_OUT1_FF] = Property(Property::State::S1);
|
||||
ci.params[id_OUT2_FF] = Property(Property::State::S1);
|
||||
|
|
@ -521,7 +547,8 @@ void GateMatePacker::pack_io_sel()
|
|||
ff_ibf_merged = merge_ibf(di_net, ci, use_custom_clock);
|
||||
}
|
||||
bool iddr_merged = false;
|
||||
if (di_net->users.entries() == 1 && (*di_net->users.begin()).cell->type == id_CC_IDDR) {
|
||||
if (di_net->users.entries() == 1 && (*di_net->users.begin()).cell->type == id_CC_IDDR &&
|
||||
(*di_net->users.begin()).port == id_D) {
|
||||
iddr_merged = merge_iddr(di_net, ci, use_custom_clock);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue