Skip to content

Commit

Permalink
greenpak4: Added DRC checks for PGA pseudo-diff + DAC0 simultaneously…
Browse files Browse the repository at this point in the history
… enabled. Added workaround for static analysis false positive.
azonenberg committed Oct 15, 2016
1 parent ab41900 commit b7c2a22
Showing 7 changed files with 79 additions and 17 deletions.
29 changes: 18 additions & 11 deletions src/gp4par/par_main.cpp
Original file line number Diff line number Diff line change
@@ -269,44 +269,51 @@ bool PostPARDRC(PARGraph* netlist, Greenpak4Device* device)
if(!powerdowns.empty())
{
Greenpak4EntityOutput src = device->GetGround();
bool ok = true;
bool xok = true;
for(auto p : powerdowns)
{
if(src.IsPowerRail())
src = p.second;
if(src != p.second)
ok = false;
xok = false;
}

if(!ok)
if(!xok)
{
LogError(
"Multiple oscillators have power-down enabled, but do not share the same power-down signal\n");
for(auto p : powerdowns)
LogNotice(" Oscillator %10s powerdown is %s\n", p.first.c_str(), p.second.GetOutputName().c_str());

ok = false;
}
}

//If the PGA is used, we cannot use DAC1 (undocumented conflict, datasheet says nothing about this...)
//It appears that enabling the PGA turns on the ADC and causes DAC1 to emit a sawtooth waveform, regardless
//of whether there is any actual use of the ADC subsystem.
//ADC/DAC conflicts
if(device->GetPart() == Greenpak4Device::GREENPAK4_SLG46620)
{
//null check on pga is unnecessary for the 46620v, but necessary to avoid false positive from static analysis
auto dac1 = device->GetDAC(1);

if(pga->IsUsed() && dac1->IsUsed())
if(pga && pga->IsUsed() && dac1->IsUsed())
{
LogError(
"Both DAC1 and the PGA are used. This is illegal due to a poorly documented control hazard.\n"
"Enabling the PGA turns on the SAR ADC, forcing DAC1 to emit a sawtooth waveform instead of the "
"desired signal.\n");
ok = false;
}
}

//TODO: Cannot use DAC1 when ADC is used
//TODO: Cannot use DAC0 when ADC/PGA pseudo-diff mode is used
//null check to avoid false positive on static analysis
auto dac0 = device->GetDAC(0);
if(pga && pga->IsUsed() && dac0->IsUsed() && (pga->GetInputMode() == Greenpak4PGA::MODE_PDIFF) )
{
LogError(
"DAC0 is used while the PGA is in pseudo-differential mode. This is illegal since the "
"PGA uses DAC0 to provide the pseudo-differential offset voltage.\n");
}

//TODO: Cannot use DAC1 when ADC is used
}

//Done
return ok;
34 changes: 34 additions & 0 deletions src/greenpak4/Greenpak4BitstreamEntity.cpp
Original file line number Diff line number Diff line change
@@ -53,6 +53,40 @@ Greenpak4BitstreamEntity::~Greenpak4BitstreamEntity()
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Connectivity tracing helpers

/**
@brief Check if we have any loads on a particular port
*/
bool Greenpak4BitstreamEntity::HasLoadsOnPort(string port)
{
//Get our cell, or bail if we're unassigned
auto ncell = dynamic_cast<Greenpak4NetlistCell*>(GetNetlistEntity());
if(ncell == NULL)
return false;

//If nothing on the port, stop
if(ncell->m_connections.find(port) == ncell->m_connections.end())
return false;

//Check if any connections other than ourself
auto vec = ncell->m_connections[port];
for(auto node : vec)
{
for(auto point : node->m_nodeports)
{
if(point.m_cell != ncell)
return true;
}

if(!node->m_ports.empty())
return true;
}

return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Net numbering helpers

2 changes: 2 additions & 0 deletions src/greenpak4/Greenpak4BitstreamEntity.h
Original file line number Diff line number Diff line change
@@ -128,6 +128,8 @@ class Greenpak4BitstreamEntity

bool IsGeneralFabricInput(std::string port) const;

bool HasLoadsOnPort(std::string port);

protected:

///Return our assigned netlist entity, if we have one (or NULL if not)
5 changes: 5 additions & 0 deletions src/greenpak4/Greenpak4DAC.cpp
Original file line number Diff line number Diff line change
@@ -56,6 +56,11 @@ Greenpak4DAC::~Greenpak4DAC()
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Accessors

bool Greenpak4DAC::IsUsed()
{
return HasLoadsOnPort("VOUT");
}

string Greenpak4DAC::GetDescription()
{
char buf[128];
2 changes: 2 additions & 0 deletions src/greenpak4/Greenpak4DAC.h
Original file line number Diff line number Diff line change
@@ -53,6 +53,8 @@ class Greenpak4DAC : public Greenpak4BitstreamEntity
unsigned int GetDACNum()
{ return m_dacnum; }

bool IsUsed();

protected:
Greenpak4EntityOutput m_vref;
Greenpak4EntityOutput m_din[8];
5 changes: 5 additions & 0 deletions src/greenpak4/Greenpak4PGA.cpp
Original file line number Diff line number Diff line change
@@ -86,6 +86,11 @@ unsigned int Greenpak4PGA::GetOutputNetNumber(string /*port*/)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Serialization

bool Greenpak4PGA::IsUsed()
{
return HasLoadsOnPort("VOUT");
}

void Greenpak4PGA::CommitChanges()
{
//Get our cell, or bail if we're unassigned
19 changes: 13 additions & 6 deletions src/greenpak4/Greenpak4PGA.h
Original file line number Diff line number Diff line change
@@ -52,6 +52,18 @@ class Greenpak4PGA : public Greenpak4BitstreamEntity
Greenpak4EntityOutput GetInputN()
{ return m_vinn; }

bool IsUsed();

enum InputModes
{
MODE_SINGLE,
MODE_DIFF,
MODE_PDIFF
};

InputModes GetInputMode()
{ return m_inputMode; }

protected:
Greenpak4EntityOutput m_vinp;
Greenpak4EntityOutput m_vinn;
@@ -60,12 +72,7 @@ class Greenpak4PGA : public Greenpak4BitstreamEntity
//decimal fixed point: legal values 25, 50, 100, 200, 400, 800, 1600, 3200
unsigned int m_gain;

enum InputModes
{
MODE_SINGLE,
MODE_DIFF,
MODE_PDIFF
} m_inputMode;
InputModes m_inputMode;

///indicates if we have any loads other than the ADC
bool m_hasNonADCLoads;

0 comments on commit b7c2a22

Please sign in to comment.