Skip to content

Commit

Permalink
Now characterizing IOBs and cross-connectors and saving delay values …
Browse files Browse the repository at this point in the history
…in the object. Still no serialization
azonenberg committed Jun 3, 2017
1 parent 1e2ebe3 commit 13ed97b
Showing 6 changed files with 104 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/gp4tchar/main.cpp
Original file line number Diff line number Diff line change
@@ -123,9 +123,9 @@ int main(int argc, char* argv[])
//Measure delay through each element
if(!MeasurePinToPinDelays(sock, hdev))
return 1;
/*
if(!MeasureCrossConnectionDelays(sock, hdev))
return 1;
/*
if(!MeasureLutDelays(sock, hdev))
return 1;
*/
79 changes: 36 additions & 43 deletions src/gp4tchar/measurements.cpp
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ bool MeasureCrossConnectionDelay(
unsigned int index,
unsigned int src,
unsigned int dst,
PTVCorner corner,
float& delay);

bool MeasurePinToPinDelay(
@@ -262,7 +263,7 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)
Output buffer delay: 1.8 ns, plus 1 ns for LVCMOS33 = 2.8 ns
Slow-slew output: 4 ns
Extrapolation: input buffer delay = 0.6 * Schmitt trigger delay
Extrapolation: input buffer delay = 1.55x output buffer delay
*/

int pins[] = {3, 4, 5, 13, 14, 15};
@@ -272,6 +273,7 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)

//TODO: ↓ edges
//TODO: x4 drive (if supported on this pin)
//TODO: Tri-states and open-drain/open-source outputs
float delay;
for(auto src : pins)
{
@@ -290,38 +292,35 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)

//Create some variables
EquationVariable ibuf("Input buffer delay");
EquationVariable obuf("Output buffer delay");
EquationVariable obuf_x1("x1 Output buffer delay");
EquationVariable obuf_x2("x2 Output buffer delay");
EquationVariable schmitt("Schmitt trigger delay");
EquationVariable route("Crossbar delay");

//Set up relationships between the various signals (see assumptions above)
//TODO: FIB probing to get more accurate parameters here
Equation e1(0);
e1.AddVariable(ibuf, 1);
e1.AddVariable(schmitt, -0.6);
e1.AddVariable(obuf_x2, -1.55);

//Gather data from the DUT
if(!MeasurePinToPinDelay(sock, hdev, src, dst, Greenpak4IOB::DRIVE_1X, false, delay))
return false;
Equation e2(delay);
e2.AddVariable(ibuf);
e2.AddVariable(route);
e2.AddVariable(obuf);
e2.AddVariable(obuf_x1);

if(!MeasurePinToPinDelay(sock, hdev, src, dst, Greenpak4IOB::DRIVE_2X, false, delay))
return false;
Equation e3(delay);
e3.AddVariable(ibuf);
e3.AddVariable(route);
e3.AddVariable(obuf, 0.5);
e3.AddVariable(obuf_x2);

if(!MeasurePinToPinDelay(sock, hdev, src, dst, Greenpak4IOB::DRIVE_2X, true, delay))
return false;
Equation e4(delay);
e4.AddVariable(ibuf);
e4.AddVariable(schmitt);
e4.AddVariable(route);
e4.AddVariable(obuf, 0.5);
e4.AddVariable(obuf_x2);

//Create and solve the equation system
EquationSystem sys;
@@ -332,27 +331,12 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)
if(!sys.Solve())
return false;

/*
LogNotice("| %4d | %2d | %6.3f | %8.3f | %8.3f | %9.3f | %8.3f |\n",
src,
dst,
ibuf.m_value,
obuf.m_value,
obuf.m_value/2,
schmitt.m_value,
route.m_value
);
*/

