Skip to content

Commit

Permalink
Now measuring I/O buffer delays across voltage corners (for 3.3V nomi…
Browse files Browse the repository at this point in the history
…nal range only)
azonenberg committed Jun 3, 2017
1 parent 13ed97b commit dfd9ea1
Showing 4 changed files with 124 additions and 86 deletions.
4 changes: 2 additions & 2 deletions src/gp4tchar/gp4tchar.h
Original file line number Diff line number Diff line change
@@ -30,10 +30,10 @@
#include "TimingData.h"

bool InitializeHardware(hdevice hdev, SilegoPart expectedPart);
bool PostProgramSetup(hdevice hdev);
bool PostProgramSetup(hdevice hdev, int voltage_mv = 3300);
bool IOReset(hdevice hdev);
bool IOSetup(hdevice hdev);
bool PowerSetup(hdevice hdev);
bool PowerSetup(hdevice hdev, int voltage_mv = 3300);

bool ReadTraceDelays();
bool CalibrateTraceDelays(Socket& sock, hdevice hdev);
16 changes: 9 additions & 7 deletions src/gp4tchar/main.cpp
Original file line number Diff line number Diff line change
@@ -123,15 +123,17 @@ 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;
*/
//if(!MeasureCrossConnectionDelays(sock, hdev))
// return 1;
//if(!MeasureLutDelays(sock, hdev))
// return 1;

//Print output
g_calDevice.PrintTimingData();
LogDebug("Dumping timing data...\n");
{
LogIndenter li;
g_calDevice.PrintTimingData();
}

//Done
LogNotice("Done, resetting board\n");
174 changes: 103 additions & 71 deletions src/gp4tchar/measurements.cpp
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ Greenpak4IOB::PullStrength unused_drive = Greenpak4IOB::PULL_1M;
Greenpak4Device g_calDevice(part, unused_pull, unused_drive);

bool PromptAndMeasureDelay(Socket& sock, int src, int dst, float& value);

