Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: azonenberg/openfpga
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: daa9f7d987d2
Choose a base ref
...
head repository: azonenberg/openfpga
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8a4cc7048640
Choose a head ref
  • 2 commits
  • 67 files changed
  • 1 contributor

Commits on Jun 7, 2017

  1. Updated to latest xptools

    azonenberg committed Jun 7, 2017
    Copy the full SHA
    21a9004 View commit details
  2. Added GetInput() to all BitstreamEntity-derived classes. Began work o…

    …n post-PAR static timing.
    azonenberg committed Jun 7, 2017
    Copy the full SHA
    8a4cc70 View commit details
Showing with 639 additions and 17 deletions.
  1. +4 −1 src/gp4par/gp4par.h
  2. +9 −5 src/gp4par/main.cpp
  3. +1 −0 src/gp4par/par_main.cpp
  4. +276 −1 src/gp4par/par_reporting.cpp
  5. +8 −0 src/greenpak4/Greenpak4Abuf.cpp
  6. +1 −0 src/greenpak4/Greenpak4Abuf.h
  7. +6 −0 src/greenpak4/Greenpak4Bandgap.cpp
  8. +1 −0 src/greenpak4/Greenpak4Bandgap.h
  9. +4 −4 src/greenpak4/Greenpak4BitstreamEntity.cpp
  10. +5 −0 src/greenpak4/Greenpak4BitstreamEntity.h
  11. +8 −0 src/greenpak4/Greenpak4ClockBuffer.cpp
  12. +1 −0 src/greenpak4/Greenpak4ClockBuffer.h
  13. +12 −0 src/greenpak4/Greenpak4Comparator.cpp
  14. +1 −0 src/greenpak4/Greenpak4Comparator.h
  15. +14 −0 src/greenpak4/Greenpak4Counter.cpp
  16. +1 −0 src/greenpak4/Greenpak4Counter.h
  17. +8 −0 src/greenpak4/Greenpak4CrossConnection.cpp
  18. +4 −0 src/greenpak4/Greenpak4CrossConnection.h
  19. +23 −0 src/greenpak4/Greenpak4DAC.cpp
  20. +1 −0 src/greenpak4/Greenpak4DAC.h
  21. +10 −0 src/greenpak4/Greenpak4DCMPMux.cpp
  22. +1 −0 src/greenpak4/Greenpak4DCMPMux.h
  23. +6 −0 src/greenpak4/Greenpak4DCMPRef.cpp
  24. +1 −0 src/greenpak4/Greenpak4DCMPRef.h
  25. +8 −0 src/greenpak4/Greenpak4Delay.cpp
  26. +1 −0 src/greenpak4/Greenpak4Delay.h
  27. +28 −0 src/greenpak4/Greenpak4DigitalComparator.cpp
  28. +1 −0 src/greenpak4/Greenpak4DigitalComparator.h
  29. +5 −0 src/greenpak4/Greenpak4DualEntity.cpp
  30. +1 −0 src/greenpak4/Greenpak4DualEntity.h
  31. +12 −0 src/greenpak4/Greenpak4Flipflop.cpp
  32. +1 −0 src/greenpak4/Greenpak4Flipflop.h
  33. +15 −5 src/greenpak4/Greenpak4IOB.cpp
  34. +1 −0 src/greenpak4/Greenpak4IOB.h
  35. +8 −0 src/greenpak4/Greenpak4Inverter.cpp
  36. +1 −0 src/greenpak4/Greenpak4Inverter.h
  37. +8 −0 src/greenpak4/Greenpak4LFOscillator.cpp
  38. +1 −0 src/greenpak4/Greenpak4LFOscillator.h
  39. +14 −0 src/greenpak4/Greenpak4LUT.cpp
  40. +1 −0 src/greenpak4/Greenpak4LUT.h
  41. +8 −0 src/greenpak4/Greenpak4NetlistCell.h
  42. +12 −0 src/greenpak4/Greenpak4PGA.cpp
  43. +1 −0 src/greenpak4/Greenpak4PGA.h
  44. +5 −0 src/greenpak4/Greenpak4PairedEntity.cpp
  45. +1 −0 src/greenpak4/Greenpak4PairedEntity.h
  46. +10 −0 src/greenpak4/Greenpak4PatternGenerator.cpp
  47. +1 −0 src/greenpak4/Greenpak4PatternGenerator.h
  48. +6 −0 src/greenpak4/Greenpak4PowerDetector.cpp
  49. +1 −0 src/greenpak4/Greenpak4PowerDetector.h
  50. +6 −0 src/greenpak4/Greenpak4PowerOnReset.cpp
  51. +1 −0 src/greenpak4/Greenpak4PowerOnReset.h
  52. +6 −0 src/greenpak4/Greenpak4PowerRail.cpp
  53. +1 −0 src/greenpak4/Greenpak4PowerRail.h
  54. +8 −0 src/greenpak4/Greenpak4RCOscillator.cpp
  55. +1 −0 src/greenpak4/Greenpak4RCOscillator.h
  56. +8 −0 src/greenpak4/Greenpak4RingOscillator.cpp
  57. +1 −0 src/greenpak4/Greenpak4RingOscillator.h
  58. +8 −0 src/greenpak4/Greenpak4SPI.cpp
  59. +1 −0 src/greenpak4/Greenpak4SPI.h
  60. +12 −0 src/greenpak4/Greenpak4ShiftRegister.cpp
  61. +1 −0 src/greenpak4/Greenpak4ShiftRegister.h
  62. +8 −0 src/greenpak4/Greenpak4SystemReset.cpp
  63. +1 −0 src/greenpak4/Greenpak4SystemReset.h
  64. +8 −0 src/greenpak4/Greenpak4VoltageReference.cpp
  65. +1 −0 src/greenpak4/Greenpak4VoltageReference.h
  66. +9 −0 src/xbpar/CombinatorialDelay.h
  67. +1 −1 src/xptools
