diff options
author | YRabbit <rabbit@yrabbit.cyou> | 2021-08-23 16:19:02 +1000 |
---|---|---|
committer | YRabbit <rabbit@yrabbit.cyou> | 2021-08-23 16:19:02 +1000 |
commit | e4196f32d388186dddfd590264561698f111e0d1 (patch) | |
tree | 4605373dc805c4351c3b4cd5b69819f8c4a1a101 | |
parent | 897a2fccb64ac52ec4d3ce728fad91c3a5a96ff1 (diff) | |
download | nextpnr-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.cc | 42 |
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)) { |