2020-06-13 05:09:46 +08:00
|
|
|
/*
|
|
|
|
* nextpnr -- Next Generation Place and Route
|
|
|
|
*
|
2021-01-07 00:22:17 +08:00
|
|
|
* Copyright (C) 2021 Lofty <dan.ravensloft@gmail.com>
|
2020-06-13 05:09:46 +08:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-01-07 00:22:17 +08:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include "nextpnr.h"
|
|
|
|
|
2021-05-01 01:40:24 +08:00
|
|
|
#include "cyclonev.h"
|
2021-01-07 00:22:17 +08:00
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_BEGIN
|
|
|
|
|
2021-01-07 02:07:59 +08:00
|
|
|
using namespace mistral;
|
2021-01-07 00:22:17 +08:00
|
|
|
|
|
|
|
Arch::Arch(ArchArgs args)
|
|
|
|
{
|
|
|
|
this->args = args;
|
|
|
|
this->cyclonev = mistral::CycloneV::get_model(args.device);
|
|
|
|
NPNR_ASSERT(this->cyclonev != nullptr);
|
2021-02-04 22:28:39 +08:00
|
|
|
|
|
|
|
for (int x = 0; x < cyclonev->get_tile_sx(); x++) {
|
|
|
|
for (int y = 0; y < cyclonev->get_tile_sy(); y++) {
|
|
|
|
CycloneV::pos_t pos = cyclonev->xy2pos(x, y);
|
|
|
|
|
|
|
|
for (CycloneV::block_type_t bel : cyclonev->pos_get_bels(pos)) {
|
|
|
|
switch (bel) {
|
|
|
|
case CycloneV::block_type_t::LAB:
|
|
|
|
/*
|
2021-05-01 01:40:24 +08:00
|
|
|
* nextpnr and mistral disagree on what a BEL is: mistral thinks an entire LAB
|
|
|
|
* is one BEL, but nextpnr wants something with more precision.
|
|
|
|
*
|
|
|
|
* One LAB contains 10 ALMs.
|
|
|
|
* One ALM contains 2 LUT outputs and 4 flop outputs.
|
|
|
|
*/
|
2021-02-04 22:28:39 +08:00
|
|
|
for (int z = 0; z < 60; z++) {
|
|
|
|
this->bel_list.push_back(BelId(pos, z));
|
|
|
|
}
|
2021-05-01 01:40:24 +08:00
|
|
|
break;
|
2021-02-04 22:28:39 +08:00
|
|
|
case CycloneV::block_type_t::GPIO:
|
|
|
|
// GPIO tiles contain 4 pins.
|
|
|
|
for (int z = 0; z < 4; z++) {
|
|
|
|
this->bel_list.push_back(BelId(pos, z));
|
|
|
|
}
|
2021-05-01 01:40:24 +08:00
|
|
|
break;
|
2021-02-04 22:28:39 +08:00
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-07 00:22:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Arch::getTileBelDimZ(int x, int y) const
|
|
|
|
{
|
|
|
|
CycloneV::pos_t pos = cyclonev->xy2pos(x, y);
|
|
|
|
|
|
|
|
for (CycloneV::block_type_t bel : cyclonev->pos_get_bels(pos)) {
|
|
|
|
switch (bel) {
|
|
|
|
case CycloneV::block_type_t::LAB:
|
|
|
|
/*
|
2021-05-01 01:40:24 +08:00
|
|
|
* nextpnr and mistral disagree on what a BEL is: mistral thinks an entire LAB
|
|
|
|
* is one BEL, but nextpnr wants something with more precision.
|
|
|
|
*
|
|
|
|
* One LAB contains 10 ALMs.
|
|
|
|
* One ALM contains 2 LUT outputs and 4 flop outputs.
|
|
|
|
*/
|
2021-01-07 00:22:17 +08:00
|
|
|
return 60;
|
|
|
|
case CycloneV::block_type_t::GPIO:
|
|
|
|
// GPIO tiles contain 4 pins.
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// As a temporary hack, only LABs and IO are allowed to be placed, so every other tile type has zero BELs.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-05-01 01:40:24 +08:00
|
|
|
BelId Arch::getBelByName(IdStringList name) const
|
2021-01-07 00:22:17 +08:00
|
|
|
{
|
|
|
|
char bel_type_str[80] = {0};
|
|
|
|
int x = 0, y = 0, z = 0;
|
|
|
|
BelId bel;
|
|
|
|
|
2021-05-01 01:40:24 +08:00
|
|
|
sscanf(name[0].c_str(this), "%25s.%d.%d.%d", bel_type_str, &x, &y, &z);
|
2021-01-07 00:22:17 +08:00
|
|
|
|
|
|
|
auto bel_type = cyclonev->block_type_lookup(std::string{bel_type_str});
|
|
|
|
|
|
|
|
bel.pos = CycloneV::xy2pos(x, y);
|
|
|
|
bel.z = (bel_type << 8) | z;
|
|
|
|
|
|
|
|
return bel;
|
|
|
|
}
|
|
|
|
|
2021-05-01 01:40:24 +08:00
|
|
|
IdStringList Arch::getBelName(BelId bel) const
|
2021-01-07 00:22:17 +08:00
|
|
|
{
|
|
|
|
char bel_str[80] = {0};
|
|
|
|
|
|
|
|
int x = CycloneV::pos2x(bel.pos);
|
|
|
|
int y = CycloneV::pos2y(bel.pos);
|
2021-01-07 02:07:59 +08:00
|
|
|
int z = bel.z & 0xFF;
|
2021-01-07 00:22:17 +08:00
|
|
|
int bel_type = bel.z >> 8;
|
|
|
|
|
|
|
|
snprintf(bel_str, 80, "%s.%03d.%03d.%03d", cyclonev->block_type_names[bel_type], x, y, z);
|
|
|
|
|
2021-05-01 01:40:24 +08:00
|
|
|
return IdStringList(id(bel_str));
|
2021-02-03 08:12:14 +08:00
|
|
|
}
|
2021-01-07 00:22:17 +08:00
|
|
|
|
2021-02-04 10:29:59 +08:00
|
|
|
std::vector<BelId> Arch::getBelsByTile(int x, int y) const
|
|
|
|
{
|
|
|
|
// This should probably be redesigned, but it's a hack.
|
|
|
|
std::vector<BelId> bels{};
|
|
|
|
|
|
|
|
CycloneV::pos_t pos = cyclonev->xy2pos(x, y);
|
|
|
|
|
2021-02-04 22:28:39 +08:00
|
|
|
for (CycloneV::block_type_t cvbel : cyclonev->pos_get_bels(pos)) {
|
|
|
|
switch (cvbel) {
|
2021-02-04 10:29:59 +08:00
|
|
|
case CycloneV::block_type_t::LAB:
|
|
|
|
/*
|
2021-05-01 01:40:24 +08:00
|
|
|
* nextpnr and mistral disagree on what a BEL is: mistral thinks an entire LAB
|
|
|
|
* is one BEL, but nextpnr wants something with more precision.
|
|
|
|
*
|
|
|
|
* One LAB contains 10 ALMs.
|
|
|
|
* One ALM contains 2 LUT outputs and 4 flop outputs.
|
|
|
|
*/
|
2021-02-04 10:29:59 +08:00
|
|
|
for (int z = 0; z < 60; z++) {
|
|
|
|
bels.push_back(BelId(pos, z));
|
|
|
|
}
|
2021-05-01 01:40:24 +08:00
|
|
|
break;
|
2021-02-04 10:29:59 +08:00
|
|
|
case CycloneV::block_type_t::GPIO:
|
|
|
|
// GPIO tiles contain 4 pins.
|
|
|
|
for (int z = 0; z < 4; z++) {
|
|
|
|
bels.push_back(BelId(pos, z));
|
|
|
|
}
|
2021-05-01 01:40:24 +08:00
|
|
|
break;
|
2021-02-04 10:29:59 +08:00
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bels;
|
|
|
|
}
|
|
|
|
|
|
|
|
IdString Arch::getBelType(BelId bel) const
|
|
|
|
{
|
2021-02-04 22:28:39 +08:00
|
|
|
for (CycloneV::block_type_t cvbel : cyclonev->pos_get_bels(bel.pos)) {
|
|
|
|
switch (cvbel) {
|
2021-02-04 10:29:59 +08:00
|
|
|
case CycloneV::block_type_t::LAB:
|
|
|
|
/*
|
2021-05-01 01:40:24 +08:00
|
|
|
* nextpnr and mistral disagree on what a BEL is: mistral thinks an entire LAB
|
|
|
|
* is one BEL, but nextpnr wants something with more precision.
|
|
|
|
*
|
|
|
|
* One LAB contains 10 ALMs.
|
|
|
|
* One ALM contains 2 LUT outputs and 4 flop outputs.
|
|
|
|
*/
|
2021-02-04 10:29:59 +08:00
|
|
|
return IdString(this, "LAB");
|
|
|
|
case CycloneV::block_type_t::GPIO:
|
|
|
|
// GPIO tiles contain 4 pins.
|
|
|
|
return IdString(this, "GPIO");
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IdString();
|
|
|
|
}
|
2021-01-07 00:22:17 +08:00
|
|
|
|
|
|
|
NEXTPNR_NAMESPACE_END
|