5 changes: 4 additions & 1 deletion src/gp4par/gp4par.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***********************************************************************************************************************
* Copyright (C) 2016 Andrew Zonenberg and contributors *
* Copyright (C) 2016-2017 Andrew Zonenberg and contributors *
* *
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General *
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) *
@@ -58,7 +58,10 @@ bool PostPARDRC(PARGraph* netlist, Greenpak4Device* device);
//Committing
bool CommitChanges(PARGraph* device, Greenpak4Device* pdev, unsigned int* num_routes_used);
bool CommitRouting(PARGraph* device, Greenpak4Device* pdev, unsigned int* num_routes_used);

//Reporting
void PrintUtilizationReport(PARGraph* netlist, Greenpak4Device* device, unsigned int* num_routes_used);
void PrintPlacementReport(PARGraph* netlist, Greenpak4Device* device);
void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device);

#endif
14 changes: 9 additions & 5 deletions src/gp4par/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***********************************************************************************************************************
* Copyright (C) 2016 Andrew Zonenberg and contributors *
* Copyright (C) 2016-2017 Andrew Zonenberg and contributors *
* *
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General *
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) *
@@ -385,8 +385,15 @@ int main(int argc, char* argv[])
device.SetLDOBypass(ldoBypass);
device.SetNVMRetryCount(bootRetry);

//Attempt to load the timing data file, if present
//FIXME: get this from a sane location and make it chip specific
string tfname = "../../../timing.json";
LogNotice("\nLoading timing data file \"%s\"\n", tfname.c_str());
if(!device.LoadTimingData(tfname))
LogWarning("Timing data file not found, unable to do timing-driven placement or evaluate post-PAR timing\n");

//Do the actual P&R
LogNotice("\nSynthesizing top-level module \"%s\".\n", netlist.GetTopModule()->GetName().c_str());
LogNotice("\nImplementing top-level module \"%s\".\n", netlist.GetTopModule()->GetName().c_str());
if(!DoPAR(&netlist, &device))
return 1;

