From ea3d579c131cdb04a3434710531f07be12cd3257 Mon Sep 17 00:00:00 2001 From: Pepijn de Vos Date: Mon, 14 Dec 2020 16:46:28 +0100 Subject: [PATCH] constraints --- gowin/arch.cc | 116 ++++++++++++++++++++++++++++++--------------- gowin/arch.h | 13 ++++- gowin/cells.cc | 6 --- gowin/constids.inc | 1 + gowin/main.cc | 14 +++--- gowin/pack.cc | 4 +- 6 files changed, 98 insertions(+), 56 deletions(-) diff --git a/gowin/arch.cc b/gowin/arch.cc index 49520e98..9efd7a11 100644 --- a/gowin/arch.cc +++ b/gowin/arch.cc @@ -19,6 +19,7 @@ #include #include +#include #include "embed.h" #include "nextpnr.h" #include "placer1.h" @@ -300,7 +301,7 @@ IdString Arch::wireToGlobal(int &row, int &col, const DatabasePOD *db, IdString return id(buf); } -const PairPOD* pairLookup(const PairPOD *list, const size_t len, const int dest) +const PairPOD *pairLookup(const PairPOD *list, const size_t len, const int dest) { for (size_t i = 0; i < len; i++) { const PairPOD *pair = &list[i]; @@ -311,36 +312,34 @@ const PairPOD* pairLookup(const PairPOD *list, const size_t len, const int dest) return nullptr; } -bool aliasCompare (GlobalAliasPOD i, GlobalAliasPOD j) { - return (i.dest_row -const T* genericLookup(const T *first, int len, const T val, C compare) +bool aliasCompare(GlobalAliasPOD i, GlobalAliasPOD j) { - auto res = std::lower_bound(first, first+len, val, compare); - if (res-first != len && !compare(val, *res)) { + return (i.dest_row < j.dest_row) || (i.dest_row == j.dest_row && i.dest_col < j.dest_col) || + (i.dest_row == j.dest_row && i.dest_col == j.dest_col && i.dest_id < j.dest_id); +} +bool timingCompare(TimingPOD i, TimingPOD j) { return i.name_id < j.name_id; } + +template const T *genericLookup(const T *first, int len, const T val, C compare) +{ + auto res = std::lower_bound(first, first + len, val, compare); + if (res - first != len && !compare(val, *res)) { return res; } else { return nullptr; } } -DelayInfo delayLookup(const TimingPOD* first, int len, IdString name) { +DelayInfo delayLookup(const TimingPOD *first, int len, IdString name) +{ TimingPOD needle; needle.name_id = name.index; const TimingPOD *timing = genericLookup(first, len, needle, timingCompare); DelayInfo info; if (timing != nullptr) { - info.maxFall = std::max(timing->ff, timing->rf)/1000; - info.minFall = std::min(timing->ff, timing->rf)/1000; - info.maxRaise = std::max(timing->rr, timing->fr)/1000; - info.minRaise = std::min(timing->rr, timing->fr)/1000; + info.maxFall = std::max(timing->ff, timing->rf) / 1000; + info.minFall = std::min(timing->ff, timing->rf) / 1000; + info.maxRaise = std::max(timing->rr, timing->fr) / 1000; + info.minRaise = std::min(timing->rr, timing->fr) / 1000; } else { info.maxFall = 0; info.minFall = 0; @@ -350,11 +349,11 @@ DelayInfo delayLookup(const TimingPOD* first, int len, IdString name) { return info; } -DelayInfo Arch::getWireTypeDelay(IdString wire) { +DelayInfo Arch::getWireTypeDelay(IdString wire) +{ IdString len; IdString glbsrc; - switch (wire.index) - { + switch (wire.index) { case ID_X01: case ID_X02: case ID_X03: @@ -458,7 +457,7 @@ DelayInfo Arch::getWireTypeDelay(IdString wire) { glbsrc = id_BRANCH_PCLK; break; default: - if (wire.str(this).rfind("SPINE", 0) == 0){ + if (wire.str(this).rfind("SPINE", 0) == 0) { glbsrc = ID_CENT_SPINE_PCLK; } else if (wire.str(this).rfind("UNK", 0) == 0) { glbsrc = ID_PIO_CENT_PCLK; @@ -479,12 +478,35 @@ DelayInfo Arch::getWireTypeDelay(IdString wire) { } } +void Arch::read_cst(std::istream &in) { + std::regex iobre = std::regex("IO_LOC +\"([^\"]+)\" +([^ ;]+);"); + std::smatch match; + std::string line; + while (!in.eof()) { + std::getline(in, line); + if(!std::regex_match(line, match, iobre)) continue; + std::cout << match[1] << " " << match[2] << std::endl; + IdString net = id(match[1]); + IdString pinname = id(match[2]); + const PairPOD *belname = pairLookup(package->pins.get(), package->num_pins, pinname.index); + if ( belname == nullptr) + log_error("Pin %s not found", pinname.c_str(this)); + //BelId bel = getBelByName(belname->src_id); + // for (auto cell : sorted(cells)) { + // std::cout << cell.first.str(this) << std::endl; + // } + auto it = cells.find(net); + if (it == cells.end()) + log_error("Cell %s not found", net.c_str(this)); + std::string bel = IdString(belname->src_id).str(this); + it->second->attrs[ID_BEL] = bel; + } +} Arch::Arch(ArchArgs args) : args(args) { family = args.family; device = args.device; - package = args.package; // Load database std::string chipdb = stringf("gowin/chipdb-%s.bin", family.c_str()); @@ -501,9 +523,9 @@ Arch::Arch(ArchArgs args) : args(args) } // setup timing info speed = nullptr; - for (unsigned int i=0; inum_speeds; i++) { + for (unsigned int i = 0; i < db->num_speeds; i++) { const TimingClassPOD *tc = &db->speeds[i]; - //std::cout << IdString(tc->name_id).str(this) << std::endl; + // std::cout << IdString(tc->name_id).str(this) << std::endl; if (IdString(tc->name_id) == id(args.speed)) { speed = tc->groups.get(); break; @@ -512,6 +534,22 @@ Arch::Arch(ArchArgs args) : args(args) if (speed == nullptr) { log_error("Unsuported speed grade '%s'.\n", args.speed.c_str()); } + package = nullptr; + for (unsigned int i = 0; i < db->num_packages; i++) { + auto pkg = &db->packages[i]; + // std::cout << IdString(pkg->name_id).str(this) << std::endl; + if (IdString(pkg->name_id) == id(args.package)) { + package = pkg; + break; + } + // for (int j=0; j < pkg->num_pins; j++) { + // auto pin = pkg->pins[j]; + // std::cout << IdString(pin.src_id).str(this) << " " << IdString(pin.dest_id).str(this) << std::endl; + // } + } + if (package == nullptr) { + log_error("Unsuported package '%s'.\n", args.package.c_str()); + } // setup db char buf[32]; for (int i = 0; i < db->rows * db->cols; i++) { @@ -519,9 +557,9 @@ Arch::Arch(ArchArgs args) : args(args) int col = i % db->cols; const TilePOD *tile = db->grid[i].get(); // setup wires - const PairPOD* pips[2] = { tile->pips.get(), tile->clock_pips.get()}; - unsigned int num_pips[2] = { tile->num_pips, tile->num_clock_pips}; - for(int p = 0; p < 2; p++) { + const PairPOD *pips[2] = {tile->pips.get(), tile->clock_pips.get()}; + unsigned int num_pips[2] = {tile->num_pips, tile->num_clock_pips}; + for (int p = 0; p < 2; p++) { for (unsigned int j = 0; j < num_pips[p]; j++) { const PairPOD pip = pips[p][j]; int destrow = row; @@ -644,9 +682,9 @@ Arch::Arch(ArchArgs args) : args(args) int row = i / db->cols; int col = i % db->cols; const TilePOD *tile = db->grid[i].get(); - const PairPOD* pips[2] = { tile->pips.get(), tile->clock_pips.get()}; - unsigned int num_pips[2] = { tile->num_pips, tile->num_clock_pips}; - for(int p = 0; p < 2; p++) { + const PairPOD *pips[2] = {tile->pips.get(), tile->clock_pips.get()}; + unsigned int num_pips[2] = {tile->num_pips, tile->num_clock_pips}; + for (int p = 0; p < 2; p++) { for (unsigned int j = 0; j < num_pips[p]; j++) { const PairPOD pip = pips[p][j]; int destrow = row; @@ -659,13 +697,13 @@ Arch::Arch(ArchArgs args) : args(args) IdString gsrcname = wireToGlobal(srcrow, srccol, db, srcid); snprintf(buf, 32, "R%dC%d_%s_%s", row + 1, col + 1, IdString(pip.src_id).c_str(this), - IdString(pip.dest_id).c_str(this)); + IdString(pip.dest_id).c_str(this)); IdString pipname = id(buf); DelayInfo delay = getWireTypeDelay(pip.dest_id); // local alias auto local_alias = pairLookup(tile->aliases.get(), tile->num_aliases, srcid.index); // std::cout << "srcid " << srcid.str(this) << std::endl; - if(local_alias!=nullptr) { + if (local_alias != nullptr) { srcid = local_alias->src_id; gsrcname = wireToGlobal(srcrow, srccol, db, srcid); } @@ -676,12 +714,12 @@ Arch::Arch(ArchArgs args) : args(args) alias.dest_row = srcrow; alias.dest_id = srcid.index; auto alias_src = genericLookup(db->aliases.get(), db->num_aliases, alias, aliasCompare); - if(alias_src!=nullptr) { + if (alias_src != nullptr) { srccol = alias_src->src_col; srcrow = alias_src->src_row; srcid = alias_src->src_id; gsrcname = wireToGlobal(srcrow, srccol, db, srcid); - //std::cout << buf << std::endl; + // std::cout << buf << std::endl; } addPip(pipname, pip.dest_id, gsrcname, gdestname, delay, Loc(col, row, j)); } @@ -1133,7 +1171,7 @@ void Arch::assignArchInfo() // add timing paths addCellTimingClock(cname, id_CLK); IdString ports[4] = {id_A, id_B, id_C, id_D}; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { DelayInfo setup = delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clksetpos); DelayInfo hold = delayLookup(speed->dff.timings.get(), speed->dff.num_timings, id_clkholdpos); // DelayInfo setup = getDelayFromNS(0.1); @@ -1144,7 +1182,7 @@ void Arch::assignArchInfo() // DelayInfo clkout = getDelayFromNS(0.1); addCellTimingClockToOut(cname, id_Q, id_CLK, clkout); IdString port_delay[4] = {id_a_f, id_b_f, id_c_f, id_d_f}; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { DelayInfo delay = delayLookup(speed->lut.timings.get(), speed->lut.num_timings, port_delay[i]); // DelayInfo delay = getDelayFromNS(0.1); addCellTimingDelay(cname, ports[i], id_F, delay); @@ -1167,7 +1205,7 @@ bool Arch::cellsCompatible(const CellInfo **cells, int count) const const CellInfo *ci = cells[i]; if (ci->is_slice && ci->slice_clk != nullptr) { Loc loc = getBelLocation(ci->bel); - int cls = loc.z/2; + int cls = loc.z / 2; bool ff_used = ci->params.at(id_FF_USED).as_bool(); if (loc.z >= 6 && ff_used) // top slice have no ff return false; diff --git a/gowin/arch.h b/gowin/arch.h index 3df0a9ed..55a1f6f5 100644 --- a/gowin/arch.h +++ b/gowin/arch.h @@ -118,6 +118,12 @@ NPNR_PACKED_STRUCT(struct TimingClassPOD { RelPtr groups; }); +NPNR_PACKED_STRUCT(struct PackagePOD { + uint32_t name_id; + uint32_t num_pins; + RelPtr pins; +}); + NPNR_PACKED_STRUCT(struct DatabasePOD { RelPtr family; uint32_t version; @@ -128,6 +134,8 @@ NPNR_PACKED_STRUCT(struct DatabasePOD { RelPtr aliases; uint32_t num_speeds; RelPtr speeds; + uint32_t num_packages; + RelPtr packages; uint16_t num_constids; uint16_t num_ids; RelPtr> id_strs; @@ -141,7 +149,7 @@ struct ArchArgs std::string package; // y = mx + c relationship between distance and delay for interconnect // delay estimates - double delayScale = 0.1, delayOffset = 0.4; + double delayScale = 0.4, delayOffset = 0.4; }; struct WireInfo; @@ -229,7 +237,7 @@ struct Arch : BaseCtx { std::string family; std::string device; - std::string package; + const PackagePOD *package; const TimingGroupsPOD *speed; std::unordered_map wires; @@ -287,6 +295,7 @@ struct Arch : BaseCtx IdString wireToGlobal(int &row, int &col, const DatabasePOD* db, IdString &wire); DelayInfo getWireTypeDelay(IdString wire); + void read_cst(std::istream &in); // --------------------------------------------------------------- // Common Arch API. Every arch must provide the following methods. diff --git a/gowin/cells.cc b/gowin/cells.cc index fb049d4c..92d564dd 100644 --- a/gowin/cells.cc +++ b/gowin/cells.cc @@ -74,9 +74,6 @@ std::unique_ptr create_generic_cell(Context *ctx, IdString type, std:: void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff) { - for(auto f : lut->ports) { - std::cout << f.first.str(ctx) << std::endl; - } lc->params[id_INIT] = lut->params[id_INIT]; IdString sim_names[4] = {id_I0, id_I1, id_I2, id_I3}; @@ -101,9 +98,6 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l replace_port(dff, id_RESET, lc, id_LSR); replace_port(dff, id_CLEAR, lc, id_LSR); replace_port(dff, id_PRESET, lc, id_LSR); - for(auto f : dff->ports) { - std::cout << f.first.str(ctx) << std::endl; - } if (pass_thru_lut) { // Fill LUT with alternating 10 const int init_size = 1 << 4; diff --git a/gowin/constids.inc b/gowin/constids.inc index 89a91164..8bc5efdd 100644 --- a/gowin/constids.inc +++ b/gowin/constids.inc @@ -393,6 +393,7 @@ X(FF_TYPE) X(INPUT_USED) X(OUTPUT_USED) X(ENABLE_USED) +X(BEL) // ports X(EN) diff --git a/gowin/main.cc b/gowin/main.cc index a5f99247..ac0de3ed 100644 --- a/gowin/main.cc +++ b/gowin/main.cc @@ -65,13 +65,13 @@ std::unique_ptr GowinCommandHandler::createContext(std::unordered_map(); - // std::ifstream in(filename); - // if (!in) - // log_error("Failed to open input PDC file %s.\n", filename.c_str()); - // ctx->read_pdc(in); - // } + if (vm.count("cst")) { + std::string filename = vm["cst"].as(); + std::ifstream in(filename); + if (!in) + log_error("Failed to open input CST file %s.\n", filename.c_str()); + ctx->read_cst(in); + } } int main(int argc, char *argv[]) diff --git a/gowin/pack.cc b/gowin/pack.cc index 4c880ee0..eb531108 100644 --- a/gowin/pack.cc +++ b/gowin/pack.cc @@ -250,11 +250,11 @@ static void pack_io(Context *ctx) create_generic_cell(ctx, id_IOB, ci->name.str(ctx) + "$iob"); gwio_to_iob(ctx, ci, ice_cell.get(), packed_cells); new_cells.push_back(std::move(ice_cell)); - iob = new_cells.back().get(); + auto gwiob = new_cells.back().get(); packed_cells.insert(ci->name); if (iob != nullptr) - std::copy(ci->attrs.begin(), ci->attrs.end(), std::inserter(iob->attrs, iob->attrs.begin())); + std::copy(iob->attrs.begin(), iob->attrs.end(), std::inserter(gwiob->attrs, gwiob->attrs.begin())); } } for (auto pcell : packed_cells) {