Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Commit

Permalink
Update frequency detection: add method 3
Browse files Browse the repository at this point in the history
  • Loading branch information
xlz-jbleclere committed Jan 20, 2021
1 parent 9bc951b commit 2a4a626
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 104 deletions.
124 changes: 91 additions & 33 deletions source/drm_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ limitations under the License.

#define NB_MAX_REGISTER 32

#define REG_FREQ_DETECTION_VERSION 0xFFF8
#define REG_FREQ_DETECTION_COUNTER 0xFFFC
#define REG_FREQ_DETECTION_VERSION 0xFFF0
#define REG_FREQ_DETECTION_COUNTER_DRMACLK 0xFFF4
#define REG_FREQ_DETECTION_COUNTER_AXIACLK 0xFFF8

#define FREQ_DETECTION_VERSION_EXPECTED 0x60DC0DE0
#define FREQ_DETECTION_VERSION_2 0x60DC0DE0
#define FREQ_DETECTION_VERSION_3 0x60DC0DE1


#define TRY try {
Expand Down Expand Up @@ -184,7 +186,7 @@ class DRM_LOCAL DrmManager::Impl {
int32_t mFrequencyCurr = 0;
uint32_t mFrequencyDetectionPeriod = 100; // in milliseconds
double mFrequencyDetectionThreshold = 12.0; // Error in percentage
bool mIsFreqDetectionMethod1 = false;
uint8_t mFreqDetectionMethod = 0;
bool mBypassFrequencyDetection = false;

// Session state
Expand Down Expand Up @@ -591,7 +593,7 @@ class DRM_LOCAL DrmManager::Impl {

Json::Value buildSettingsNode() {
Json::Value settings;
settings["frequency_detection_method"] = mIsFreqDetectionMethod1? 1:2;
settings["frequency_detection_method"] = mFreqDetectionMethod;
settings["bypass_frequency_detection"] = mBypassFrequencyDetection;
settings["frequency_detection_threshold"] = mFrequencyDetectionThreshold;
settings["frequency_detection_period"] = mFrequencyDetectionPeriod;
Expand Down Expand Up @@ -948,8 +950,12 @@ class DRM_LOCAL DrmManager::Impl {
// Determine frequency detection method if metering/floating mode is active
if ( !isNodeLockedMode() ) {
determineFrequencyDetectionMethod();
if ( mIsFreqDetectionMethod1 ) {
detectDrmFrequencyMethod1();
if ( mFreqDetectionMethod == 3 ) {
detectDrmFrequencyMethod3();
} else if ( mFreqDetectionMethod == 2 ) {
detectDrmFrequencyMethod2();
} else {
Unreachable( "Unsupported DRM frequency detection method: {} ", mFreqDetectionMethod ); //LCOV_EXCL_LINE
}
}

Expand Down Expand Up @@ -1686,18 +1692,38 @@ class DRM_LOCAL DrmManager::Impl {
if ( ret != 0 ) {
Debug( "Failed to read DRM Ctrl frequency detection version register, errcode = {}. ", ret ); //LCOV_EXCL_LINE
}
if ( reg == FREQ_DETECTION_VERSION_EXPECTED ) {
// Use Method 1
Debug( "Use dedicated counter to compute DRM frequency (method 1)" );
mIsFreqDetectionMethod1 = true;
} else {
if ( reg == FREQ_DETECTION_VERSION_3 ) {
// Use Method 3
Debug( "Use dedicated counter to compute DRM frequency (method 3)" );
mFreqDetectionMethod = 3;
} else if ( reg == FREQ_DETECTION_VERSION_2 ) {
// Use Method 2
Debug( "Use license timer counter to compute DRM frequency (method 2)" );
mIsFreqDetectionMethod1 = false;
Debug( "Use dedicated counter to compute DRM frequency (method 2)" );
mFreqDetectionMethod = 2;
} else {
// Use Method 1
Debug( "Use license timer counter to compute DRM frequency (method 1)" );
mFreqDetectionMethod = 1;
}
}

void detectDrmFrequencyMethod1() {
std::vector<int32_t> frequency_list;

if ( mBypassFrequencyDetection ) {
return;
}

frequency_list.push_back( detectDrmFrequencyFromLicenseTimer() );
frequency_list.push_back( detectDrmFrequencyFromLicenseTimer() );
frequency_list.push_back( detectDrmFrequencyFromLicenseTimer() );
std::sort( frequency_list.begin(), frequency_list.end());

int32_t measured_frequency = frequency_list[1];
checkDrmFrequency( measured_frequency );
}

void detectDrmFrequencyMethod2() {
int ret;
uint32_t counter;
TClock::duration wait_duration = std::chrono::milliseconds( mFrequencyDetectionPeriod );
Expand All @@ -1708,16 +1734,16 @@ class DRM_LOCAL DrmManager::Impl {

std::lock_guard<std::recursive_mutex> lock( mDrmControllerMutex );

// Start detection counter
ret = writeDrmAddress( REG_FREQ_DETECTION_COUNTER, 0 );
// Reset detection counter by writing drm_aclk counter register
ret = writeDrmAddress( REG_FREQ_DETECTION_VERSION, 0 );
if ( ret != 0 )
Unreachable( "Failed to start DRM frequency detection counter, errcode = {}. ", ret ); //LCOV_EXCL_LINE

// Wait a fixed period of time
sleepOrExit( wait_duration );

// Sample counter
ret = readDrmAddress( REG_FREQ_DETECTION_COUNTER, counter );
// Sample drm_aclk counter
ret = readDrmAddress( REG_FREQ_DETECTION_COUNTER_DRMACLK, counter );
if ( ret != 0 ) {
Unreachable( "Failed to read DRM Ctrl frequency detection counter register, errcode = {}. ", ret ); //LCOV_EXCL_LINE
}
Expand All @@ -1734,20 +1760,55 @@ class DRM_LOCAL DrmManager::Impl {
checkDrmFrequency( measured_frequency );
}

void detectDrmFrequencyMethod2() {
std::vector<int32_t> frequency_list;
void detectDrmFrequencyMethod3() {
int ret;
uint32_t counter_drmaclk, counter_axiaclk;
TClock::duration wait_duration = std::chrono::milliseconds( mFrequencyDetectionPeriod );

if ( mBypassFrequencyDetection ) {
return;
}

frequency_list.push_back( detectDrmFrequencyFromLicenseTimer() );
frequency_list.push_back( detectDrmFrequencyFromLicenseTimer() );
frequency_list.push_back( detectDrmFrequencyFromLicenseTimer() );
std::sort( frequency_list.begin(), frequency_list.end());
std::lock_guard<std::recursive_mutex> lock( mDrmControllerMutex );

int32_t measured_frequency = frequency_list[1];
checkDrmFrequency( measured_frequency );
// Reset detection counter by writing drm_aclk counter register
ret = writeDrmAddress( REG_FREQ_DETECTION_VERSION, 0 );
if ( ret != 0 )
Unreachable( "Failed to start DRM frequency detection counter, errcode = {}. ", ret ); //LCOV_EXCL_LINE

// Wait a fixed period of time
sleepOrExit( wait_duration );

// Sample drm_aclk and s_axi_aclk counters
ret = readDrmAddress( REG_FREQ_DETECTION_COUNTER_DRMACLK, counter_drmaclk );
if ( ret != 0 ) {
Unreachable( "Failed to read drm_aclk frequency detection counter register, errcode = {}. ", ret ); //LCOV_EXCL_LINE
}
ret = readDrmAddress( REG_FREQ_DETECTION_COUNTER_AXIACLK, counter_axiaclk );
if ( ret != 0 ) {
Unreachable( "Failed to read s_axi_aclk frequency detection counter register, errcode = {}. ", ret ); //LCOV_EXCL_LINE
}

if ( counter_drmaclk == 0xFFFFFFFF )
Throw( DRM_BadFrequency, "Frequency auto-detection of drm_aclk failed: frequency_detection_period parameter ({} ms) is too long.",
mFrequencyDetectionPeriod );
if ( counter_axiaclk == 0xFFFFFFFF )
Throw( DRM_BadFrequency, "Frequency auto-detection of s_axi_aclk failed: frequency_detection_period parameter ({} ms) is too long.",
mFrequencyDetectionPeriod );

// Compute estimated DRM frequency for drm_aclk
int32_t measured_drmaclk = (int32_t)((double)counter_drmaclk / mFrequencyDetectionPeriod / 1000);
Debug( "Frequency detection of drm_aclk counter after {:f} ms is 0x{:08x} => estimated frequency = {} MHz",
(double)mFrequencyDetectionPeriod/1000, counter_drmaclk, measured_frequency );

// Compute estimated DRM frequency for s_axi_aclk
int32_t measured_axiaclk = (int32_t)((double)counter_axiaclk / mFrequencyDetectionPeriod / 1000);
Debug( "Frequency detection of drm_aclk counter after {:f} ms is 0x{:08x} => estimated frequency = {} MHz",
(double)mFrequencyDetectionPeriod/1000, counter_axiaclk, measured_frequency );

// Verify estimated frequencies remain in the accepted tolerance
checkDrmFrequency( measured_drmaclk );
checkDrmFrequency( measured_axiaclk );
}

int32_t detectDrmFrequencyFromLicenseTimer() {
Expand Down Expand Up @@ -1858,8 +1919,8 @@ class DRM_LOCAL DrmManager::Impl {
getHostAndCardInfo();

/// Detecting DRM controller frequency if needed
if ( !mIsFreqDetectionMethod1 )
detectDrmFrequencyMethod2();
if ( mFreqDetectionMethod == 1 )
detectDrmFrequencyMethod1();

bool go_sleeping( false );

Expand Down Expand Up @@ -2452,12 +2513,9 @@ class DRM_LOCAL DrmManager::Impl {
break;
}
case ParameterKey::frequency_detection_method: {
int32_t method_index = 2;
if ( mIsFreqDetectionMethod1 )
method_index = 1;
json_value[key_str] = method_index;
json_value[key_str] = mFreqDetectionMethod;
Debug( "Get value of parameter '{}' (ID={}): Method {}", key_str, key_id,
method_index );
mFreqDetectionMethod );
break;
}
case ParameterKey::frequency_detection_threshold: {
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,11 +603,11 @@ def create_log_level(verbosity):
return verbosity

# Get frequency detection version
freq_version = fpga_driver[0].read_register(drm_ctrl_base_addr + 0xFFF8)
freq_version = fpga_driver[0].read_register(drm_ctrl_base_addr + 0xFFF0)

# Store some values for access in tests
import accelize_drm as _accelize_drm
_accelize_drm.pytest_new_freq_method_supported = freq_version == 0x60DC0DE0
_accelize_drm.pytest_freq_detection_version = freq_version
_accelize_drm.pytest_proxy_debug = pytestconfig.getoption("proxy_debug")
_accelize_drm.pytest_server = pytestconfig.getoption("server")
_accelize_drm.pytest_build_environment = build_environment
Expand Down
124 changes: 89 additions & 35 deletions tests/test_frequency_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_configuration_file_with_bad_frequency(accelize_drm, conf_json, cred_jso
assert abs(conf_json['drm']['frequency_mhz'] - frequency) * 100.0 / frequency > freq_threshold
conf_json.save()

if accelize_drm.pytest_new_freq_method_supported:
if accelize_drm.pytest_freq_detection_version != 0xFFFFFFFF:
with pytest.raises(accelize_drm.exceptions.DRMBadFrequency) as excinfo:
drm_manager = accelize_drm.DrmManager(
conf_json.path,
Expand Down Expand Up @@ -142,10 +142,48 @@ def test_configuration_file_with_bad_frequency(accelize_drm, conf_json, cred_jso

@pytest.mark.minimum
def test_drm_manager_frequency_detection_method1(accelize_drm, conf_json, cred_json, async_handler, basic_log_file):
"""Test method1 (based on dedicated counter in AXI wrapper) to estimate drm frequency is working"""
"""Test method 1 (based on license timer) to estimate drm frequency is still working"""

refdesign = accelize_drm.pytest_ref_designs
driver = accelize_drm.pytest_fpga_driver[0]
fpga_image_bkp = driver.fpga_image
async_cb = async_handler.create()

# Program FPGA with HDK 3.x.x (with frequency detection method 1)
hdk = list(filter(lambda x: x.startswith('3.'), refdesign.hdk_versions))[-1]
assert hdk.startswith('3.')
image_id = refdesign.get_image_id(hdk)
try:
driver.program_fpga(image_id)
conf_json.reset()
conf_json['settings'].update(basic_log_file.create(1))
conf_json.save()
drm_manager = accelize_drm.DrmManager(
conf_json.path,
cred_json.path,
driver.read_register_callback,
driver.write_register_callback,
async_cb.callback
)
assert drm_manager.get('frequency_detection_method') == 1
drm_manager.activate()
assert drm_manager.get('frequency_detection_method') == 1
drm_manager.deactivate()
del drm_manager
log_content = basic_log_file.read()
assert "Use license timer counter to compute DRM frequency (method 1)" in log_content
basic_log_file.remove()
finally:
# Reprogram FPGA with original image
driver.program_fpga(fpga_image_bkp)

if not accelize_drm.pytest_new_freq_method_supported:
pytest.skip("New frequency detection method is not supported: test skipped")

@pytest.mark.minimum
def test_drm_manager_frequency_detection_method2(accelize_drm, conf_json, cred_json, async_handler, basic_log_file):
"""Test method2 (based on dedicated counter in AXI wrapper) to estimate drm_aclk frequency is working"""

if accelize_drm.pytest_freq_detection_version != 0x60DC0DE0:
pytest.skip("Frequency detection method 2 is not implemented in this design: test skipped")

driver = accelize_drm.pytest_fpga_driver[0]
async_cb = async_handler.create()
Expand All @@ -161,18 +199,18 @@ def test_drm_manager_frequency_detection_method1(accelize_drm, conf_json, cred_j
driver.write_register_callback,
async_cb.callback
)
assert drm_manager.get('frequency_detection_method') == 1
assert drm_manager.get('frequency_detection_method') == 2
del drm_manager
log_content = basic_log_file.read()
assert "Use dedicated counter to compute DRM frequency (method 1)" in log_content
assert "Use dedicated counter to compute DRM frequency" in log_content
basic_log_file.remove()


def test_drm_manager_frequency_detection_method1_exception(accelize_drm, conf_json, cred_json, async_handler):
"""Test method1 (based on dedicated counter in AXI wrapper) to estimate drm frequency is working"""
def test_drm_manager_frequency_detection_method2_exception(accelize_drm, conf_json, cred_json, async_handler):
"""Test method 2 (based on dedicated counter in AXI wrapper) to estimate drm frequency is working"""

if not accelize_drm.pytest_new_freq_method_supported:
pytest.skip("New frequency detection method is not supported: test skipped")
if accelize_drm.pytest_freq_detection_version != 0x60DC0DE0:
pytest.skip("Frequency detection method 2 is not implemented in this design: test skipped")

driver = accelize_drm.pytest_fpga_driver[0]
async_cb = async_handler.create()
Expand All @@ -195,47 +233,63 @@ def test_drm_manager_frequency_detection_method1_exception(accelize_drm, conf_js


@pytest.mark.minimum
def test_drm_manager_frequency_detection_method2(accelize_drm, conf_json, cred_json, async_handler, basic_log_file):
"""Test method2 (based on license timer) to estimate drm frequency is still working"""
def test_drm_manager_frequency_detection_method3(accelize_drm, conf_json, cred_json, async_handler, basic_log_file):
"""Test method 3 (based on dedicated counter in AXI wrapper) to estimate drm_aclk frequency is working"""

if accelize_drm.pytest_freq_detection_version != 0x60DC0DE0:
pytest.skip("Frequency detection method 3 is not implemented in this design: test skipped")

refdesign = accelize_drm.pytest_ref_designs
driver = accelize_drm.pytest_fpga_driver[0]
fpga_image_bkp = driver.fpga_image
async_cb = async_handler.create()

# Program FPGA with HDK 3.x.x (with frequency detection method 2)
hdk = list(filter(lambda x: x.startswith('3.'), refdesign.hdk_versions))[-1]
assert hdk.startswith('3.')
image_id = refdesign.get_image_id(hdk)
try:
driver.program_fpga(image_id)
conf_json.reset()
conf_json['settings'].update(basic_log_file.create(1))
conf_json.save()
conf_json.reset()
conf_json['settings'].update(basic_log_file.create(1))
conf_json.save()

drm_manager = accelize_drm.DrmManager(
conf_json.path,
cred_json.path,
driver.read_register_callback,
driver.write_register_callback,
async_cb.callback
)
assert drm_manager.get('frequency_detection_method') == 3
del drm_manager
log_content = basic_log_file.read()
assert "Use dedicated counter to compute DRM frequency" in log_content
basic_log_file.remove()


def test_drm_manager_frequency_detection_method3_exception(accelize_drm, conf_json, cred_json, async_handler):
"""Test method 3 based on dedicated counters in AXI wrapper to estimate drm_aclk and s_axi_aclk frequency is working"""

if accelize_drm.pytest_freq_detection_version != 0x60DC0DE1:
pytest.skip("Frequency detection method 3 is not implemented in this design: test skipped")

driver = accelize_drm.pytest_fpga_driver[0]
async_cb = async_handler.create()

conf_json.reset()
conf_json['settings']['frequency_detection_period'] = (int)(2**32 / 125000000 * 1000) + 1000
conf_json.save()
with pytest.raises(accelize_drm.exceptions.DRMBadFrequency) as excinfo:
drm_manager = accelize_drm.DrmManager(
conf_json.path,
cred_json.path,
driver.read_register_callback,
driver.write_register_callback,
async_cb.callback
)
assert drm_manager.get('frequency_detection_method') == 2
drm_manager.activate()
assert drm_manager.get('frequency_detection_method') == 2
drm_manager.deactivate()
del drm_manager
log_content = basic_log_file.read()
assert "Use license timer counter to compute DRM frequency (method 2)" in log_content
basic_log_file.remove()
finally:
# Reprogram FPGA with original image
driver.program_fpga(fpga_image_bkp)
assert search(r'Frequency auto-detection failed: frequency_detection_period parameter \([^)]+\) is too long',
str(excinfo.value)) is not None
assert async_handler.get_error_code(str(excinfo.value)) == accelize_drm.exceptions.DRMBadFrequency.error_code
async_cb.assert_NoError()


def test_drm_manager_frequency_detection_bypass(accelize_drm, conf_json, cred_json, async_handler):
"""Test bypass of frequency detection"""

if not accelize_drm.pytest_new_freq_method_supported:
if accelize_drm.pytest_freq_detection_version != 0xFFFFFFFF:
pytest.skip("New frequency detection method is not supported: test skipped")

driver = accelize_drm.pytest_fpga_driver[0]
Expand Down
Loading

0 comments on commit 2a4a626

Please sign in to comment.