@@ -399,9 +406,6 @@ int main(int argc, char* argv[])
return 1;
}

//TODO: Static timing analysis
LogNotice("\nStatic timing analysis: not yet implemented\n");

return 0;
}

1 change: 1 addition & 0 deletions src/gp4par/par_main.cpp
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ bool DoPAR(Greenpak4Netlist* netlist, Greenpak4Device* device)
//Print reports
PrintUtilizationReport(ngraph, device, num_routes_used);
PrintPlacementReport(ngraph, device);
PrintTimingReport(netlist, device);

//Final cleanup
delete ngraph;
277 changes: 276 additions & 1 deletion src/gp4par/par_reporting.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***********************************************************************************************************************
* Copyright (C) 2016 Andrew Zonenberg and contributors *
* Copyright (C) 2016-2017 Andrew Zonenberg and contributors *
* *
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General *
* Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) *
@@ -20,6 +20,19 @@

using namespace std;

typedef vector<const PARGraphEdge*> CombinatorialPath;

void FindCombinatorialPaths(
const set<Greenpak4NetlistCell*>& sources,
const set<Greenpak4NetlistCell*>& sinks,
set<CombinatorialPath>& paths);

void FindCombinatorialPaths(
const set<Greenpak4NetlistCell*>& sinks,
CombinatorialPath basepath,
const PARGraphEdge* tip,
set<CombinatorialPath>& paths);

static void PrintRow(string kind, int used, int total)
{
if(total == 0)
@@ -226,3 +239,265 @@ void PrintPlacementReport(PARGraph* netlist, Greenpak4Device* /*device*/)

LogVerbose("+----------------------------------------------------+-----------------+\n");
}