bool MeasureCrossConnectionDelay(
Socket& sock,
hdevice hdev,
@@ -52,6 +53,7 @@ bool MeasurePinToPinDelay(
int dst,
Greenpak4IOB::DriveStrength drive,
bool schmitt,
int voltage_mv,
float& delay);

bool ProgramAndMeasureDelay(
@@ -60,8 +62,13 @@ bool ProgramAndMeasureDelay(
vector<uint8_t>& bitstream,
int src,
int dst,
int voltage_mv,
float& delay);

//Voltages to test at
//For now, 3.3 +/- 150 mV
const int g_testVoltages[] = {3150, 3300, 3450};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Initial measurement calibration

@@ -229,13 +236,20 @@ bool MeasureDelay(Socket& sock, int src, int dst, float& delay)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Load the bitstream onto the device and measure a pin-to-pin delay

bool ProgramAndMeasureDelay(Socket& sock, hdevice hdev, vector<uint8_t>& bitstream, int src, int dst, float& delay)
bool ProgramAndMeasureDelay(
Socket& sock,
hdevice hdev,
vector<uint8_t>& bitstream,
int src,
int dst,
int voltage_mv,
float& delay)
{
//Emulate the device
LogVerbose("Loading new bitstream\n");
if(!DownloadBitstream(hdev, bitstream, DownloadMode::EMULATION))
return false;
if(!PostProgramSetup(hdev))
if(!PostProgramSetup(hdev, voltage_mv))
return false;

usleep (1000 * 10);
@@ -268,9 +282,6 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)

int pins[] = {3, 4, 5, 13, 14, 15};

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

//TODO: ↓ edges
//TODO: x4 drive (if supported on this pin)
//TODO: Tri-states and open-drain/open-source outputs
@@ -290,53 +301,69 @@ bool MeasurePinToPinDelays(Socket& sock, hdevice hdev)
if(src > 10 && dst < 10)
continue;

//Create some variables
EquationVariable ibuf("Input buffer delay");
EquationVariable obuf_x1("x1 Output buffer delay");
EquationVariable obuf_x2("x2 Output buffer delay");
EquationVariable schmitt("Schmitt trigger 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(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(obuf_x1);

if(!MeasurePinToPinDelay(sock, hdev, src, dst, Greenpak4IOB::DRIVE_2X, false, delay))
return false;
Equation e3(delay);
e3.AddVariable(ibuf);
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(obuf_x2);

//Create and solve the equation system
EquationSystem sys;
sys.AddEquation(e1);
sys.AddEquation(e2);
sys.AddEquation(e3);
sys.AddEquation(e4);
if(!sys.Solve())
return false;

//Save combinatorial delays for these pins
auto iob = g_calDevice.GetIOB(src);
iob->AddCombinatorialDelay("IO", "OUT", corner, CombinatorialDelay(ibuf.m_value, -1));
iob->SetSchmittTriggerDelay(corner, CombinatorialDelay(schmitt.m_value, -1));
iob->SetOutputDelay(Greenpak4IOB::DRIVE_1X, corner, CombinatorialDelay(obuf_x1.m_value, -1));
iob->SetOutputDelay(Greenpak4IOB::DRIVE_2X, corner, CombinatorialDelay(obuf_x2.m_value, -1));
//Try various voltages
for(auto voltage : g_testVoltages)
{
//Test conditions (TODO: pass this in from somewhere?)
PTVCorner corner(PTVCorner::SPEED_TYPICAL, 25, voltage);

//Create some variables
EquationVariable ibuf("Input buffer delay");
EquationVariable obuf_x1("x1 output buffer delay");
EquationVariable obuf_x2("x2 output buffer delay");
EquationVariable schmitt("Schmitt trigger 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(obuf_x2, -1.55);

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

if(!MeasurePinToPinDelay(sock, hdev, src, dst,
Greenpak4IOB::DRIVE_2X, false, corner.GetVoltage(), delay))
{
return false;
}
Equation e3(delay);
e3.AddVariable(ibuf);
e3.AddVariable(obuf_x2);

if(!MeasurePinToPinDelay(sock, hdev, src, dst,
Greenpak4IOB::DRIVE_2X, true, corner.GetVoltage(), delay))
{
return false;
}
Equation e4(delay);
e4.AddVariable(ibuf);
e4.AddVariable(schmitt);
e4.AddVariable(obuf_x2);

//Create and solve the equation system
EquationSystem sys;
sys.AddEquation(e1);
sys.AddEquation(e2);
sys.AddEquation(e3);
sys.AddEquation(e4);
if(!sys.Solve())
return false;

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

@@ -353,6 +380,7 @@ bool MeasurePinToPinDelay(
int dst,
Greenpak4IOB::DriveStrength drive,
bool schmitt,
int voltage_mv,
float& delay)
{
delay = -1;
@@ -385,7 +413,7 @@ bool MeasurePinToPinDelay(
//device.WriteToFile("/tmp/test.txt", 0, false); //for debug in case of failure

//Get the delay
if(!ProgramAndMeasureDelay(sock, hdev, bitstream, src, dst, delay))
if(!ProgramAndMeasureDelay(sock, hdev, bitstream, src, dst, voltage_mv, delay))
return false;

//Subtract the PCB trace delay at each end of the line
@@ -403,23 +431,27 @@ 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++)
//Try various voltages
for(auto voltage : g_testVoltages)
{
if(!MeasureCrossConnectionDelay(sock, hdev, 0, i, 3, 13, corner, d))
return false;
g_calDevice.GetCrossConnection(0, i)->AddCombinatorialDelay("I", "O", corner, CombinatorialDelay(d, -1));
}
//Test conditions (TODO: pass this in from somewhere?)
PTVCorner corner(PTVCorner::SPEED_TYPICAL, 25, voltage);

for(int i=0; i<10; i++)
{
if(!MeasureCrossConnectionDelay(sock, hdev, 1, i, 13, 3, corner, d))
return false;
g_calDevice.GetCrossConnection(1, i)->AddCombinatorialDelay("I", "O", corner, CombinatorialDelay(d, -1));
//East
float d;
for(int i=0; i<10; 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++)
{
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;
@@ -468,7 +500,7 @@ bool MeasureCrossConnectionDelay(
//device.WriteToFile("/tmp/test.txt", 0, false); //for debug in case of failure

//Get the delay
if(!ProgramAndMeasureDelay(sock, hdev, bitstream, src, dst, delay))
if(!ProgramAndMeasureDelay(sock, hdev, bitstream, src, dst, corner.GetVoltage(), delay))
return false;

//Subtract the PCB trace delay at each end of the line
@@ -499,8 +531,8 @@ bool MeasureCrossConnectionDelay(

bool MeasureLutDelays(Socket& /*sock*/, hdevice /*hdev*/)
{
//LogNotice("Measuring LUT delays...\n");
//LogIndenter li;
LogNotice("Measuring LUT delays...\n");
LogIndenter li;
return true;
}

16 changes: 10 additions & 6 deletions src/gp4tchar/setup.cpp
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ using namespace std;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Board initialization

bool PostProgramSetup(hdevice hdev)
bool PostProgramSetup(hdevice hdev, int voltage_mv)
{
//Clear I/Os from programming mode
if(!IOReset(hdev))
@@ -32,7 +32,7 @@ bool PostProgramSetup(hdevice hdev)
//Load the new configuration
if(!IOSetup(hdev))
return false;
if(!PowerSetup(hdev))
if(!PowerSetup(hdev, voltage_mv))
return false;

return true;
@@ -71,11 +71,15 @@ bool IOSetup(hdevice hdev)
return true;
}

bool PowerSetup(hdevice hdev)
bool PowerSetup(hdevice hdev, int voltage_mv)
{
//Do not change this voltage! This is what the FPGA uses
//TODO: sweep from 3.15 to 3.45 to do voltage corner analysis
float voltage = 3.3;
float voltage = voltage_mv * 0.001f;
if(voltage > 3.455)
{
LogError("Tried to set voltage to %.3f mV, disallowing for FPGA safety\n", voltage);
return false;
}

return ConfigureSiggen(hdev, 1, voltage);
}

0 comments on commit dfd9ea1

Please sign in to comment.