From ec948487741d982707122f96d127af1f3c95ee66 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sun, 19 Aug 2018 16:59:36 +0100 Subject: [PATCH] ecp5: Add cell delays Signed-off-by: David Shah --- ecp5/arch.cc | 142 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 11 deletions(-) diff --git a/ecp5/arch.cc b/ecp5/arch.cc index b2ce4acb..f9853ae2 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -46,13 +46,16 @@ static std::tuple 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 *ptr) { return ptr->get(); } +static const ChipInfoPOD *get_chip_info(const RelPtr *ptr) +{ return ptr->get(); } #if defined(_MSC_VER) void load_chipdb(); @@ -381,13 +384,16 @@ delay_t Arch::predictDelay(const NetInfo *net_info, const PortRef &sink) const return 50 * (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 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> Arch::getTilesAtLocation(int row, int col)