aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2018-11-04 14:51:48 +0000
committerDavid Shah <dave@ds0.me>2018-11-12 14:03:58 +0000
commit8af86ff37d3f370f2bf9add46261f3b5a6b3f5a4 (patch)
tree06d7e1f26873f59df9a3b2a191ad58a1edf5af38 /ecp5
parentbd2b3e5e029e9f84f8e0f52e33ad9a5c12f7c9ff (diff)
downloadnextpnr-8af86ff37d3f370f2bf9add46261f3b5a6b3f5a4.tar.gz
nextpnr-8af86ff37d3f370f2bf9add46261f3b5a6b3f5a4.tar.bz2
nextpnr-8af86ff37d3f370f2bf9add46261f3b5a6b3f5a4.zip
ecp5: Update arch to new timing API
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'ecp5')
-rw-r--r--ecp5/arch.cc75
-rw-r--r--ecp5/arch.h12
2 files changed, 72 insertions, 15 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 91331f7e..a7bebd61 100644
--- a/ecp5/arch.cc
+++ b/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;
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 583d539f..07b1e65d 100644
--- a/ecp5/arch.h
+++ b/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;