Skip to content

Commit

Permalink
BUGFIX: Static timing analysis no longer goes into infinite recursion…
Browse files Browse the repository at this point in the history
… when we have a combinatorial loop. Report combinatorial loops as PAR warnings. Skip timing analysis if we have no timing data file. Reduced warning spam when timing data is incomplete from one message per path to one message total
azonenberg committed Jun 9, 2017
1 parent 567ff4a commit 48edca9
Showing 3 changed files with 60 additions and 8 deletions.
57 changes: 49 additions & 8 deletions src/gp4par/par_reporting.cpp
Original file line number Diff line number Diff line change
@@ -247,6 +247,12 @@ void PrintPlacementReport(PARGraph* netlist, Greenpak4Device* /*device*/)
*/
void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
{
if(!device->HasTimingData())
{
LogWarning("No timing data for target device, not running timing analysis\n");
return;
}

LogNotice("\nTiming report:\n");
LogIndenter li;

@@ -287,6 +293,7 @@ void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)

//DEBUG: print all paths
int i=0;
bool incomplete = false;
for(auto path : paths)
{
LogVerbose("Path %d\n", i++);
@@ -330,8 +337,9 @@ void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
auto rscell = device->GetIOB(3);
if(!rscell->GetCombinatorialDelay(previous_port, edge->m_sourceport, corner, delay))
{
LogWarning("Couldn't get timing data even from fallback pin\n");
delay = CombinatorialDelay(0, 0);
//LogWarning("Couldn't get timing data even from fallback pin\n");
incomplete = true;
continue;
}
}

@@ -356,8 +364,9 @@ void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
CombinatorialDelay delay;
if(!srccell->GetCombinatorialDelay(previous_port, edge->m_sourceport, corner, delay))
{
LogWarning("Couldn't get timing data\n");
delay = CombinatorialDelay(0, 0);
//LogWarning("Couldn't get timing data\n");
incomplete = true;
continue;
}
float worst = delay.GetWorst();
cdelay += worst;
@@ -381,8 +390,9 @@ void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
{
if(!xc->GetCombinatorialDelay("I", "O", corner, delay))
{
LogWarning("Couldn't get timing data\n");
delay = CombinatorialDelay(0, 0);
//LogWarning("Couldn't get timing data\n");
incomplete = true;
continue;
}
float worst = delay.GetWorst();
cdelay += worst;
@@ -410,8 +420,9 @@ void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
auto rscell = device->GetIOB(3);
if(!rscell->GetCombinatorialDelay(edge->m_destport, "IO", corner, delay))
{
LogWarning("Couldn't get timing data even from fallback pin\n");
delay = CombinatorialDelay(0, 0);
//LogWarning("Couldn't get timing data even from fallback pin\n");
incomplete = true;
continue;
}
}

@@ -432,6 +443,8 @@ void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
"+--------------------------------------------------------------+------------+-----------"
"+------------+------------+------------+\n");
}
if(incomplete)
LogWarning("Timing data doesn't have info for all primitives, report is incomplete\n");
}

/**
@@ -495,6 +508,34 @@ void FindCombinatorialPaths(
{
auto edge = destnode->GetEdgeByIndex(i);

//Verify that this edge is not already in the netlist. If it is, complain and stop
bool loop = false;
for(auto tedge : basepath)
{
if(edge == tedge)
{
loop = true;

LogWarning("Found combinatorial loop, not following it for static timing\n");
LogIndenter li;

for(auto eedge : basepath)
{
auto snode = static_cast<Greenpak4NetlistEntity*>(eedge->m_sourcenode->GetData());
auto dnode = static_cast<Greenpak4NetlistEntity*>(eedge->m_destnode->GetData());
LogWarning("From cell %50s port %15s to %50s port %15s\n",
snode->m_name.c_str(),
eedge->m_sourceport.c_str(),
dnode->m_name.c_str(),
eedge->m_destport.c_str());
}

break;
}
}
if(loop)
continue;

//Find all paths that begin with the new, longer path
CombinatorialPath npath = basepath;
npath.push_back(edge);
3 changes: 3 additions & 0 deletions src/greenpak4/Greenpak4Device.cpp
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ Greenpak4Device::Greenpak4Device(
, m_disableChargePump(false)
, m_ldoBypass(false)
, m_nvmLoadRetryCount(1)
, m_hasTimingData(false)
{
//Create power rails
//These have to come first, since all other nodes will refer to these during construction
@@ -1413,5 +1414,7 @@ bool Greenpak4Device::LoadTimingData(json_object* object)
return false;
}

m_hasTimingData = true;

return true;
}
8 changes: 8 additions & 0 deletions src/greenpak4/Greenpak4Device.h
Original file line number Diff line number Diff line change
@@ -336,6 +336,9 @@ class Greenpak4Device
bool LoadTimingData(json_object* object);
bool LoadTimingData(std::string fname);

bool HasTimingData()
{ return m_hasTimingData; }

protected:

bool GenerateBitstream(bool* bitstream, uint8_t userid, bool readProtect);
@@ -496,6 +499,11 @@ class Greenpak4Device
@brief Number of times to attempt re-reading NVM in case of boot failure
*/
int m_nvmLoadRetryCount;

/**
@brief True if we have static timing data
*/
bool m_hasTimingData;
};

#endif

0 comments on commit 48edca9

Please sign in to comment.