/**
@brief Prints the post-PAR static timing analysis
TODO: Refactor this into Greenpak4PAREngine?
*/
void PrintTimingReport(Greenpak4Netlist* netlist, Greenpak4Device* device)
{
LogNotice("\nTiming report:\n");
LogIndenter li;

//Find all nodes in the design that can begin a combinatorial path
//This is only input buffers for now, but eventually will include DFFs and other stateful blocks
set<Greenpak4NetlistCell*> sources;
auto module = netlist->GetTopModule();
for(auto it = module->cell_begin(); it != module->cell_end(); it++)
{
auto cell = it->second;

//TODO: check stateful internal blocks too
if(!cell->IsIbuf())
continue;
sources.emplace(cell);
}

//Find all nodes in the design that can end a combinatorial path
//This is only output buffers for now, but eventually will include DFFs and other stateful blocks
set<Greenpak4NetlistCell*> sinks;
for(auto it = module->cell_begin(); it != module->cell_end(); it++)
{
auto cell = it->second;

//TODO: check stateful internal blocks too
if(!cell->IsObuf())
continue;
sinks.emplace(cell);
}

//Find all combinatorial paths in the design.
set<CombinatorialPath> paths;
FindCombinatorialPaths(sources, sinks, paths);

//The corner we're testing at (TODO multi-corner)
PTVCorner corner(PTVCorner::SPEED_TYPICAL, 25, 3300);
LogVerbose("Running static timing for %s\n", corner.toString().c_str());

//DEBUG: print all paths
int i=0;
for(auto path : paths)
{
LogVerbose("Path %d\n", i++);
LogIndenter li;
LogVerbose(
"+--------------------------------------------------------------+------------+-----------"
"+------------+------------+------------+\n");
LogVerbose("| %60s | %10s | %10s| %10s | %10s | %10s |\n",
"Instance",
"Site",
"SrcPort",
"DstPort",
"Delay",
"Cumulative"
);
LogVerbose(
"+--------------------------------------------------------------+------------+-----------"
"+------------+------------+------------+\n");

float cdelay = 0;

//TODO: figure this out for DFFs etc
string previous_port = "IO";

for(auto edge : path)
{
auto src = static_cast<Greenpak4NetlistEntity*>(edge->m_sourcenode->GetData());
auto srccell = static_cast<Greenpak4BitstreamEntity*>(edge->m_sourcenode->GetMate()->GetData());
auto dst = static_cast<Greenpak4NetlistEntity*>(edge->m_destnode->GetData());
auto dstcell = static_cast<Greenpak4BitstreamEntity*>(edge->m_destnode->GetMate()->GetData());

//If the source is an input buffer, add a delay for that
auto sncell = dynamic_cast<Greenpak4NetlistCell*>(src);
if(sncell->IsIbuf())
{
//Look up the delay
CombinatorialDelay delay;
if(!srccell->GetCombinatorialDelay(previous_port, edge->m_sourceport, corner, delay))
{
//DEBUG: use data from other pins if we haven't characterized this one yet!!!
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);
}
}

float worst = delay.GetWorst();
cdelay += worst;

LogVerbose("| %60s | %10s | %10s| %10s | %10.3f | %10.3f |\n",
src->m_name.c_str(),
srccell->GetDescription().c_str(),
previous_port.c_str(),
edge->m_sourceport.c_str(),
worst,
cdelay
);

//Done, save the old source
previous_port = edge->m_destport;
continue;
}

//Cell delay
CombinatorialDelay delay;
if(!srccell->GetCombinatorialDelay(previous_port, edge->m_sourceport, corner, delay))
{
LogWarning("Couldn't get timing data\n");
delay = CombinatorialDelay(0, 0);
}
float worst = delay.GetWorst();
cdelay += worst;

LogVerbose("| %60s | %10s | %10s| %10s | %10.3f | %10.3f |\n",
src->m_name.c_str(),
srccell->GetDescription().c_str(),
previous_port.c_str(),
edge->m_sourceport.c_str(),
worst,
cdelay
);

//Done, save the old source
previous_port = edge->m_destport;

//See if we used a cross-connection on the next hop
auto dsrc = dstcell->GetInput(edge->m_destport);
auto xc = dynamic_cast<Greenpak4CrossConnection*>(dsrc.GetRealEntity());
if(xc)
{
if(!xc->GetCombinatorialDelay("I", "O", corner, delay))
{
LogWarning("Couldn't get timing data\n");
delay = CombinatorialDelay(0, 0);
}
float worst = delay.GetWorst();
cdelay += worst;

LogVerbose("| %60s | %10s | %10s| %10s | %10.3f | %10.3f |\n",
"__routing__",
xc->GetDescription().c_str(),
"I",
"O",
worst,
cdelay
);
}

//If the destination is an output buffer, add that path
auto dncell = dynamic_cast<Greenpak4NetlistCell*>(dst);
if(dncell->IsObuf())
{
//Look up the delay
CombinatorialDelay delay;

if(!dstcell->GetCombinatorialDelay(edge->m_destport, "IO", corner, delay))
{
//DEBUG: use data from other pins if we haven't characterized this one yet!!!
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);
}
}

float worst = delay.GetWorst();
cdelay += worst;

LogVerbose("| %60s | %10s | %10s| %10s | %10.3f | %10.3f |\n",
dst->m_name.c_str(),
dstcell->GetDescription().c_str(),
edge->m_destport.c_str(),
"IO",
worst,
cdelay
);
}
}
LogVerbose(
"+--------------------------------------------------------------+------------+-----------"
"+------------+------------+------------+\n");
}
}

