aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYRabbit <rabbit@yrabbit.cyou>2021-08-23 16:19:02 +1000
committerYRabbit <rabbit@yrabbit.cyou>2021-08-23 16:19:02 +1000
commite4196f32d388186dddfd590264561698f111e0d1 (patch)
tree4605373dc805c4351c3b4cd5b69819f8c4a1a101
parent897a2fccb64ac52ec4d3ce728fad91c3a5a96ff1 (diff)
downloadnextpnr-e4196f32d388186dddfd590264561698f111e0d1.tar.gz
nextpnr-e4196f32d388186dddfd590264561698f111e0d1.tar.bz2
nextpnr-e4196f32d388186dddfd590264561698f111e0d1.zip
gowin: Add the IO[TRBL]style placement recognition
Specifying pin placement with this notation (e.g. IOR4B) allows to use the same constraint file without changes for different packages and even different families. The vendor router also understands this notation. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
-rw-r--r--gowin/arch.cc42
1 files changed, 37 insertions, 5 deletions
diff --git a/gowin/arch.cc b/gowin/arch.cc
index 0bc0ef56..a4be92cd 100644
--- a/gowin/arch.cc
+++ b/gowin/arch.cc
@@ -482,14 +482,34 @@ DelayQuad Arch::getWireTypeDelay(IdString wire)
}
}
+static Loc getLoc(std::smatch match, int maxX, int maxY)
+{
+ int col = std::stoi(match[2]);
+ int row = 1; // Top
+ std::string side = match[1].str();
+ if (side == "R") {
+ row = col;
+ col = maxX;
+ } else if (side == "B") {
+ row = maxY;
+ } else if (side == "L") {
+ row = col;
+ col = 1;
+ }
+ int z = match[3].str()[0] - 'A';
+ return Loc(col - 1, row - 1, z);
+}
+
void Arch::read_cst(std::istream &in)
{
std::regex iobre = std::regex("IO_LOC +\"([^\"]+)\" +([^ ;]+) *;.*");
std::regex portre = std::regex("IO_PORT +\"([^\"]+)\" +([^;]+;).*");
std::regex port_attrre = std::regex("([^ =;]+=[^ =;]+) *([^;]*;)");
- std::smatch match, match_attr;
- std::string line;
+ std::regex iobelre = std::regex("IO([TRBL])([0-9]+)([A-Z])");
+ std::smatch match, match_attr, match_pinloc;
+ std::string line, pinline;
bool io_loc;
+
while (!in.eof()) {
std::getline(in, line);
io_loc = true;
@@ -512,11 +532,23 @@ void Arch::read_cst(std::istream &in)
}
if (io_loc) { // IO_LOC name pin
IdString pinname = id(match[2]);
+ pinline = match[2];
const PairPOD *belname = pairLookup(package->pins.get(), package->num_pins, pinname.index);
- if (belname == nullptr)
+ if (belname != nullptr) {
+ std::string bel = IdString(belname->src_id).str(this);
+ it->second->attrs[IdString(ID_BEL)] = bel;
+ } else if (std::regex_match(pinline, match_pinloc, iobelre)) {
+ // may be it's IOx#[AB] style?
+ Loc loc = getLoc(match_pinloc, getGridDimX(), getGridDimY());
+ BelId bel = getBelByLocation(loc);
+ if (bel == BelId()) {
+ log_error("Pin %s not found\n", pinline.c_str());
+ }
+ std::string belname = getCtx()->nameOfBel(bel);
+ it->second->attrs[IdString(ID_BEL)] = belname;
+ } else {
log_error("Pin %s not found\n", pinname.c_str(this));
- std::string bel = IdString(belname->src_id).str(this);
- it->second->attrs[IdString(ID_BEL)] = bel;
+ }
} else { // IO_PORT attr=value
std::string attr_val = match[2];
while (std::regex_match(attr_val, match_attr, port_attrre)) {