Merge branch 'master' of gitlab.com:SymbioticEDA/nextpnr
This commit is contained in:
commit
c667f640d5
@ -51,7 +51,8 @@ class SAPlacer
|
||||
int num_bel_types = 0;
|
||||
for (auto bel : ctx->getBels()) {
|
||||
int x, y;
|
||||
ctx->estimatePosition(bel, x, y);
|
||||
bool gb;
|
||||
ctx->estimatePosition(bel, x, y, gb);
|
||||
BelType type = ctx->getBelType(bel);
|
||||
int type_idx;
|
||||
if (bel_types.find(type) == bel_types.end()) {
|
||||
@ -290,18 +291,17 @@ class SAPlacer
|
||||
float get_wirelength(NetInfo *net)
|
||||
{
|
||||
float wirelength = 0;
|
||||
int driver_x = 0, driver_y = 0;
|
||||
bool consider_driver = false;
|
||||
int driver_x, driver_y;
|
||||
bool driver_gb;
|
||||
CellInfo *driver_cell = net->driver.cell;
|
||||
if (!driver_cell)
|
||||
return 0;
|
||||
if (driver_cell->bel == BelId())
|
||||
return 0;
|
||||
consider_driver =
|
||||
ctx->estimatePosition(driver_cell->bel, driver_x, driver_y);
|
||||
ctx->estimatePosition(driver_cell->bel, driver_x, driver_y, driver_gb);
|
||||
WireId drv_wire = ctx->getWireBelPin(
|
||||
driver_cell->bel, ctx->portPinFromId(net->driver.port));
|
||||
if (!consider_driver)
|
||||
if (driver_gb)
|
||||
return 0;
|
||||
for (auto load : net->users) {
|
||||
if (load.cell == nullptr)
|
||||
@ -309,7 +309,7 @@ class SAPlacer
|
||||
CellInfo *load_cell = load.cell;
|
||||
if (load_cell->bel == BelId())
|
||||
continue;
|
||||
// ctx->estimatePosition(load_cell->bel, load_x, load_y);
|
||||
// ctx->estimatePosition(load_cell->bel, load_x, load_y, load_gb);
|
||||
WireId user_wire = ctx->getWireBelPin(
|
||||
load_cell->bel, ctx->portPinFromId(load.port));
|
||||
// wirelength += std::abs(load_x - driver_x) + std::abs(load_y -
|
||||
@ -376,8 +376,9 @@ class SAPlacer
|
||||
delta = new_wirelength - curr_wirelength;
|
||||
n_move++;
|
||||
// SA acceptance criterea
|
||||
if (delta < 0 || (temp > 1e-6 && (ctx->rng() / float(0x3fffffff)) <=
|
||||
std::exp(-delta / temp))) {
|
||||
if (delta < 0 ||
|
||||
(temp > 1e-6 &&
|
||||
(ctx->rng() / float(0x3fffffff)) <= std::exp(-delta / temp))) {
|
||||
n_accept++;
|
||||
if (delta < 0)
|
||||
improved = true;
|
||||
@ -407,8 +408,9 @@ class SAPlacer
|
||||
BelId random_bel_for_cell(CellInfo *cell)
|
||||
{
|
||||
BelType targetType = ctx->belTypeFromId(cell->type);
|
||||
int x = 0, y = 0;
|
||||
ctx->estimatePosition(cell->bel, x, y);
|
||||
int x, y;
|
||||
bool gb;
|
||||
ctx->estimatePosition(cell->bel, x, y, gb);
|
||||
while (true) {
|
||||
int nx = ctx->rng(2 * diameter + 1) + std::max(x - diameter, 0);
|
||||
int ny = ctx->rng(2 * diameter + 1) + std::max(y - diameter, 0);
|
||||
|
@ -206,15 +206,16 @@ struct Router
|
||||
assert(next_delay >= 0);
|
||||
|
||||
if (visited.count(next_wire)) {
|
||||
if (visited.at(next_wire).delay <= next_delay + 1e-3)
|
||||
if (visited.at(next_wire).delay <=
|
||||
next_delay + ctx->getDelayEpsilon())
|
||||
continue;
|
||||
#if 0 // FIXME
|
||||
if (ctx->verbose)
|
||||
log("Found better route to %s. Old vs new delay "
|
||||
"estimate: %.2f %.2f\n",
|
||||
"estimate: %.3f %.3f\n",
|
||||
ctx->getWireName(next_wire).c_str(),
|
||||
float(visited.at(next_wire).delay),
|
||||
float(next_delay));
|
||||
ctx->getDelayNS(visited.at(next_wire).delay),
|
||||
ctx->getDelayNS(next_delay));
|
||||
#endif
|
||||
revisitCnt++;
|
||||
}
|
||||
@ -246,8 +247,8 @@ struct Router
|
||||
}
|
||||
|
||||
if (ctx->verbose)
|
||||
log(" Final path delay: %.2f\n",
|
||||
float(visited[dst_wire].delay));
|
||||
log(" Final path delay: %.3f\n",
|
||||
ctx->getDelayNS(visited[dst_wire].delay));
|
||||
maxDelay = fmaxf(maxDelay, visited[dst_wire].delay);
|
||||
|
||||
if (ctx->verbose)
|
||||
@ -257,7 +258,8 @@ struct Router
|
||||
|
||||
while (1) {
|
||||
if (ctx->verbose)
|
||||
log(" %8.2f %s\n", float(visited[cursor].delay),
|
||||
log(" %8.3f %s\n",
|
||||
ctx->getDelayNS(visited[cursor].delay),
|
||||
ctx->getWireName(cursor).c_str(ctx));
|
||||
|
||||
if (src_wires.count(cursor))
|
||||
|
@ -141,11 +141,11 @@ const std::vector<PipId> &Arch::getWireAliases(WireId wire) const
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
bool Arch::estimatePosition(BelId bel, int &x, int &y) const
|
||||
void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
|
||||
{
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
return false;
|
||||
x = 0;
|
||||
y = 0;
|
||||
gb = false;
|
||||
}
|
||||
|
||||
delay_t Arch::estimateDelay(WireId src, WireId dst) const { return 0.0; }
|
||||
|
@ -120,8 +120,10 @@ struct Arch : BaseCtx
|
||||
const std::vector<PipId> &getPipsUphill(WireId wire) const;
|
||||
const std::vector<PipId> &getWireAliases(WireId wire) const;
|
||||
|
||||
bool estimatePosition(BelId bel, int &x, int &y) const;
|
||||
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
|
||||
delay_t estimateDelay(WireId src, WireId dst) const;
|
||||
delay_t getDelayEpsilon() const { return 0.01; }
|
||||
float getDelayNS(delay_t v) const { return v; }
|
||||
|
||||
std::vector<GraphicElement> getFrameGraphics() const;
|
||||
std::vector<GraphicElement> getBelGraphics(BelId bel) const;
|
||||
|
@ -749,12 +749,11 @@ void json_import(Context *ctx, string modname, JsonNode *node)
|
||||
int netid = bits->data_array.at(i)->data_number;
|
||||
if (netid >= netnames.size())
|
||||
netnames.resize(netid + 1);
|
||||
netnames.at(netid) =
|
||||
ctx->id(basename +
|
||||
(num_bits == 1 ? ""
|
||||
: std::string("[") +
|
||||
std::to_string(i) +
|
||||
std::string("]")));
|
||||
netnames.at(netid) = ctx->id(
|
||||
basename +
|
||||
(num_bits == 1 ? "" : std::string("[") +
|
||||
std::to_string(i) +
|
||||
std::string("]")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,16 @@ InfoTab::InfoTab(QWidget *parent) : QWidget(parent)
|
||||
f.setStyleHint(QFont::Monospace);
|
||||
plainTextEdit->setFont(f);
|
||||
|
||||
plainTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
QAction *clearAction = new QAction("Clear &buffer", this);
|
||||
clearAction->setStatusTip("Clears display buffer");
|
||||
connect(clearAction, SIGNAL(triggered()), this, SLOT(clearBuffer()));
|
||||
contextMenu = plainTextEdit->createStandardContextMenu();
|
||||
contextMenu->addSeparator();
|
||||
contextMenu->addAction(clearAction);
|
||||
connect(plainTextEdit, SIGNAL(customContextMenuRequested(const QPoint)),
|
||||
this, SLOT(showContextMenu(const QPoint)));
|
||||
|
||||
QGridLayout *mainLayout = new QGridLayout();
|
||||
mainLayout->addWidget(plainTextEdit);
|
||||
setLayout(mainLayout);
|
||||
@ -20,3 +30,10 @@ void InfoTab::info(std::string str)
|
||||
plainTextEdit->insertPlainText(str.c_str());
|
||||
plainTextEdit->moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
void InfoTab::showContextMenu(const QPoint &pt)
|
||||
{
|
||||
contextMenu->exec(mapToGlobal(pt));
|
||||
}
|
||||
|
||||
void InfoTab::clearBuffer() { plainTextEdit->clear(); }
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef INFOTAB_H
|
||||
#define INFOTAB_H
|
||||
|
||||
#include <QMenu>
|
||||
#include <QPlainTextEdit>
|
||||
#include "nextpnr.h"
|
||||
|
||||
@ -14,9 +15,13 @@ class InfoTab : public QWidget
|
||||
public:
|
||||
explicit InfoTab(QWidget *parent = 0);
|
||||
void info(std::string str);
|
||||
private Q_SLOTS:
|
||||
void showContextMenu(const QPoint &pt);
|
||||
void clearBuffer();
|
||||
|
||||
private:
|
||||
QPlainTextEdit *plainTextEdit;
|
||||
QMenu *contextMenu;
|
||||
};
|
||||
|
||||
#endif // INFOTAB_H
|
||||
|
@ -15,6 +15,16 @@ PythonTab::PythonTab(QWidget *parent) : QWidget(parent)
|
||||
f.setStyleHint(QFont::Monospace);
|
||||
plainTextEdit->setFont(f);
|
||||
|
||||
plainTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
QAction *clearAction = new QAction("Clear &buffer", this);
|
||||
clearAction->setStatusTip("Clears display buffer");
|
||||
connect(clearAction, SIGNAL(triggered()), this, SLOT(clearBuffer()));
|
||||
contextMenu = plainTextEdit->createStandardContextMenu();
|
||||
contextMenu->addSeparator();
|
||||
contextMenu->addAction(clearAction);
|
||||
connect(plainTextEdit, SIGNAL(customContextMenuRequested(const QPoint)),
|
||||
this, SLOT(showContextMenu(const QPoint)));
|
||||
|
||||
lineEdit = new LineEditor();
|
||||
lineEdit->setMinimumHeight(30);
|
||||
lineEdit->setMaximumHeight(30);
|
||||
@ -98,3 +108,10 @@ void PythonTab::editLineReturnPressed(QString text)
|
||||
print(std::string(">>> " + input + "\n"));
|
||||
int error = executePython(input);
|
||||
}
|
||||
|
||||
void PythonTab::showContextMenu(const QPoint &pt)
|
||||
{
|
||||
contextMenu->exec(mapToGlobal(pt));
|
||||
}
|
||||
|
||||
void PythonTab::clearBuffer() { plainTextEdit->clear(); }
|
@ -2,6 +2,7 @@
|
||||
#define PYTHONTAB_H
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QMenu>
|
||||
#include <QPlainTextEdit>
|
||||
#include "emb.h"
|
||||
#include "line_editor.h"
|
||||
@ -22,10 +23,13 @@ class PythonTab : public QWidget
|
||||
int executePython(std::string &command);
|
||||
private Q_SLOTS:
|
||||
void editLineReturnPressed(QString text);
|
||||
void showContextMenu(const QPoint &pt);
|
||||
void clearBuffer();
|
||||
|
||||
private:
|
||||
QPlainTextEdit *plainTextEdit;
|
||||
LineEditor *lineEdit;
|
||||
QMenu *contextMenu;
|
||||
emb::stdout_write_type write;
|
||||
};
|
||||
|
||||
|
@ -295,13 +295,12 @@ std::string Arch::getBelPackagePin(BelId bel) const
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
bool Arch::estimatePosition(BelId bel, int &x, int &y) const
|
||||
void Arch::estimatePosition(BelId bel, int &x, int &y, bool &gb) const
|
||||
{
|
||||
assert(bel != BelId());
|
||||
x = chip_info->bel_data[bel.index].x;
|
||||
y = chip_info->bel_data[bel.index].y;
|
||||
|
||||
return chip_info->bel_data[bel.index].type != TYPE_SB_GB;
|
||||
gb = chip_info->bel_data[bel.index].type == TYPE_SB_GB;
|
||||
}
|
||||
|
||||
delay_t Arch::estimateDelay(WireId src, WireId dst) const
|
||||
|
19
ice40/arch.h
19
ice40/arch.h
@ -63,6 +63,17 @@ enum PortPin : int32_t
|
||||
PIN_MAXIDX
|
||||
};
|
||||
|
||||
enum WireType : int8_t
|
||||
{
|
||||
WIRE_TYPE_NONE = 0,
|
||||
WIRE_TYPE_LOCAL = 1,
|
||||
WIRE_TYPE_GLOBAL = 2,
|
||||
WIRE_TYPE_SP4_VERT = 3,
|
||||
WIRE_TYPE_SP4_HORZ = 4,
|
||||
WIRE_TYPE_SP12_HORZ = 5,
|
||||
WIRE_TYPE_SP12_VERT = 6
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**** Everything in this section must be kept in sync with chipdb.py ****/
|
||||
@ -130,7 +141,9 @@ struct WireInfoPOD
|
||||
BelPortPOD bel_uphill;
|
||||
RelPtr<BelPortPOD> bels_downhill;
|
||||
|
||||
int16_t x, y;
|
||||
int8_t x, y;
|
||||
WireType type;
|
||||
int8_t padding_0;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PackagePinPOD
|
||||
@ -740,8 +753,10 @@ struct Arch : BaseCtx
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
bool estimatePosition(BelId bel, int &x, int &y) const;
|
||||
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
|
||||
delay_t estimateDelay(WireId src, WireId dst) const;
|
||||
delay_t getDelayEpsilon() const { return 10; }
|
||||
float getDelayNS(delay_t v) const { return v * 0.001; }
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
|
118
ice40/chipdb.py
118
ice40/chipdb.py
@ -45,6 +45,7 @@ cbit_re = re.compile(r'B(\d+)\[(\d+)\]')
|
||||
portpins = dict()
|
||||
beltypes = dict()
|
||||
tiletypes = dict()
|
||||
wiretypes = dict()
|
||||
|
||||
with open("ice40/portpins.inc") as f:
|
||||
for line in f:
|
||||
@ -69,9 +70,30 @@ tiletypes["IO"] = 2
|
||||
tiletypes["RAMB"] = 3
|
||||
tiletypes["RAMT"] = 4
|
||||
|
||||
wiretypes["LOCAL"] = 1
|
||||
wiretypes["GLOBAL"] = 2
|
||||
wiretypes["SP4_VERT"] = 5
|
||||
wiretypes["SP4_HORZ"] = 6
|
||||
wiretypes["SP12_HORZ"] = 7
|
||||
wiretypes["SP12_VERT"] = 8
|
||||
|
||||
def maj_wire_name(name):
|
||||
if re.match(r"lutff_\d/(in|out)", name[2]):
|
||||
if name[2].startswith("lutff_"):
|
||||
return True
|
||||
if name[2].startswith("io_"):
|
||||
return True
|
||||
if name[2].startswith("ram/"):
|
||||
return True
|
||||
if name[2].startswith("sp4_h_r_"):
|
||||
return name[2] in ("sp4_h_r_0", "sp4_h_r_1", "sp4_h_r_2", "sp4_h_r_3", "sp4_h_r_4", "sp4_h_r_5",
|
||||
"sp4_h_r_6", "sp4_h_r_7", "sp4_h_r_8", "sp4_h_r_9", "sp4_h_r_10", "sp4_h_r_11")
|
||||
if name[2].startswith("sp4_v_b_"):
|
||||
return name[2] in ("sp4_v_b_0", "sp4_v_b_1", "sp4_v_b_2", "sp4_v_b_3", "sp4_v_b_4", "sp4_v_b_5",
|
||||
"sp4_v_b_6", "sp4_v_b_7", "sp4_v_b_8", "sp4_v_b_9", "sp4_v_b_10", "sp4_v_b_11")
|
||||
if name[2].startswith("sp12_h_r_"):
|
||||
return name[2] in ("sp12_h_r_0", "sp12_h_r_1")
|
||||
if name[2].startswith("sp12_v_b_"):
|
||||
return name[2] in ("sp12_v_b_0", "sp12_v_b_1")
|
||||
return False
|
||||
|
||||
def cmp_wire_names(newname, oldname):
|
||||
@ -79,8 +101,92 @@ def cmp_wire_names(newname, oldname):
|
||||
return True
|
||||
if maj_wire_name(oldname):
|
||||
return False
|
||||
|
||||
if newname[2].startswith("sp") and oldname[2].startswith("sp"):
|
||||
m1 = re.match(r".*_(\d+)$", newname[2])
|
||||
m2 = re.match(r".*_(\d+)$", oldname[2])
|
||||
if m1 and m2:
|
||||
idx1 = int(m1.group(1))
|
||||
idx2 = int(m2.group(1))
|
||||
if idx1 != idx2:
|
||||
return idx1 < idx2
|
||||
|
||||
return newname < oldname
|
||||
|
||||
def wire_type(name):
|
||||
longname = name
|
||||
name = name.split('/')[-1]
|
||||
wt = None
|
||||
|
||||
if name.startswith("glb_netwk_"):
|
||||
wt = "GLOBAL"
|
||||
elif name.startswith("D_IN_") or name.startswith("D_OUT_"):
|
||||
wt = "LOCAL"
|
||||
elif name in ("OUT_ENB", "cen", "inclk", "latch", "outclk", "clk", "s_r", "carry_in", "carry_in_mux"):
|
||||
wt = "LOCAL"
|
||||
elif name in ("in_0", "in_1", "in_2", "in_3", "cout", "lout", "out", "fabout"):
|
||||
wt = "LOCAL"
|
||||
elif name.startswith("local_g") or name.startswith("glb2local_"):
|
||||
wt = "LOCAL"
|
||||
elif name.startswith("span4_horz_") or name.startswith("sp4_h_"):
|
||||
wt = "SP4_HORZ"
|
||||
elif name.startswith("span4_vert_") or name.startswith("sp4_v_") or name.startswith("sp4_r_v_"):
|
||||
wt = "SP4_VERT"
|
||||
elif name.startswith("span12_horz_") or name.startswith("sp12_h_"):
|
||||
wt = "SP12_HORZ"
|
||||
elif name.startswith("span12_vert_") or name.startswith("sp12_v_"):
|
||||
wt = "SP12_VERT"
|
||||
elif name.startswith("MASK_") or name.startswith("RADDR_") or name.startswith("WADDR_"):
|
||||
wt = "LOCAL"
|
||||
elif name.startswith("RDATA_") or name.startswith("WDATA_") or name.startswith("neigh_op_"):
|
||||
wt = "LOCAL"
|
||||
elif name in ("WCLK", "WCLKE", "WE", "RCLK", "RCLKE", "RE"):
|
||||
wt = "LOCAL"
|
||||
|
||||
if wt is None:
|
||||
print("No type for wire: %s (%s)" % (longname, name), file=sys.stderr)
|
||||
assert 0
|
||||
return wt
|
||||
|
||||
def pipdelay(src, dst):
|
||||
src = wire_names_r[src]
|
||||
dst = wire_names_r[dst]
|
||||
src_type = wire_type(src[2])
|
||||
dst_type = wire_type(dst[2])
|
||||
|
||||
if src_type == "LOCAL" and dst_type == "LOCAL":
|
||||
return 250
|
||||
|
||||
if src_type == "GLOBAL" and dst_type == "LOCAL":
|
||||
return 400
|
||||
|
||||
# Local -> Span
|
||||
|
||||
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)
|
||||
assert 0
|
||||
|
||||
with open(sys.argv[1], "r") as f:
|
||||
mode = None
|
||||
|
||||
@ -663,7 +769,7 @@ for wire in range(num_wires):
|
||||
pi = dict()
|
||||
pi["src"] = src
|
||||
pi["dst"] = wire
|
||||
pi["delay"] = 1
|
||||
pi["delay"] = pipdelay(src, wire)
|
||||
pi["x"] = pip_xy[(src, wire)][0]
|
||||
pi["y"] = pip_xy[(src, wire)][1]
|
||||
pi["switch_mask"] = pip_xy[(src, wire)][2]
|
||||
@ -687,7 +793,7 @@ for wire in range(num_wires):
|
||||
pi = dict()
|
||||
pi["src"] = wire
|
||||
pi["dst"] = dst
|
||||
pi["delay"] = 1
|
||||
pi["delay"] = pipdelay(wire, dst)
|
||||
pi["x"] = pip_xy[(wire, dst)][0]
|
||||
pi["y"] = pip_xy[(wire, dst)][1]
|
||||
pi["switch_mask"] = pip_xy[(wire, dst)][2]
|
||||
@ -809,8 +915,10 @@ for info in wireinfo:
|
||||
bba.u32(info["uphill_bel"], "bel_uphill.bel_index")
|
||||
bba.u32(info["uphill_pin"], "bel_uphill.port")
|
||||
bba.r(info["list_bels_downhill"], "bels_downhill")
|
||||
bba.u16(info["x"], "x")
|
||||
bba.u16(info["y"], "y")
|
||||
bba.u8(info["x"], "x")
|
||||
bba.u8(info["y"], "y")
|
||||
bba.u8(wiretypes[wire_type(info["name"])], "type")
|
||||
bba.u8(0, "padding")
|
||||
|
||||
bba.l("pip_data_%s" % dev_name, "PipInfoPOD")
|
||||
for info in pipinfo:
|
||||
|
Loading…
Reference in New Issue
Block a user