aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-08-19 17:11:34 +0100
committerGitHub <noreply@github.com>2018-08-19 17:11:34 +0100
commit0f86d082e50eddd366a3ffc4524a6a7111bb8d30 (patch)
tree64a50c4946cda129e6064288b082ffbdeb62747b
parent91c60ac66715de07c6980e753bbb906b0cf15a29 (diff)
parent1b3a201a54d36085a0675ebaebda523645ad45b3 (diff)
downloadnextpnr-0f86d082e50eddd366a3ffc4524a6a7111bb8d30.tar.gz
nextpnr-0f86d082e50eddd366a3ffc4524a6a7111bb8d30.tar.bz2
nextpnr-0f86d082e50eddd366a3ffc4524a6a7111bb8d30.zip
Merge pull request #59 from daveshah1/ecp5_timing
Simple timing model for ECP5
-rw-r--r--ecp5/arch.cc146
-rw-r--r--ecp5/arch.h2
-rwxr-xr-xecp5/trellis_import.py46
3 files changed, 178 insertions, 16 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index b2ce4acb..57ba480d 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -46,13 +46,16 @@ static std::tuple<int, int, std::string> split_identifier_name(const std::string
void IdString::initialize_arch(const BaseCtx *ctx)
{
#define X(t) initialize_add(ctx, #t, ID_##t);
+
#include "constids.inc"
+
#undef X
}
// -----------------------------------------------------------------------
-static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr) { return ptr->get(); }
+static const ChipInfoPOD *get_chip_info(const RelPtr<ChipInfoPOD> *ptr)
+{ return ptr->get(); }
#if defined(_MSC_VER)
void load_chipdb();
@@ -369,7 +372,7 @@ BelId Arch::getBelByLocation(Loc loc) const
delay_t Arch::estimateDelay(WireId src, WireId dst) const
{
- return 50 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y));
+ return 100 * (abs(src.location.x - dst.location.x) + abs(src.location.y - dst.location.y));
}
delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
@@ -378,16 +381,19 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const
auto driver_loc = getBelLocation(driver.cell->bel);
auto sink_loc = getBelLocation(sink.cell->bel);
- return 50 * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y));
+ return 100 * (abs(driver_loc.x - sink_loc.x) + abs(driver_loc.y - sink_loc.y));
}
-bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; }
+bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const
+{ return false; }
// -----------------------------------------------------------------------
-bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }
+bool Arch::place()
+{ return placer1(getCtx(), Placer1Cfg(getCtx())); }
-bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); }
+bool Arch::route()
+{ return router1(getCtx(), Router1Cfg(getCtx())); }
// -----------------------------------------------------------------------
@@ -408,8 +414,8 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
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;
+ 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);
}
@@ -438,22 +444,136 @@ DecalXY Arch::getBelDecal(BelId bel) const
return decalxy;
}
-DecalXY Arch::getWireDecal(WireId wire) const { return {}; }
+DecalXY Arch::getWireDecal(WireId wire) const
+{ return {}; }
-DecalXY Arch::getPipDecal(PipId pip) const { return {}; };
+DecalXY Arch::getPipDecal(PipId pip) const
+{ return {}; };
-DecalXY Arch::getGroupDecal(GroupId pip) const { return {}; };
+DecalXY Arch::getGroupDecal(GroupId pip) const
+{ return {}; };
// -----------------------------------------------------------------------
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
{
- return false;
+ // Data for -8 grade
+ if (cell->type == id_TRELLIS_SLICE) {
+ bool has_carry = str_or_default(cell->params, id("MODE"), "LOGIC") == "CCU2";
+ if (fromPort == id_A0 || fromPort == id_B0 || fromPort == id_C0 || fromPort == id_D0) {
+ if (toPort == id_F0) {
+ delay.delay = 180;
+ return true;
+ } else if (has_carry && toPort == id_F1) {
+ delay.delay = 500;
+ return true;
+ } else if (has_carry && toPort == id_FCO) {
+ delay.delay = 355;
+ return true;
+ } else if (toPort == id_OFX0) {
+ delay.delay = 306;
+ return true;
+ }
+ }
+
+ if (fromPort == id_A1 || fromPort == id_B1 || fromPort == id_C1 || fromPort == id_D1) {
+ if (toPort == id_F1) {
+ delay.delay = 180;
+ return true;
+ } else if (has_carry && toPort == id_FCO) {
+ delay.delay = 355;
+ return true;
+ } else if (toPort == id_OFX0) {
+ delay.delay = 306;
+ return true;
+ }
+ }
+
+ if (has_carry && fromPort == id_FCI) {
+ if (toPort == id_F0) {
+ delay.delay = 328;
+ return true;
+ } else if (toPort == id_F1) {
+ delay.delay = 349;
+ return true;
+ } else if (toPort == id_FCO) {
+ delay.delay = 56;
+ return true;
+ }
+ }
+
+ if (fromPort == id_CLK && (toPort == id_Q0 || toPort == id_Q1)) {
+ delay.delay = 395;
+ return true;
+ }
+
+ if (fromPort == id_M0 && toPort == id_OFX0) {
+ delay.delay = 193;
+ return true;
+ }
+
+ if (fromPort == id_WCK && (toPort == id_F0 || toPort == id_F1)) {
+ delay.delay = 717;
+ return true;
+ }
+
+ if ((fromPort == id_A0 && toPort == id_WADO3) ||
+ (fromPort == id_A1 && toPort == id_WDO1) ||
+ (fromPort == id_B0 && toPort == id_WADO1) ||
+ (fromPort == id_B1 && toPort == id_WDO3) ||
+ (fromPort == id_C0 && toPort == id_WADO2) ||
+ (fromPort == id_C1 && toPort == id_WDO0) ||
+ (fromPort == id_D0 && toPort == id_WADO0) ||
+ (fromPort == id_D1 && toPort == id_WDO2)) {
+ delay.delay = 0;
+ return true;
+ }
+ return false;
+ } else {
+ return false;
+ }
}
TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const
{
- return TMG_IGNORE;
+ if (cell->type == id_TRELLIS_SLICE) {
+ int sd0 = int_or_default(cell->params, id("REG0_SD"), 0), sd1 = int_or_default(cell->params, id("REG1_SD"), 0);
+ if (port == id_CLK || port == id_WCK)
+ return TMG_CLOCK_INPUT;
+ if (port == id_A0 || port == id_A1 || port == id_B0 || port == id_B1 || port == id_C0 || port == id_C1 ||
+ port == id_D0 || port == id_D1 || port == id_FCI || port == id_FXA || port == id_FXB)
+ return TMG_COMB_INPUT;
+ if (port == id_F0 || port == id_F1 || port == id_FCO || port == id_OFX0 || port == id_OFX1)
+ return TMG_COMB_OUTPUT;
+ if (port == id_DI0 || port == id_DI1 || port == id_CE || port == id_LSR || (sd0 == 1 && port == id_M0) || (sd1 == 1 && port == id_M1)) {
+ clockPort = id_CLK;
+ return TMG_REGISTER_INPUT;
+ }
+ if (port == id_M0 || port == id_M1)
+ return TMG_COMB_INPUT;
+ if (port == id_Q0 || port == id_Q1) {
+ clockPort = id_CLK;
+ return TMG_REGISTER_OUTPUT;
+ }
+
+ if (port == id_WDO0 || port == id_WDO1 || port == id_WDO2 || port == id_WDO3 || port == id_WADO0 || port == id_WADO1 || port == id_WADO2 || port == id_WADO3)
+ return TMG_COMB_OUTPUT;
+
+ if (port == id_WD0 || port == id_WD1 || port == id_WAD0 || port == id_WAD1 || port == id_WAD2 || port == id_WAD3 || port == id_WRE) {
+ clockPort = id_WCK;
+ return TMG_REGISTER_INPUT;
+ }
+
+ NPNR_ASSERT_FALSE_STR("no timing type for slice port '" + port.str(this) + "'");
+ } else if (cell->type == id_TRELLIS_IO) {
+ if (port == id_T || port == id_I)
+ return TMG_ENDPOINT;
+ if (port == id_O)
+ return TMG_STARTPOINT;
+ return TMG_IGNORE;
+ } else {
+ NPNR_ASSERT_FALSE_STR("no timing data for cell type '" + cell->type.str(this) + "'");
+ }
}
std::vector<std::pair<std::string, std::string>> Arch::getTilesAtLocation(int row, int col)
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 712c6e0a..da86d4e2 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -745,7 +745,7 @@ struct Arch : BaseCtx
{
DelayInfo delay;
NPNR_ASSERT(pip != PipId());
- delay.delay = locInfo(pip)->pip_data[pip.index].delay * 100;
+ delay.delay = locInfo(pip)->pip_data[pip.index].delay;
return delay;
}
diff --git a/ecp5/trellis_import.py b/ecp5/trellis_import.py
index 7c7c9e15..de8e9958 100755
--- a/ecp5/trellis_import.py
+++ b/ecp5/trellis_import.py
@@ -130,11 +130,54 @@ def process_loc_globals(chip):
tapdrv = chip.global_data.get_tap_driver(y, x)
global_data[x, y] = (quadrants.index(quad), int(tapdrv.dir), tapdrv.col)
+def get_wire_type(name):
+ if "H00" in name or "V00" in name:
+ return "X0"
+ if "H01" in name or "V01" in name:
+ return "X1"
+ if "H02" in name or "V02" in name:
+ return "X2"
+ if "H06" in name or "V06" in name:
+ return "X6"
+ if "_SLICE" in name or "_EBR" in name:
+ return "SLICE"
+ return "LOCAL"
+
+def get_pip_delay(wire_from, wire_to):
+ # ECP5 timings WIP!!!
+ type_from = get_wire_type(wire_from)
+ type_to = get_wire_type(wire_to)
+ if type_from == "X2" and type_to == "X2":
+ return 170
+ if type_from == "SLICE" or type_to == "SLICE":
+ return 205
+ if type_from in ("LOCAL", "X0") and type_to in ("X1", "X2", "X6"):
+ return 90
+ if type_from == "X6" or type_to == "X6":
+ return 200
+ if type_from in ("X1", "X2", "X6") and type_to in ("LOCAL", "X0"):
+ return 90
+ return 100
+
+
+
def write_database(dev_name, chip, ddrg, endianness):
def write_loc(loc, sym_name):
bba.u16(loc.x, "%s.x" % sym_name)
bba.u16(loc.y, "%s.y" % sym_name)
+ loctypes = list([_.key() for _ in ddrg.locationTypes])
+ loc_with_type = {}
+ for y in range(0, max_row+1):
+ for x in range(0, max_col+1):
+ loc_with_type[loctypes.index(ddrg.typeAtLocation[pytrellis.Location(x, y)])] = (x, y)
+
+ def get_wire_name(arc_loctype, rel, idx):
+ loc = loc_with_type[arc_loctype]
+ lt = ddrg.typeAtLocation[pytrellis.Location(loc[0] + rel.x, loc[1] + rel.y)]
+ wire = ddrg.locationTypes[lt].wires[idx]
+ return ddrg.to_str(wire.name)
+
bba = BinaryBlobAssembler()
bba.pre('#include "nextpnr.h"')
bba.pre('NEXTPNR_NAMESPACE_BEGIN')
@@ -142,7 +185,6 @@ def write_database(dev_name, chip, ddrg, endianness):
bba.push("chipdb_blob_%s" % dev_name)
bba.r("chip_info", "chip_info")
- loctypes = list([_.key() for _ in ddrg.locationTypes])
for idx in range(len(loctypes)):
loctype = ddrg.locationTypes[loctypes[idx]]
@@ -153,7 +195,7 @@ def write_database(dev_name, chip, ddrg, endianness):
write_loc(arc.sinkWire.rel, "dst")
bba.u32(arc.srcWire.id, "src_idx")
bba.u32(arc.sinkWire.id, "dst_idx")
- bba.u32(arc.delay, "delay") # TODO:delay
+ bba.u32(get_pip_delay(get_wire_name(idx, arc.srcWire.rel, arc.srcWire.id), get_wire_name(idx, arc.sinkWire.rel, arc.sinkWire.id)), "delay") # TODO:delay
bba.u16(get_tiletype_index(ddrg.to_str(arc.tiletype)), "tile_type")
bba.u8(int(arc.cls), "pip_type")
bba.u8(0, "padding")