From e4b044da52ce7d8fed2e461bec09c86cb293566d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Jul 2018 19:39:44 -0700 Subject: [PATCH 01/11] Fix tns --- common/place_common.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/common/place_common.cc b/common/place_common.cc index 5673c847..b7ea84f8 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -72,6 +72,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type wirelength = wirelen_t((ymax - ymin) + (xmax - xmin)); } + tns = ctx->getDelayNS(tns); return wirelength; } From a82f6f410595de26e82eaf4818e41036f0bc2f9c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 30 Jul 2018 19:19:30 -0700 Subject: [PATCH 02/11] Modify predictDelay signature --- common/nextpnr.cc | 2 +- common/place_common.cc | 8 +++----- ecp5/arch.cc | 8 ++++++-- ecp5/arch.h | 2 +- generic/arch.cc | 12 +++++++----- generic/arch.h | 2 +- ice40/arch.cc | 21 +++++++++++++-------- ice40/arch.h | 2 +- 8 files changed, 33 insertions(+), 24 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 5b0a45ed..4a97bd93 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -111,7 +111,7 @@ delay_t Context::getNetinfoRouteDelay(NetInfo *net_info, int user_idx) const if (cursor == src_wire) return delay + getWireDelay(src_wire).maxDelay(); - return predictDelay(src_wire, dst_wire); + return predictDelay(net_info, net_info->users[user_idx]); } static uint32_t xorshift32(uint32_t x) diff --git a/common/place_common.cc b/common/place_common.cc index b7ea84f8..3c19a733 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -37,10 +37,9 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type return 0; driver_gb = ctx->getBelGlobalBuf(driver_cell->bel); driver_loc = ctx->getBelLocation(driver_cell->bel); - WireId drv_wire = ctx->getBelPinWire(driver_cell->bel, ctx->portPinFromId(net->driver.port)); if (driver_gb) return 0; - float worst_slack = 1000; + delay_t worst_slack = std::numeric_limits::max(); int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y; for (auto load : net->users) { if (load.cell == nullptr) @@ -49,9 +48,8 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type if (load_cell->bel == BelId()) continue; if (ctx->timing_driven && type == MetricType::COST) { - WireId user_wire = ctx->getBelPinWire(load_cell->bel, ctx->portPinFromId(load.port)); - delay_t raw_wl = ctx->estimateDelay(drv_wire, user_wire); - float slack = ctx->getDelayNS(load.budget) - ctx->getDelayNS(raw_wl); + delay_t net_delay = ctx->predictDelay(net, load); + auto slack = load.budget - net_delay; if (slack < 0) tns += slack; worst_slack = std::min(slack, worst_slack); diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 88b5e4d4..23105df2 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -413,9 +413,13 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y)); } -delay_t Arch::predictDelay(WireId src, WireId dst) const +delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const; { - return 200 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y)); + const auto& driver = net_info->driver; + auto driver_loc = getBelLocation(driver.cell->bel); + auto sink_loc = getBelLocation(sink.cell->bel); + + return 200 * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y)); } // ----------------------------------------------------------------------- diff --git a/ecp5/arch.h b/ecp5/arch.h index 13f2db1f..400d6e55 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -776,7 +776,7 @@ struct Arch : BaseCtx // ------------------------------------------------- delay_t estimateDelay(WireId src, WireId dst) const; - delay_t predictDelay(WireId src, WireId dst) const; + delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const; delay_t getDelayEpsilon() const { return 20; } delay_t getRipupDelayPenalty() const { return 200; } float getDelayNS(delay_t v) const { return v * 0.001; } diff --git a/generic/arch.cc b/generic/arch.cc index 8ef37716..4469a828 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -403,12 +403,14 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const return (dx + dy) * grid_distance_to_delay; } -delay_t Arch::predictDelay(WireId src, WireId dst) const +delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const; { - const WireInfo &s = wires.at(src); - const WireInfo &d = wires.at(dst); - int dx = abs(s.x - d.x); - int dy = abs(s.y - d.y); + const auto& driver = net_info->driver; + auto driver_loc = getBelLocation(driver.cell->bel); + auto sink_loc = getBelLocation(sink.cell->bel); + + int dx = abs(driver_loc.x - driver_loc.x); + int dy = abs(sink_loc.y - sink_locy); return (dx + dy) * grid_distance_to_delay; } diff --git a/generic/arch.h b/generic/arch.h index 60220fbe..f02649f6 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -194,7 +194,7 @@ struct Arch : BaseCtx const std::vector &getGroupGroups(GroupId group) const; delay_t estimateDelay(WireId src, WireId dst) const; - delay_t predictDelay(WireId src, WireId dst) const; + delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const; delay_t getDelayEpsilon() const { return 0.01; } delay_t getRipupDelayPenalty() const { return 1.0; } float getDelayNS(delay_t v) const { return v; } diff --git a/ice40/arch.cc b/ice40/arch.cc index 91c20b42..107bf56a 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -582,17 +582,19 @@ delay_t Arch::estimateDelay(WireId src, WireId dst) const return xscale * abs(xd) + yscale * abs(yd) + offset; } -delay_t Arch::predictDelay(WireId src, WireId dst) const +delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const { - NPNR_ASSERT(src != WireId()); - int x1 = chip_info->wire_data[src.index].x; - int y1 = chip_info->wire_data[src.index].y; + const auto& driver = net_info->driver; + auto driver_loc = getBelLocation(driver.cell->bel); + auto sink_loc = getBelLocation(sink.cell->bel); - NPNR_ASSERT(dst != WireId()); - int x2 = chip_info->wire_data[dst.index].x; - int y2 = chip_info->wire_data[dst.index].y; + if (driver.port == id_cout) { + if (driver_loc.y == sink_loc.y) + return 0; + return 250; + } - int xd = x2 - x1, yd = y2 - y1; + int xd = sink_loc.x - driver_loc.x, yd = sink_loc.y - driver_loc.y; int xscale = 120, yscale = 120, offset = 0; // if (chip_info->wire_data[src.index].type == WIRE_TYPE_SP4_VERT) { @@ -600,6 +602,9 @@ delay_t Arch::predictDelay(WireId src, WireId dst) const // offset = 500; // } + if (driver.port == id_o) offset += 330; + if (sink.port == id_i0 || sink.port == id_i1 || sink.port == id_i2 || sink.port == id_i3) offset += 260; + return xscale * abs(xd) + yscale * abs(yd) + offset; } diff --git a/ice40/arch.h b/ice40/arch.h index 1725d181..57089ed7 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -684,7 +684,7 @@ struct Arch : BaseCtx // ------------------------------------------------- delay_t estimateDelay(WireId src, WireId dst) const; - delay_t predictDelay(WireId src, WireId dst) const; + delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const; delay_t getDelayEpsilon() const { return 20; } delay_t getRipupDelayPenalty() const { return 200; } float getDelayNS(delay_t v) const { return v * 0.001; } From 32ff0059feeb2dd8187393c63dae7db59a2e5b43 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 31 Jul 2018 11:55:25 +0200 Subject: [PATCH 03/11] Add binary search to getBelPinWire() and getBelPinType() Signed-off-by: Clifford Wolf --- ice40/arch.cc | 43 ++++++++++++++++++++++++++++++++++++------- ice40/arch.h | 2 +- ice40/chipdb.py | 14 ++++++-------- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/ice40/arch.cc b/ice40/arch.cc index 8162098c..fd68e972 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -311,9 +311,23 @@ PortType Arch::getBelPinType(BelId bel, PortPin pin) const int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); - for (int i = 0; i < num_bel_wires; i++) - if (bel_wires[i].port == pin) - return PortType(bel_wires[i].type); + if (num_bel_wires < 7) { + for (int i = 0; i < num_bel_wires; i++) { + if (bel_wires[i].port == pin) + return PortType(bel_wires[i].type); + } + } else { + int b = 0, e = num_bel_wires-1; + while (b <= e) { + int i = (b+e) / 2; + if (bel_wires[i].port == pin) + return PortType(bel_wires[i].type); + if (bel_wires[i].port > pin) + e = i-1; + else + b = i+1; + } + } return PORT_INOUT; } @@ -327,10 +341,25 @@ WireId Arch::getBelPinWire(BelId bel, PortPin pin) const int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires; const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get(); - for (int i = 0; i < num_bel_wires; i++) { - if (bel_wires[i].port == pin) { - ret.index = bel_wires[i].wire_index; - break; + if (num_bel_wires < 7) { + for (int i = 0; i < num_bel_wires; i++) { + if (bel_wires[i].port == pin) { + ret.index = bel_wires[i].wire_index; + break; + } + } + } else { + int b = 0, e = num_bel_wires-1; + while (b <= e) { + int i = (b+e) / 2; + if (bel_wires[i].port == pin) { + ret.index = bel_wires[i].wire_index; + break; + } + if (bel_wires[i].port > pin) + e = i-1; + else + b = i+1; } } diff --git a/ice40/arch.h b/ice40/arch.h index 8c6a3d93..1d68ec4a 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -44,9 +44,9 @@ template struct RelPtr }; NPNR_PACKED_STRUCT(struct BelWirePOD { - int32_t wire_index; PortPin port; int32_t type; + int32_t wire_index; }); NPNR_PACKED_STRUCT(struct BelInfoPOD { diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 3ef58185..32d3485f 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -492,13 +492,13 @@ def add_bel_input(bel, wire, port): if wire not in wire_belports: wire_belports[wire] = set() wire_belports[wire].add((bel, port)) - bel_wires[bel].append((wire, port, 0)) + bel_wires[bel].append((portpins[port], 0, wire)) def add_bel_output(bel, wire, port): if wire not in wire_belports: wire_belports[wire] = set() wire_belports[wire].add((bel, port)) - bel_wires[bel].append((wire, port, 1)) + bel_wires[bel].append((portpins[port], 1, wire)) def add_bel_lc(x, y, z): bel = len(bel_name) @@ -759,14 +759,12 @@ bba.post('NEXTPNR_NAMESPACE_END') bba.push("chipdb_blob_%s" % dev_name) bba.r("chip_info_%s" % dev_name, "chip_info") -index = 0 for bel in range(len(bel_name)): bba.l("bel_wires_%d" % bel, "BelWirePOD") - for i in range(len(bel_wires[bel])): - bba.u32(bel_wires[bel][i][0], "wire_index") - bba.u32(portpins[bel_wires[bel][i][1]], "port") - bba.u32(bel_wires[bel][i][2], "type") - index += 1 + for data in sorted(bel_wires[bel]): + bba.u32(data[0], "port") + bba.u32(data[1], "type") + bba.u32(data[2], "wire_index") bba.l("bel_data_%s" % dev_name, "BelInfoPOD") for bel in range(len(bel_name)): From e3a403fa2990602941ce756726488820182aff26 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 31 Jul 2018 14:36:17 +0200 Subject: [PATCH 04/11] ecp5: Disable Pip list in GUI for now Signed-off-by: David Shah --- gui/treemodel.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/treemodel.cc b/gui/treemodel.cc index d79e38de..d42dc401 100644 --- a/gui/treemodel.cc +++ b/gui/treemodel.cc @@ -141,6 +141,7 @@ void ContextTreeModel::loadData(Context *ctx) QMap pip_items; // Add pips to tree +#ifndef ARCH_ECP5 for (auto pip : ctx->getPips()) { auto id = ctx->getPipName(pip); QStringList items = QString(id.c_str(ctx)).split("/"); @@ -164,6 +165,7 @@ void ContextTreeModel::loadData(Context *ctx) parent = pip_items[name]; } } +#endif pip_root->sort(); nets_root = new ContextTreeItem("Nets"); @@ -341,4 +343,4 @@ QList ContextTreeModel::search(QString text) } return list; } -NEXTPNR_NAMESPACE_END \ No newline at end of file +NEXTPNR_NAMESPACE_END From f3127f7dfd33469d29010b611aafb715a33b3be2 Mon Sep 17 00:00:00 2001 From: David Shah Date: Tue, 31 Jul 2018 14:39:37 +0200 Subject: [PATCH 05/11] ecp5: Add Bel graphics Signed-off-by: David Shah --- ecp5/arch.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++---- ecp5/archdefs.h | 13 +++++++---- ecp5/gfx.h | 35 ++++++++++++++++++++++++++++++ ecp5/main.cc | 10 +++++---- 4 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 ecp5/gfx.h diff --git a/ecp5/arch.cc b/ecp5/arch.cc index c8617190..7f7079bf 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -21,6 +21,7 @@ #include #include #include +#include "gfx.h" #include "log.h" #include "nextpnr.h" #include "placer1.h" @@ -421,16 +422,64 @@ bool Arch::route() { return router1(getCtx()); } // ----------------------------------------------------------------------- -std::vector Arch::getDecalGraphics(DecalId decalId) const +std::vector Arch::getDecalGraphics(DecalId decal) const { std::vector ret; - // FIXME + + if (decal.type == DecalId::TYPE_FRAME) { + /* nothing */ + } + + if (decal.type == DecalId::TYPE_BEL) { + BelId bel; + bel.index = decal.z; + bel.location = decal.location; + int z = locInfo(bel)->bel_data[bel.index].z; + auto bel_type = getBelType(bel); + + if (bel_type == TYPE_TRELLIS_SLICE) { + GraphicElement el; + el.type = GraphicElement::TYPE_BOX; + el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; + el.x1 = bel.location.x + logic_cell_x1; + el.x2 = bel.location.x + logic_cell_x2; + el.y1 = bel.location.y + logic_cell_y1 + (z)*logic_cell_pitch; + el.y2 = bel.location.y + logic_cell_y2 + (z)*logic_cell_pitch; + ret.push_back(el); + } + + if (bel_type == TYPE_TRELLIS_IO) { + GraphicElement el; + el.type = GraphicElement::TYPE_BOX; + el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE; + el.x1 = bel.location.x + logic_cell_x1; + el.x2 = bel.location.x + logic_cell_x2; + el.y1 = bel.location.y + logic_cell_y1 + (2 * z) * logic_cell_pitch; + el.y2 = bel.location.y + logic_cell_y2 + (2 * z + 1) * logic_cell_pitch; + ret.push_back(el); + } + } + return ret; } -DecalXY Arch::getFrameDecal() const { return {}; } +DecalXY Arch::getFrameDecal() const +{ + DecalXY decalxy; + decalxy.decal.type = DecalId::TYPE_FRAME; + decalxy.decal.active = true; + return decalxy; +} -DecalXY Arch::getBelDecal(BelId bel) const { return {}; } +DecalXY Arch::getBelDecal(BelId bel) const +{ + DecalXY decalxy; + decalxy.decal.type = DecalId::TYPE_BEL; + decalxy.decal.location = bel.location; + decalxy.decal.z = bel.index; + decalxy.decal.active = bel_to_cell.count(bel) && (bel_to_cell.at(bel) != IdString()); + return decalxy; +} DecalXY Arch::getWireDecal(WireId wire) const { return {}; } diff --git a/ecp5/archdefs.h b/ecp5/archdefs.h index 40442e1b..829db683 100644 --- a/ecp5/archdefs.h +++ b/ecp5/archdefs.h @@ -120,17 +120,21 @@ struct GroupId struct DecalId { - char type = 0; // Bel/Wire/Pip/Frame (b/w/p/f) + enum + { + TYPE_FRAME, + TYPE_BEL + } type; Location location; uint32_t z = 0; - + bool active = false; bool operator==(const DecalId &other) const { - return type == other.type && location == other.location && z == other.z; + return type == other.type && location == other.location && z == other.z && active == other.active; } bool operator!=(const DecalId &other) const { - return type != other.type || location != other.location || z != other.z; + return type != other.type || location != other.location || z != other.z || active != other.active; } }; @@ -200,6 +204,7 @@ template <> struct hash boost::hash_combine(seed, hash()(decal.type)); boost::hash_combine(seed, hash()(decal.location)); boost::hash_combine(seed, hash()(decal.z)); + boost::hash_combine(seed, hash()(decal.active)); return seed; } }; diff --git a/ecp5/gfx.h b/ecp5/gfx.h new file mode 100644 index 00000000..0290d2f6 --- /dev/null +++ b/ecp5/gfx.h @@ -0,0 +1,35 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * 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. + * + */ + +#ifndef ECP5_GFX_H +#define ECP5_GFX_H + +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +const float logic_cell_x1 = 0.76; +const float logic_cell_x2 = 0.95; +const float logic_cell_y1 = 0.05; +const float logic_cell_y2 = 0.15; +const float logic_cell_pitch = 0.125; + +NEXTPNR_NAMESPACE_END + +#endif diff --git a/ecp5/main.cc b/ecp5/main.cc index f2db74d7..90096855 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -100,16 +100,18 @@ int main(int argc, char *argv[]) } if (vm.count("help") || argc == 1) { - std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git " - "sha1 " GIT_COMMIT_HASH_STR ")\n"; + std::cout << boost::filesystem::basename(argv[0]) + << " -- Next Generation Place and Route (git " + "sha1 " GIT_COMMIT_HASH_STR ")\n"; std::cout << "\n"; std::cout << options << "\n"; return argc != 1; } if (vm.count("version")) { - std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git " - "sha1 " GIT_COMMIT_HASH_STR ")\n"; + std::cout << boost::filesystem::basename(argv[0]) + << " -- Next Generation Place and Route (git " + "sha1 " GIT_COMMIT_HASH_STR ")\n"; return 1; } From 38d7cc3b8502b494f2d28a6de16eb634f23b7777 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 31 Jul 2018 13:41:18 +0000 Subject: [PATCH 06/11] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 51141b09..c22579ba 100644 --- a/README.md +++ b/README.md @@ -162,3 +162,8 @@ Links and references - [SymbiFlow](https://github.com/SymbiFlow/symbiflow-arch-defs) - [Gaffe](https://github.com/kc8apf/gaffe) - [KinglerPAR](https://github.com/rqou/KinglerPAR) + +> SymbiFlow is working with the Verilog to Routing tool to extend the current +research tool to support real architectures. VtR is strongly focused on +architecture research but having support for real architectures might enable +research nextpnr zu providing documentation and explanation. From 2652485a0118a2dff46b6547683c8b988ee3b619 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 31 Jul 2018 16:43:19 +0200 Subject: [PATCH 07/11] Use icestorm timing information Signed-off-by: Clifford Wolf --- ice40/chipdb.py | 81 +++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/ice40/chipdb.py b/ice40/chipdb.py index 32d3485f..97ccbe48 100644 --- a/ice40/chipdb.py +++ b/ice40/chipdb.py @@ -214,56 +214,71 @@ def wire_type(name): assert 0 return wt -def pipdelay(src, dst, db): +def pipdelay(src_idx, dst_idx, db): if db is None: return 0 - src = wire_names_r[src] - dst = wire_names_r[dst] + src = wire_names_r[src_idx] + dst = wire_names_r[dst_idx] src_type = wire_type(src[2]) dst_type = wire_type(dst[2]) + if dst[2].startswith("sp4_") or dst[2].startswith("span4_"): + if src[2].startswith("sp12_") or src[2].startswith("span12_"): + return db["Sp12to4.I.O"] + + if src[2].startswith("span4_"): + return db["IoSpan4Mux.I.O"] + + if dst[2].startswith("sp4_h_"): + return db["Span4Mux_h4.I.O"] + else: + return db["Span4Mux_v4.I.O"] + + if dst[2].startswith("sp12_") or dst[2].startswith("span12_"): + if dst[2].startswith("sp12_h_"): + return db["Span12Mux_h12.I.O"] + else: + return db["Span12Mux_v12.I.O"] + + if dst[2] in ("fabout", "clk"): + return 0 # FIXME? + + if src[2].startswith("glb_netwk_") and dst[2].startswith("glb2local_"): + return 0 # FIXME? + + if dst[2] == "carry_in_mux": + return db["ICE_CARRY_IN_MUX.carryinitin.carryinitout"] + + if dst[2] in ("lutff_global/clk", "io_global/inclk", "io_global/outclk", "ram/RCLK", "ram/WCLK"): + return db["ClkMux.I.O"] + + if dst[2] in ("lutff_global/s_r", "io_global/latch", "ram/RE", "ram/WE"): + return db["SRMux.I.O"] + + if dst[2] in ("lutff_global/cen", "io_global/cen", "ram/RCLKE", "ram/WCLKE"): + return db["CEMux.I.O"] + if dst[2].startswith("local_"): return db["LocalMux.I.O"] - if src_type == "LOCAL" and dst_type == "LOCAL": - return 250 + if src[2].startswith("local_") and dst[2] in ("io_0/D_OUT_0", "io_0/D_OUT_1", "io_0/OUT_ENB", "io_1/D_OUT_0", "io_1/D_OUT_1", "io_1/OUT_ENB"): + return db["IoInMux.I.O"] - if src_type == "GLOBAL" and dst_type == "LOCAL": - return 400 + if re.match(r"lutff_\d+/in_\d+", dst[2]): + return db["InMux.I.O"] - # Local -> Span + if re.match(r"ram/(MASK|RADDR|WADDR|WDATA)_", dst[2]): + return db["InMux.I.O"] - if src_type == "LOCAL" and dst_type in ("SP4_HORZ", "SP4_VERT"): - return 350 - - if src_type == "LOCAL" and dst_type in ("SP12_HORZ", "SP12_VERT"): - return 500 - - # Span -> Local - - if src_type in ("SP4_HORZ", "SP4_VERT", "SP12_HORZ", "SP12_VERT") and dst_type == "LOCAL": - return 300 - - # Span -> Span - - if src_type in ("SP12_HORZ", "SP12_VERT") and dst_type in ("SP12_HORZ", "SP12_VERT"): - return 450 - - if src_type in ("SP4_HORZ", "SP4_VERT") and dst_type in ("SP4_HORZ", "SP4_VERT"): - return 300 - - if src_type in ("SP12_HORZ", "SP12_VERT") and dst_type in ("SP4_HORZ", "SP4_VERT"): - return 380 - - # print(src, dst, src_type, dst_type, file=sys.stderr) + print(src, dst, src_idx, dst_idx, src_type, dst_type, file=sys.stderr) assert 0 -def wiredelay(wire, db): +def wiredelay(wire_idx, db): if db is None: return 0 - wire = wire_names_r[wire] + wire = wire_names_r[wire_idx] wtype = wire_type(wire[2]) # FIXME From 41726087b7577f2ce46acb2456f254a063cbbf52 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 31 Jul 2018 17:01:38 +0200 Subject: [PATCH 08/11] getChipName() should be const Signed-off-by: Clifford Wolf --- ecp5/arch.cc | 3 +-- ecp5/arch.h | 2 +- generic/arch.h | 2 +- ice40/arch.cc | 2 +- ice40/arch.h | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 7f7079bf..2b40e79a 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -141,9 +141,8 @@ Arch::Arch(ArchArgs args) : args(args) // ----------------------------------------------------------------------- -std::string Arch::getChipName() +std::string Arch::getChipName() const { - if (args.type == ArchArgs::LFE5U_25F) { return "LFE5U-25F"; } else if (args.type == ArchArgs::LFE5U_45F) { diff --git a/ecp5/arch.h b/ecp5/arch.h index 7d183e11..2421428f 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -399,7 +399,7 @@ struct Arch : BaseCtx ArchArgs args; Arch(ArchArgs args); - std::string getChipName(); + std::string getChipName() const; IdString archId() const { return id("ecp5"); } IdString archArgsToId(ArchArgs args) const; diff --git a/generic/arch.h b/generic/arch.h index ed069d4d..9a0da75b 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -122,7 +122,7 @@ struct Arch : BaseCtx Arch(ArchArgs args); - std::string getChipName() { return chipName; } + std::string getChipName() const { return chipName; } IdString archId() const { return id("generic"); } IdString archArgsToId(ArchArgs args) const { return id("none"); } diff --git a/ice40/arch.cc b/ice40/arch.cc index fd68e972..f3004155 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -204,7 +204,7 @@ Arch::Arch(ArchArgs args) : args(args) // ----------------------------------------------------------------------- -std::string Arch::getChipName() +std::string Arch::getChipName() const { #ifdef ICE40_HX1K_ONLY if (args.type == ArchArgs::HX1K) { diff --git a/ice40/arch.h b/ice40/arch.h index 1d68ec4a..7efa733c 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -365,7 +365,7 @@ struct Arch : BaseCtx ArchArgs args; Arch(ArchArgs args); - std::string getChipName(); + std::string getChipName() const; IdString archId() const { return id("ice40"); } IdString archArgsToId(ArchArgs args) const; From b55ccc12f0b2ac964cb4ff72b191fee2c4e1bdad Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 31 Jul 2018 17:40:19 +0200 Subject: [PATCH 09/11] add graphics toolbar to all targets --- gui/ecp5/mainwindow.cc | 2 ++ gui/generic/mainwindow.cc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index 1168a55c..4b1c7e3b 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -40,6 +40,8 @@ void MainWindow::createMenu() { QMenu *menu_Custom = new QMenu("&Generic", menuBar); menuBar->addAction(menu_Custom->menuAction()); + + createGraphicsBar(); } void MainWindow::new_proj() {} diff --git a/gui/generic/mainwindow.cc b/gui/generic/mainwindow.cc index 88e291e6..1efc73bb 100644 --- a/gui/generic/mainwindow.cc +++ b/gui/generic/mainwindow.cc @@ -40,6 +40,8 @@ void MainWindow::createMenu() { QMenu *menu_Custom = new QMenu("&Generic", menuBar); menuBar->addAction(menu_Custom->menuAction()); + + createGraphicsBar(); } void MainWindow::new_proj() {} From 2a91aea0a6d17f6d00edb391cc543ec9409e96e5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Jul 2018 14:42:01 -0700 Subject: [PATCH 10/11] Fix merge issues --- common/timing.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/timing.cc b/common/timing.cc index b1a5619d..f33a2ef1 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -57,7 +57,7 @@ static delay_t follow_user_port(Context *ctx, PortRef &user, int path_length, de if (is_path) { NetInfo *net = port.second.net; if (net) { - delay_t path_budget = follow_net(ctx, net, path_length, slack - comb_delay, update, min_slack, + delay_t path_budget = follow_net(ctx, net, path_length, slack - comb_delay.maxDelay(), update, min_slack, current_path, crit_path); value = std::min(value, path_budget); } @@ -110,7 +110,7 @@ static delay_t walk_paths(Context *ctx, bool update, PortRefList *crit_path) IdString clock_domain = ctx->getPortClock(cell.second.get(), port.first); if (clock_domain != IdString()) { delay_t slack = default_slack; // TODO: clock constraints - delay_t clkToQ; + DelayInfo clkToQ; if (ctx->getCellDelay(cell.second.get(), clock_domain, port.first, clkToQ)) slack -= clkToQ.maxDelay(); if (port.second.net) @@ -197,10 +197,10 @@ delay_t timing_analysis(Context *ctx, bool print_fmax, bool print_path) ++i; auto &driver = net->driver; auto driver_cell = driver.cell; - delay_t comb_delay; + DelayInfo comb_delay; ctx->getCellDelay(sink_cell, last_port, driver.port, comb_delay); - total += comb_delay; - log_info("%4d %4d Source %s.%s\n", comb_delay, total, driver_cell->name.c_str(ctx), + total += comb_delay.maxDelay(); + log_info("%4d %4d Source %s.%s\n", comb_delay.maxDelay(), total, driver_cell->name.c_str(ctx), driver.port.c_str(ctx)); delay_t net_delay = ctx->getNetinfoRouteDelay(net, i); total += net_delay; From 51956eb9617300a892d78619234f0f9f36c2cfb4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 31 Jul 2018 16:23:35 -0700 Subject: [PATCH 11/11] Fix tns computation --- common/place_common.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/place_common.cc b/common/place_common.cc index 3c19a733..31f15721 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -39,6 +39,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type driver_loc = ctx->getBelLocation(driver_cell->bel); if (driver_gb) return 0; + delay_t negative_slack = 0; delay_t worst_slack = std::numeric_limits::max(); int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y; for (auto load : net->users) { @@ -51,7 +52,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type delay_t net_delay = ctx->predictDelay(net, load); auto slack = load.budget - net_delay; if (slack < 0) - tns += slack; + negative_slack += slack; worst_slack = std::min(slack, worst_slack); } @@ -70,7 +71,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type wirelength = wirelen_t((ymax - ymin) + (xmax - xmin)); } - tns = ctx->getDelayNS(tns); + tns += ctx->getDelayNS(negative_slack); return wirelength; }