ecp5: Update arch to new timing API
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
bd2b3e5e02
commit
8af86ff37d
@ -530,8 +530,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
|
||||
Fmax = 1000 / ctx->getDelayNS(path.second.path_delay);
|
||||
else
|
||||
Fmax = 500 / ctx->getDelayNS(path.second.path_delay);
|
||||
if (!clock_fmax.count(a.clock) ||
|
||||
Fmax < clock_fmax.at(a.clock)) {
|
||||
if (!clock_fmax.count(a.clock) || Fmax < clock_fmax.at(a.clock)) {
|
||||
clock_reports[a.clock] = path;
|
||||
clock_fmax[a.clock] = Fmax;
|
||||
}
|
||||
|
75
ecp5/arch.cc
75
ecp5/arch.cc
@ -539,10 +539,10 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
|
||||
return true;
|
||||
}
|
||||
#if 0 // FIXME
|
||||
if (fromPort == id_WCK && (toPort == id_F0 || toPort == id_F1)) {
|
||||
delay.delay = 717;
|
||||
return true;
|
||||
}
|
||||
if (fromPort == id_WCK && (toPort == id_F0 || toPort == id_F1)) {
|
||||
delay.delay = 717;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
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) ||
|
||||
@ -576,10 +576,10 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
|
||||
}
|
||||
}
|
||||
|
||||
TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const
|
||||
TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const
|
||||
{
|
||||
auto disconnected = [cell](IdString p) { return !cell->ports.count(p) || cell->ports.at(p).net == nullptr; };
|
||||
|
||||
clockInfoCount = 0;
|
||||
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)
|
||||
@ -598,13 +598,13 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id
|
||||
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;
|
||||
clockInfoCount = 1;
|
||||
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;
|
||||
clockInfoCount = 1;
|
||||
return TMG_REGISTER_OUTPUT;
|
||||
}
|
||||
|
||||
@ -614,7 +614,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id
|
||||
|
||||
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;
|
||||
clockInfoCount = 1;
|
||||
return TMG_REGISTER_INPUT;
|
||||
}
|
||||
|
||||
@ -638,10 +638,8 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id
|
||||
for (auto c : boost::adaptors::reverse(port_name)) {
|
||||
if (std::isdigit(c))
|
||||
continue;
|
||||
if (c == 'A')
|
||||
clockPort = id_CLKA;
|
||||
else if (c == 'B')
|
||||
clockPort = id_CLKB;
|
||||
if (c == 'A' || c == 'B')
|
||||
clockInfoCount = 1;
|
||||
else
|
||||
NPNR_ASSERT_FALSE_STR("bad ram port");
|
||||
return (cell->ports.at(port).type == PORT_OUT) ? TMG_REGISTER_OUTPUT : TMG_REGISTER_INPUT;
|
||||
@ -658,6 +656,57 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id
|
||||
}
|
||||
}
|
||||
|
||||
TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
|
||||
{
|
||||
TimingClockingInfo info;
|
||||
info.setup.delay = 0;
|
||||
info.hold.delay = 0;
|
||||
info.clockToQ.delay = 0;
|
||||
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_WD0 || port == id_WD1 || port == id_WAD0 || port == id_WAD1 || port == id_WAD2 ||
|
||||
port == id_WAD3 || port == id_WRE) {
|
||||
info.edge = RISING_EDGE;
|
||||
info.clock_port = id_WCK;
|
||||
info.setup.delay = 100;
|
||||
info.hold.delay = 0;
|
||||
} else if (port == id_DI0 || port == id_DI1 || port == id_CE || port == id_LSR || (sd0 == 1 && port == id_M0) ||
|
||||
(sd1 == 1 && port == id_M1)) {
|
||||
info.edge = cell->sliceInfo.clkmux == id("INV") ? FALLING_EDGE : RISING_EDGE;
|
||||
info.clock_port = id_CLK;
|
||||
info.setup.delay = 100;
|
||||
info.hold.delay = 0;
|
||||
} else {
|
||||
info.edge = cell->sliceInfo.clkmux == id("INV") ? FALLING_EDGE : RISING_EDGE;
|
||||
info.clock_port = id_CLK;
|
||||
info.clockToQ.delay = 395;
|
||||
}
|
||||
} else if (cell->type == id_DP16KD) {
|
||||
for (auto c : boost::adaptors::reverse(port.str(this))) {
|
||||
if (std::isdigit(c))
|
||||
continue;
|
||||
if (c == 'A')
|
||||
info.clock_port = id_CLKA;
|
||||
else if (c == 'B')
|
||||
info.clock_port = id_CLKB;
|
||||
else
|
||||
NPNR_ASSERT_FALSE_STR("bad ram port");
|
||||
}
|
||||
info.edge = (str_or_default(cell->params, info.clock_port == id_CLKB ? id("CLKBMUX") : id("CLKAMUX"), "CLK") ==
|
||||
"INV")
|
||||
? FALLING_EDGE
|
||||
: RISING_EDGE;
|
||||
if (cell->ports.at(port).type == PORT_OUT) {
|
||||
info.clockToQ.delay = 4280;
|
||||
} else {
|
||||
info.setup.delay = 100;
|
||||
info.hold.delay = 0;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> Arch::getTilesAtLocation(int row, int col)
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> ret;
|
||||
|
12
ecp5/arch.h
12
ecp5/arch.h
@ -855,6 +855,12 @@ struct Arch : BaseCtx
|
||||
delay_t getDelayEpsilon() const { return 20; }
|
||||
delay_t getRipupDelayPenalty() const { return 200; }
|
||||
float getDelayNS(delay_t v) const { return v * 0.001; }
|
||||
DelayInfo getDelayFromNS(float ns) const
|
||||
{
|
||||
DelayInfo del;
|
||||
del.delay = delay_t(ns * 1000);
|
||||
return del;
|
||||
}
|
||||
uint32_t getDelayChecksum(delay_t v) const { return v; }
|
||||
bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
|
||||
|
||||
@ -878,8 +884,10 @@ struct Arch : BaseCtx
|
||||
// Get the delay through a cell from one port to another, returning false
|
||||
// if no path exists
|
||||
bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
|
||||
// Get the port class, also setting clockPort if applicable
|
||||
TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const;
|
||||
// Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
|
||||
TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
|
||||
// Get the TimingClockingInfo of a port
|
||||
TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
|
||||
// Return true if a port is a net
|
||||
bool isGlobalNet(const NetInfo *net) const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user