aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYRabbit <rabbit@yrabbit.cyou>2021-08-31 07:36:11 +1000
committerYRabbit <rabbit@yrabbit.cyou>2021-08-31 07:36:11 +1000
commit23a5e9185887758e7d5fd83fe49686aaa5783896 (patch)
tree5332e0cf993a7173ed578ab4b3160ffb0e36c4ae
parent0e83db47a067b55f45567c89a08af470196a18e7 (diff)
downloadnextpnr-23a5e9185887758e7d5fd83fe49686aaa5783896.tar.gz
nextpnr-23a5e9185887758e7d5fd83fe49686aaa5783896.tar.bz2
nextpnr-23a5e9185887758e7d5fd83fe49686aaa5783896.zip
gowin: Add constraints on primitive placement.
Added support for the INS_LOC instruction in the constraints file (.CST), which is used to specify object placement. Expanded treatment of IO_LOC/IO_PORT constraints, which now can be applied to both ports and IO buffers. Port constraints have priority. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
-rw-r--r--gowin/arch.cc43
-rw-r--r--gowin/arch.h3
-rw-r--r--gowin/pack.cc16
3 files changed, 48 insertions, 14 deletions
diff --git a/gowin/arch.cc b/gowin/arch.cc
index a4be92cd..813d52ed 100644
--- a/gowin/arch.cc
+++ b/gowin/arch.cc
@@ -506,21 +506,31 @@ void Arch::read_cst(std::istream &in)
std::regex portre = std::regex("IO_PORT +\"([^\"]+)\" +([^;]+;).*");
std::regex port_attrre = std::regex("([^ =;]+=[^ =;]+) *([^;]*;)");
std::regex iobelre = std::regex("IO([TRBL])([0-9]+)([A-Z])");
+ std::regex inslocre = std::regex("INS_LOC +\"([^\"]+)\" +R([0-9]+)C([0-9]+)\\[([0-9])\\]\\[([AB])\\] *;.*");
std::smatch match, match_attr, match_pinloc;
std::string line, pinline;
- bool io_loc;
+ enum
+ {
+ ioloc,
+ ioport,
+ insloc
+ } cst_type;
while (!in.eof()) {
std::getline(in, line);
- io_loc = true;
+ cst_type = ioloc;
if (!std::regex_match(line, match, iobre)) {
if (std::regex_match(line, match, portre)) {
- io_loc = false;
+ cst_type = ioport;
} else {
- if ((!line.empty()) && (line.rfind("//", 0) == std::string::npos)) {
- log_warning("Invalid constraint: %s\n", line.c_str());
+ if (std::regex_match(line, match, inslocre)) {
+ cst_type = insloc;
+ } else {
+ if ((!line.empty()) && (line.rfind("//", 0) == std::string::npos)) {
+ log_warning("Invalid constraint: %s\n", line.c_str());
+ }
+ continue;
}
- continue;
}
}
@@ -530,13 +540,14 @@ void Arch::read_cst(std::istream &in)
log_info("Cell %s not found\n", net.c_str(this));
continue;
}
- if (io_loc) { // IO_LOC name pin
+ switch (cst_type) {
+ case ioloc: { // 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) {
std::string bel = IdString(belname->src_id).str(this);
- it->second->attrs[IdString(ID_BEL)] = bel;
+ it->second->setAttr(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());
@@ -545,20 +556,30 @@ void Arch::read_cst(std::istream &in)
log_error("Pin %s not found\n", pinline.c_str());
}
std::string belname = getCtx()->nameOfBel(bel);
- it->second->attrs[IdString(ID_BEL)] = belname;
+ it->second->setAttr(IdString(ID_BEL), belname);
} else {
log_error("Pin %s not found\n", pinname.c_str(this));
}
- } else { // IO_PORT attr=value
+ } break;
+ case insloc: { // INS_LOC
+ int slice = std::stoi(match[4].str()) * 2;
+ if (match[5].str() == "B") {
+ ++slice;
+ }
+ std::string belname = std::string("R") + match[2].str() + "C" + match[3].str() + stringf("_SLICE%d", slice);
+ it->second->setAttr(IdString(ID_BEL), belname);
+ } break;
+ default: { // IO_PORT attr=value
std::string attr_val = match[2];
while (std::regex_match(attr_val, match_attr, port_attrre)) {
std::string attr = "&";
attr += match_attr[1];
boost::algorithm::to_upper(attr);
- it->second->attrs[id(attr)] = 1;
+ it->second->setAttr(id(attr), 1);
attr_val = match_attr[2];
}
}
+ }
}
}
diff --git a/gowin/arch.h b/gowin/arch.h
index 8ba037de..8774c303 100644
--- a/gowin/arch.h
+++ b/gowin/arch.h
@@ -446,6 +446,9 @@ struct Arch : BaseArch<ArchRanges>
bool cellsCompatible(const CellInfo **cells, int count) const;
std::vector<IdString> cell_types;
+
+ // Permissible combinations of modes in a single slice
+ std::map<const IdString, IdString> dff_comp_mode;
};
NEXTPNR_NAMESPACE_END
diff --git a/gowin/pack.cc b/gowin/pack.cc
index 213889f5..708f06da 100644
--- a/gowin/pack.cc
+++ b/gowin/pack.cc
@@ -253,9 +253,19 @@ static void pack_io(Context *ctx)
auto gwiob = new_cells.back().get();
packed_cells.insert(ci->name);
- if (iob != nullptr)
- for (auto &attr : iob->attrs)
- gwiob->attrs[attr.first] = attr.second;
+ if (iob != nullptr) {
+ // in Gowin .CST port attributes take precedence over cell attributes.
+ // first copy cell attrs related to IO
+ for (auto &attr : ci->attrs) {
+ if (attr.first == IdString(ID_BEL) || attr.first.str(ctx)[0] == '&') {
+ gwiob->setAttr(attr.first, attr.second);
+ }
+ }
+ // rewrite attributes from the port
+ for (auto &attr : iob->attrs) {
+ gwiob->setAttr(attr.first, attr.second);
+ }
+ }
}
}
for (auto pcell : packed_cells) {