//Save combinatorial delays for these pins
auto iob = g_calDevice.GetIOB(src);
iob->AddCombinatorialDelay("IO", "OUT", corner, CombinatorialDelay(ibuf.m_value, -1));
//iob->AddCombinatorialDelay("IN", "IO", corner, CombinatorialDelay(obuf.m_value, -1));
iob->SetSchmittTriggerDelay(corner, CombinatorialDelay(schmitt.m_value, -1));
iob->SetOutputDelay(Greenpak4IOB::DRIVE_1X, corner, CombinatorialDelay(obuf.m_value, -1));
iob->SetOutputDelay(Greenpak4IOB::DRIVE_2X, corner, CombinatorialDelay(obuf.m_value/2, -1));

//TODO: route.m_value goes somewhere
iob->SetOutputDelay(Greenpak4IOB::DRIVE_1X, corner, CombinatorialDelay(obuf_x1.m_value, -1));
iob->SetOutputDelay(Greenpak4IOB::DRIVE_2X, corner, CombinatorialDelay(obuf_x2.m_value, -1));
}
}

@@ -419,21 +403,23 @@ bool MeasureCrossConnectionDelays(Socket& sock, hdevice hdev)
LogNotice("Measuring cross-connection delays...\n");
LogIndenter li;

//Test conditions (TODO: pass this in from somewhere?)
PTVCorner corner(PTVCorner::SPEED_TYPICAL, 25, 3300);

//East
float d;
for(int i=0; i<10; i++)
{
//east
MeasureCrossConnectionDelay(sock, hdev, 0, i, 3, 13, d);
LogNotice("East cross-connection %d from pins 3 to 13: %.3f\n", i, d);

//g_calDevice.GetCrossConnection(0, i,
if(!MeasureCrossConnectionDelay(sock, hdev, 0, i, 3, 13, corner, d))
return false;
g_calDevice.GetCrossConnection(0, i)->AddCombinatorialDelay("I", "O", corner, CombinatorialDelay(d, -1));
}

for(int i=0; i<10; i++)
{
//west
MeasureCrossConnectionDelay(sock, hdev, 1, i, 13, 3, d);
LogNotice("West cross-connection %d from pins 13 to 3: %.3f\n", i, d);
if(!MeasureCrossConnectionDelay(sock, hdev, 1, i, 13, 3, corner, d))
return false;
g_calDevice.GetCrossConnection(1, i)->AddCombinatorialDelay("I", "O", corner, CombinatorialDelay(d, -1));
}