/**
@brief Go over all cells in the netlist and DFS until we find all paths from source to sink nodes
Source: input buffer or stateful element
Sink: output buffer or stateful element
We don't care about the timing of these paths yet, these are just all of the paths to consider
*/
void FindCombinatorialPaths(
const set<Greenpak4NetlistCell*>& sources,
const set<Greenpak4NetlistCell*>& sinks,
set<CombinatorialPath>& paths)
{
//Find all edges leaving all source nodes
for(auto cell : sources)
{
auto srcnode = cell->m_parnode;
for(uint32_t i=0; i<srcnode->GetEdgeCount(); i++)
{
auto edge = srcnode->GetEdgeByIndex(i);
//LogDebug("Edge: %s - %s\n", edge->m_sourceport.c_str(), edge->m_destport.c_str());

//Find all paths that begin with this edge
CombinatorialPath path;
path.push_back(edge);
FindCombinatorialPaths(sinks, path, edge, paths);
}
}
}

/**
@brief Recursively search out from a given path
*/
void FindCombinatorialPaths(
const set<Greenpak4NetlistCell*>& sinks,
CombinatorialPath basepath,
const PARGraphEdge* tip,
set<CombinatorialPath>& paths)
{
//Jump through some hoops to see where this edge ends
auto destnode = tip->m_destnode;
auto destent = static_cast<Greenpak4NetlistEntity*>(destnode->GetData());
auto destcell = dynamic_cast<Greenpak4NetlistCell*>(destent);
if(!destcell)
{
LogWarning("Dest node is not cell\n");
return;
}

//If it ends at a sink node, that's the end of this path
if(sinks.find(destcell) != sinks.end())
{
paths.emplace(basepath);
return;
}

//Nope, this node is not the end. Search all outbound edges from it
for(uint32_t i=0; i<destnode->GetEdgeCount(); i++)
{
auto edge = destnode->GetEdgeByIndex(i);

//Find all paths that begin with the new, longer path
CombinatorialPath npath = basepath;
npath.push_back(edge);
FindCombinatorialPaths(sinks, npath, edge, paths);
}
}
8 changes: 8 additions & 0 deletions src/greenpak4/Greenpak4Abuf.cpp
Original file line number Diff line number Diff line change
@@ -59,6 +59,14 @@ void Greenpak4Abuf::SetInput(string port, Greenpak4EntityOutput src)
//ignore anything else silently (should not be possible since synthesis would error out)
}

Greenpak4EntityOutput Greenpak4Abuf::GetInput(string port) const
{
if(port == "IN")
return m_input;
else
return Greenpak4EntityOutput(NULL);
}

vector<string> Greenpak4Abuf::GetOutputPorts() const
{
vector<string> r;
1 change: 1 addition & 0 deletions src/greenpak4/Greenpak4Abuf.h
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ class Greenpak4Abuf : public Greenpak4BitstreamEntity
virtual std::string GetDescription() const;

virtual void SetInput(std::string port, Greenpak4EntityOutput src);
virtual Greenpak4EntityOutput GetInput(std::string port) const;
virtual unsigned int GetOutputNetNumber(std::string port);

virtual std::vector<std::string> GetInputPorts() const;
6 changes: 6 additions & 0 deletions src/greenpak4/Greenpak4Bandgap.cpp
Original file line number Diff line number Diff line change
@@ -67,6 +67,12 @@ void Greenpak4Bandgap::SetInput(string /*port*/, Greenpak4EntityOutput /*src*/)
//no inputs
}

Greenpak4EntityOutput Greenpak4Bandgap::GetInput(string /*port*/) const
{
//no inputs
return Greenpak4EntityOutput(NULL);
}

vector<string> Greenpak4Bandgap::GetOutputPorts() const
{
vector<string> r;
1 change: 1 addition & 0 deletions src/greenpak4/Greenpak4Bandgap.h
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@ class Greenpak4Bandgap : public Greenpak4BitstreamEntity
virtual std::string GetDescription() const;

virtual void SetInput(std::string port, Greenpak4EntityOutput src);
virtual Greenpak4EntityOutput GetInput(std::string port) const;
virtual unsigned int GetOutputNetNumber(std::string port);

virtual std::vector<std::string> GetInputPorts() const;
Loading