Merge branch 'redist_slack' of gitlab.com:SymbioticEDA/nextpnr into redist_slack
This commit is contained in:
commit
5d58d6ad1b
@ -162,3 +162,8 @@ Links and references
|
|||||||
- [SymbiFlow](https://github.com/SymbiFlow/symbiflow-arch-defs)
|
- [SymbiFlow](https://github.com/SymbiFlow/symbiflow-arch-defs)
|
||||||
- [Gaffe](https://github.com/kc8apf/gaffe)
|
- [Gaffe](https://github.com/kc8apf/gaffe)
|
||||||
- [KinglerPAR](https://github.com/rqou/KinglerPAR)
|
- [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.
|
||||||
|
@ -39,6 +39,8 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type
|
|||||||
driver_loc = ctx->getBelLocation(driver_cell->bel);
|
driver_loc = ctx->getBelLocation(driver_cell->bel);
|
||||||
if (driver_gb)
|
if (driver_gb)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
delay_t negative_slack = 0;
|
||||||
delay_t worst_slack = std::numeric_limits<delay_t>::max();
|
delay_t worst_slack = std::numeric_limits<delay_t>::max();
|
||||||
int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y;
|
int xmin = driver_loc.x, xmax = driver_loc.x, ymin = driver_loc.y, ymax = driver_loc.y;
|
||||||
for (auto load : net->users) {
|
for (auto load : net->users) {
|
||||||
@ -51,7 +53,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type
|
|||||||
delay_t net_delay = ctx->predictDelay(net, load);
|
delay_t net_delay = ctx->predictDelay(net, load);
|
||||||
auto slack = load.budget - net_delay;
|
auto slack = load.budget - net_delay;
|
||||||
if (slack < 0)
|
if (slack < 0)
|
||||||
tns += slack;
|
negative_slack += slack;
|
||||||
worst_slack = std::min(slack, worst_slack);
|
worst_slack = std::min(slack, worst_slack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ wirelen_t get_net_metric(const Context *ctx, const NetInfo *net, MetricType type
|
|||||||
wirelength = wirelen_t((ymax - ymin) + (xmax - xmin));
|
wirelength = wirelen_t((ymax - ymin) + (xmax - xmin));
|
||||||
}
|
}
|
||||||
|
|
||||||
tns = ctx->getDelayNS(tns);
|
tns += ctx->getDelayNS(negative_slack);
|
||||||
return wirelength;
|
return wirelength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
ecp5/arch.cc
60
ecp5/arch.cc
@ -21,6 +21,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "gfx.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
#include "placer1.h"
|
#include "placer1.h"
|
||||||
@ -140,9 +141,8 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
std::string Arch::getChipName()
|
std::string Arch::getChipName() const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (args.type == ArchArgs::LFE5U_25F) {
|
if (args.type == ArchArgs::LFE5U_25F) {
|
||||||
return "LFE5U-25F";
|
return "LFE5U-25F";
|
||||||
} else if (args.type == ArchArgs::LFE5U_45F) {
|
} else if (args.type == ArchArgs::LFE5U_45F) {
|
||||||
@ -432,16 +432,64 @@ bool Arch::route() { return router1(getCtx()); }
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decalId) const
|
std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
||||||
{
|
{
|
||||||
std::vector<GraphicElement> ret;
|
std::vector<GraphicElement> 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;
|
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 {}; }
|
DecalXY Arch::getWireDecal(WireId wire) const { return {}; }
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ struct Arch : BaseCtx
|
|||||||
ArchArgs args;
|
ArchArgs args;
|
||||||
Arch(ArchArgs args);
|
Arch(ArchArgs args);
|
||||||
|
|
||||||
std::string getChipName();
|
std::string getChipName() const;
|
||||||
|
|
||||||
IdString archId() const { return id("ecp5"); }
|
IdString archId() const { return id("ecp5"); }
|
||||||
IdString archArgsToId(ArchArgs args) const;
|
IdString archArgsToId(ArchArgs args) const;
|
||||||
|
@ -120,17 +120,21 @@ struct GroupId
|
|||||||
|
|
||||||
struct DecalId
|
struct DecalId
|
||||||
{
|
{
|
||||||
char type = 0; // Bel/Wire/Pip/Frame (b/w/p/f)
|
enum
|
||||||
|
{
|
||||||
|
TYPE_FRAME,
|
||||||
|
TYPE_BEL
|
||||||
|
} type;
|
||||||
Location location;
|
Location location;
|
||||||
uint32_t z = 0;
|
uint32_t z = 0;
|
||||||
|
bool active = false;
|
||||||
bool operator==(const DecalId &other) const
|
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
|
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<NEXTPNR_NAMESPACE_PREFIX DecalId>
|
|||||||
boost::hash_combine(seed, hash<int>()(decal.type));
|
boost::hash_combine(seed, hash<int>()(decal.type));
|
||||||
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX Location>()(decal.location));
|
boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX Location>()(decal.location));
|
||||||
boost::hash_combine(seed, hash<int>()(decal.z));
|
boost::hash_combine(seed, hash<int>()(decal.z));
|
||||||
|
boost::hash_combine(seed, hash<bool>()(decal.active));
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
35
ecp5/gfx.h
Normal file
35
ecp5/gfx.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* nextpnr -- Next Generation Place and Route
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* 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
|
10
ecp5/main.cc
10
ecp5/main.cc
@ -100,16 +100,18 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("help") || argc == 1) {
|
if (vm.count("help") || argc == 1) {
|
||||||
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
std::cout << boost::filesystem::basename(argv[0])
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
<< " -- Next Generation Place and Route (git "
|
||||||
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
std::cout << options << "\n";
|
std::cout << options << "\n";
|
||||||
return argc != 1;
|
return argc != 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count("version")) {
|
if (vm.count("version")) {
|
||||||
std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git "
|
std::cout << boost::filesystem::basename(argv[0])
|
||||||
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
<< " -- Next Generation Place and Route (git "
|
||||||
|
"sha1 " GIT_COMMIT_HASH_STR ")\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ struct Arch : BaseCtx
|
|||||||
|
|
||||||
Arch(ArchArgs args);
|
Arch(ArchArgs args);
|
||||||
|
|
||||||
std::string getChipName() { return chipName; }
|
std::string getChipName() const { return chipName; }
|
||||||
|
|
||||||
IdString archId() const { return id("generic"); }
|
IdString archId() const { return id("generic"); }
|
||||||
IdString archArgsToId(ArchArgs args) const { return id("none"); }
|
IdString archArgsToId(ArchArgs args) const { return id("none"); }
|
||||||
|
@ -40,6 +40,8 @@ void MainWindow::createMenu()
|
|||||||
{
|
{
|
||||||
QMenu *menu_Custom = new QMenu("&Generic", menuBar);
|
QMenu *menu_Custom = new QMenu("&Generic", menuBar);
|
||||||
menuBar->addAction(menu_Custom->menuAction());
|
menuBar->addAction(menu_Custom->menuAction());
|
||||||
|
|
||||||
|
createGraphicsBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::new_proj() {}
|
void MainWindow::new_proj() {}
|
||||||
|
@ -40,6 +40,8 @@ void MainWindow::createMenu()
|
|||||||
{
|
{
|
||||||
QMenu *menu_Custom = new QMenu("&Generic", menuBar);
|
QMenu *menu_Custom = new QMenu("&Generic", menuBar);
|
||||||
menuBar->addAction(menu_Custom->menuAction());
|
menuBar->addAction(menu_Custom->menuAction());
|
||||||
|
|
||||||
|
createGraphicsBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::new_proj() {}
|
void MainWindow::new_proj() {}
|
||||||
|
@ -141,6 +141,7 @@ void ContextTreeModel::loadData(Context *ctx)
|
|||||||
QMap<QString, ContextTreeItem *> pip_items;
|
QMap<QString, ContextTreeItem *> pip_items;
|
||||||
|
|
||||||
// Add pips to tree
|
// Add pips to tree
|
||||||
|
#ifndef ARCH_ECP5
|
||||||
for (auto pip : ctx->getPips()) {
|
for (auto pip : ctx->getPips()) {
|
||||||
auto id = ctx->getPipName(pip);
|
auto id = ctx->getPipName(pip);
|
||||||
QStringList items = QString(id.c_str(ctx)).split("/");
|
QStringList items = QString(id.c_str(ctx)).split("/");
|
||||||
@ -164,6 +165,7 @@ void ContextTreeModel::loadData(Context *ctx)
|
|||||||
parent = pip_items[name];
|
parent = pip_items[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
pip_root->sort();
|
pip_root->sort();
|
||||||
|
|
||||||
nets_root = new ContextTreeItem("Nets");
|
nets_root = new ContextTreeItem("Nets");
|
||||||
@ -341,4 +343,4 @@ QList<QModelIndex> ContextTreeModel::search(QString text)
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -204,7 +204,7 @@ Arch::Arch(ArchArgs args) : args(args)
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
std::string Arch::getChipName()
|
std::string Arch::getChipName() const
|
||||||
{
|
{
|
||||||
#ifdef ICE40_HX1K_ONLY
|
#ifdef ICE40_HX1K_ONLY
|
||||||
if (args.type == ArchArgs::HX1K) {
|
if (args.type == ArchArgs::HX1K) {
|
||||||
@ -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;
|
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();
|
const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();
|
||||||
|
|
||||||
for (int i = 0; i < num_bel_wires; i++)
|
if (num_bel_wires < 7) {
|
||||||
if (bel_wires[i].port == pin)
|
for (int i = 0; i < num_bel_wires; i++) {
|
||||||
return PortType(bel_wires[i].type);
|
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;
|
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;
|
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();
|
const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();
|
||||||
|
|
||||||
for (int i = 0; i < num_bel_wires; i++) {
|
if (num_bel_wires < 7) {
|
||||||
if (bel_wires[i].port == pin) {
|
for (int i = 0; i < num_bel_wires; i++) {
|
||||||
ret.index = bel_wires[i].wire_index;
|
if (bel_wires[i].port == pin) {
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,6 +631,11 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
|
|||||||
int xd = sink_loc.x - driver_loc.x, yd = sink_loc.y - driver_loc.y;
|
int xd = sink_loc.x - driver_loc.x, yd = sink_loc.y - driver_loc.y;
|
||||||
int xscale = 120, yscale = 120, offset = 0;
|
int xscale = 120, yscale = 120, offset = 0;
|
||||||
|
|
||||||
|
// if (chip_info->wire_data[src.index].type == WIRE_TYPE_SP4_VERT) {
|
||||||
|
// yd = yd < -4 ? yd + 4 : (yd < 0 ? 0 : yd);
|
||||||
|
// offset = 500;
|
||||||
|
// }
|
||||||
|
|
||||||
if (driver.port == id_o) offset += 330;
|
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;
|
if (sink.port == id_i0 || sink.port == id_i1 || sink.port == id_i2 || sink.port == id_i3) offset += 260;
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@ template <typename T> struct RelPtr
|
|||||||
};
|
};
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct BelWirePOD {
|
NPNR_PACKED_STRUCT(struct BelWirePOD {
|
||||||
int32_t wire_index;
|
|
||||||
PortPin port;
|
PortPin port;
|
||||||
int32_t type;
|
int32_t type;
|
||||||
|
int32_t wire_index;
|
||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct BelInfoPOD {
|
NPNR_PACKED_STRUCT(struct BelInfoPOD {
|
||||||
@ -365,7 +365,7 @@ struct Arch : BaseCtx
|
|||||||
ArchArgs args;
|
ArchArgs args;
|
||||||
Arch(ArchArgs args);
|
Arch(ArchArgs args);
|
||||||
|
|
||||||
std::string getChipName();
|
std::string getChipName() const;
|
||||||
|
|
||||||
IdString archId() const { return id("ice40"); }
|
IdString archId() const { return id("ice40"); }
|
||||||
IdString archArgsToId(ArchArgs args) const;
|
IdString archArgsToId(ArchArgs args) const;
|
||||||
|
@ -214,56 +214,71 @@ def wire_type(name):
|
|||||||
assert 0
|
assert 0
|
||||||
return wt
|
return wt
|
||||||
|
|
||||||
def pipdelay(src, dst, db):
|
def pipdelay(src_idx, dst_idx, db):
|
||||||
if db is None:
|
if db is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
src = wire_names_r[src]
|
src = wire_names_r[src_idx]
|
||||||
dst = wire_names_r[dst]
|
dst = wire_names_r[dst_idx]
|
||||||
src_type = wire_type(src[2])
|
src_type = wire_type(src[2])
|
||||||
dst_type = wire_type(dst[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_"):
|
if dst[2].startswith("local_"):
|
||||||
return db["LocalMux.I.O"]
|
return db["LocalMux.I.O"]
|
||||||
|
|
||||||
if src_type == "LOCAL" and dst_type == "LOCAL":
|
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 250
|
return db["IoInMux.I.O"]
|
||||||
|
|
||||||
if src_type == "GLOBAL" and dst_type == "LOCAL":
|
if re.match(r"lutff_\d+/in_\d+", dst[2]):
|
||||||
return 400
|
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"):
|
print(src, dst, src_idx, dst_idx, src_type, dst_type, file=sys.stderr)
|
||||||
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)
|
|
||||||
assert 0
|
assert 0
|
||||||
|
|
||||||
def wiredelay(wire, db):
|
def wiredelay(wire_idx, db):
|
||||||
if db is None:
|
if db is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
wire = wire_names_r[wire]
|
wire = wire_names_r[wire_idx]
|
||||||
wtype = wire_type(wire[2])
|
wtype = wire_type(wire[2])
|
||||||
|
|
||||||
# FIXME
|
# FIXME
|
||||||
@ -492,13 +507,13 @@ def add_bel_input(bel, wire, port):
|
|||||||
if wire not in wire_belports:
|
if wire not in wire_belports:
|
||||||
wire_belports[wire] = set()
|
wire_belports[wire] = set()
|
||||||
wire_belports[wire].add((bel, port))
|
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):
|
def add_bel_output(bel, wire, port):
|
||||||
if wire not in wire_belports:
|
if wire not in wire_belports:
|
||||||
wire_belports[wire] = set()
|
wire_belports[wire] = set()
|
||||||
wire_belports[wire].add((bel, port))
|
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):
|
def add_bel_lc(x, y, z):
|
||||||
bel = len(bel_name)
|
bel = len(bel_name)
|
||||||
@ -759,14 +774,12 @@ bba.post('NEXTPNR_NAMESPACE_END')
|
|||||||
bba.push("chipdb_blob_%s" % dev_name)
|
bba.push("chipdb_blob_%s" % dev_name)
|
||||||
bba.r("chip_info_%s" % dev_name, "chip_info")
|
bba.r("chip_info_%s" % dev_name, "chip_info")
|
||||||
|
|
||||||
index = 0
|
|
||||||
for bel in range(len(bel_name)):
|
for bel in range(len(bel_name)):
|
||||||
bba.l("bel_wires_%d" % bel, "BelWirePOD")
|
bba.l("bel_wires_%d" % bel, "BelWirePOD")
|
||||||
for i in range(len(bel_wires[bel])):
|
for data in sorted(bel_wires[bel]):
|
||||||
bba.u32(bel_wires[bel][i][0], "wire_index")
|
bba.u32(data[0], "port")
|
||||||
bba.u32(portpins[bel_wires[bel][i][1]], "port")
|
bba.u32(data[1], "type")
|
||||||
bba.u32(bel_wires[bel][i][2], "type")
|
bba.u32(data[2], "wire_index")
|
||||||
index += 1
|
|
||||||
|
|
||||||
bba.l("bel_data_%s" % dev_name, "BelInfoPOD")
|
bba.l("bel_data_%s" % dev_name, "BelInfoPOD")
|
||||||
for bel in range(len(bel_name)):
|
for bel in range(len(bel_name)):
|
||||||
|
Loading…
Reference in New Issue
Block a user