return true;
@@ -446,6 +432,7 @@ bool MeasureCrossConnectionDelay(
unsigned int index,
unsigned int src,
unsigned int dst,
PTVCorner corner,
float& delay)
{
delay = -1;
@@ -487,18 +474,24 @@ bool MeasureCrossConnectionDelay(
//Subtract the PCB trace delay at each end of the line
delay -= g_devkitCal.pinDelays[src].m_rising;
delay -= g_devkitCal.pinDelays[dst].m_rising;
return true;

/*
delay = -1;
//Subtract the I/O buffer delay at each end of the line
//TODO: import calibration from the Greenpak4Device and/or reset it?
CombinatorialDelay d;
srciob = g_calDevice.GetIOB(src);
srciob->SetSchmittTrigger(false);
if(!srciob->GetCombinatorialDelay("IO", "OUT", corner, d))
return false;
delay -= d.m_rising;

//Create the device
dstiob = g_calDevice.GetIOB(dst);
dstiob->SetDriveType(Greenpak4IOB::DRIVE_PUSHPULL);
dstiob->SetDriveStrength(Greenpak4IOB::DRIVE_2X);
if(!dstiob->GetCombinatorialDelay("IN", "IO", corner, d))
return false;
delay -= d.m_rising;

//Done
string dir = (matrix == 0) ? "east" : "west";
LogNotice("%s %d: %.3f ns\n", dir.c_str(), index, delay);
return true;
*/
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8 changes: 8 additions & 0 deletions src/greenpak4/Greenpak4BitstreamEntity.cpp
Original file line number Diff line number Diff line change
@@ -238,14 +238,22 @@ bool Greenpak4BitstreamEntity::GetCombinatorialDelay(
//If this isn't a corner we know about, give up
auto pit = m_pinToPinDelays.find(corner);
if(pit == m_pinToPinDelays.end())
{
LogWarning("Greenpak4BitstreamEntity::GetCombinatorialDelay: no delay for process corner %s\n",
corner.toString().c_str());
return false;
}

//If we don't have data for this pin pair, give up
PinPair pair(srcport, dstport);
auto& dmap = pit->second;
auto dit = dmap.find(pair);
if(dit == dmap.end())
{
LogWarning("Greenpak4BitstreamEntity::GetCombinatorialDelay: no delay for path %s to %s\n",
srcport.c_str(), dstport.c_str());
return false;
}

//Got it
delay = dit->second;
42 changes: 40 additions & 2 deletions src/greenpak4/Greenpak4IOB.cpp
Original file line number Diff line number Diff line change
@@ -258,8 +258,8 @@ void Greenpak4IOB::PrintExtraTimingData(PTVCorner corner) const
if(GetCombinatorialDelay("IO", "OUT", corner, bd))
{
LogNotice("%10s to %10s: %.3f ns rising, %.3f ns falling\n",
"IO",
"OUT (Sch)",
"IO (Sch)",
"OUT",
time.m_rising + bd.m_rising,
time.m_falling + bd.m_falling);
}
@@ -304,6 +304,44 @@ bool Greenpak4IOB::GetCombinatorialDelay(
PTVCorner corner,
CombinatorialDelay& delay) const
{
//INPUT path: enable Schmitt trigger if needed
if( (srcport == "IO") && (dstport == "OUT") )
{
//Get the baseline IO to OUT delay from the base class
if(!Greenpak4BitstreamEntity::GetCombinatorialDelay(srcport, dstport, corner, delay))
{
LogWarning("Greenpak4IOB::GetCombinatorialDelay: no delay for process corner %s\n",
corner.toString().c_str());
return false;
}

//Add Schmitt trigger delay if needed
if(m_schmittTrigger)
{
auto it = m_schmittTriggerDelays.find(corner);
if(it == m_schmittTriggerDelays.end())
return false;
delay += it->second;
}
return true;
}

//OUTPUT path: look up drive strength
else if( (srcport == "IN") && (dstport == "IO") )
{
auto it = m_outputDelays.find(DriveCondition(m_driveStrength, corner));
if(it == m_outputDelays.end())
{
LogWarning("Greenpak4IOB::GetCombinatorialDelay: no delay for drive condition (strength=%d, corner=%s)\n",
m_driveStrength,
corner.toString().c_str());
return false;
}

delay = it->second;
return true;
}

//Default: return base class info
return Greenpak4BitstreamEntity::GetCombinatorialDelay(srcport, dstport, corner, delay);
}
1 change: 1 addition & 0 deletions src/greenpak4/Greenpak4IOB.h
Original file line number Diff line number Diff line change
@@ -149,6 +149,7 @@ class Greenpak4IOB : public Greenpak4BitstreamEntity
void SetSchmittTriggerDelay(PTVCorner c, CombinatorialDelay d)
{ m_schmittTriggerDelays[c] = d; }

//TODO: drive type should go in here too?
typedef std::pair<DriveStrength, PTVCorner> DriveCondition;

void SetOutputDelay(DriveStrength s, PTVCorner c, CombinatorialDelay d)
18 changes: 18 additions & 0 deletions src/xbpar/CombinatorialDelay.h
Original file line number Diff line number Diff line change
@@ -32,6 +32,24 @@ class CombinatorialDelay

float m_rising;
float m_falling;

//Delay adding
CombinatorialDelay operator+(const CombinatorialDelay& rhs) const
{ return CombinatorialDelay(m_rising + rhs.m_rising, m_falling + rhs.m_falling); }

CombinatorialDelay& operator=(const CombinatorialDelay& rhs)
{
m_rising = rhs.m_rising;
m_falling = rhs.m_falling;
return *this;
}

CombinatorialDelay& operator+=(const CombinatorialDelay& rhs)
{
m_rising += rhs.m_rising;
m_falling += rhs.m_falling;
return *this;
}
};

#endif

0 comments on commit 13ed97b

Please sign in to comment.