diff options
| author | Martin Braun <martin.braun@ettus.com> | 2020-01-23 16:10:22 -0800 |
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2020-01-28 09:35:36 -0800 |
| commit | bafa9d95453387814ef25e6b6256ba8db2df612f (patch) | |
| tree | 39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/sim/rfnoc/PkgTestExec.sv | |
| parent | 3075b981503002df3115d5f1d0b97d2619ba30f2 (diff) | |
| download | uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2 uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip | |
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce
the size of the repository. However, over the last half-decade, the
split between the repositories has proven more burdensome than it has
been helpful. By merging the FPGA code back, it will be possible to
create atomic commits that touch both FPGA and UHD codebases. Continuous
integration testing is also simplified by merging the repositories,
because it was previously difficult to automatically derive the correct
UHD branch when testing a feature branch on the FPGA repository.
This commit also updates the license files and paths therein.
We are therefore merging the repositories again. Future development for
FPGA code will happen in the same repository as the UHD host code and
MPM code.
== Original Codebase and Rebasing ==
The original FPGA repository will be hosted for the foreseeable future
at its original local location: https://github.com/EttusResearch/fpga/
It can be used for bisecting, reference, and a more detailed history.
The final commit from said repository to be merged here is
05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as
v4.0.0.0-pre-uhd-merge.
If you have changes in the FPGA repository that you want to rebase onto
the UHD repository, simply run the following commands:
- Create a directory to store patches (this should be an empty
directory):
mkdir ~/patches
- Now make sure that your FPGA codebase is based on the same state as
the code that was merged:
cd src/fpga # Or wherever your FPGA code is stored
git rebase v4.0.0.0-pre-uhd-merge
Note: The rebase command may look slightly different depending on what
exactly you're trying to rebase.
- Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge:
git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches
Note: Make sure that only patches are stored in your output directory.
It should otherwise be empty. Make sure that you picked the correct
range of commits, and only commits you wanted to rebase were exported
as patch files.
- Go to the UHD repository and apply the patches:
cd src/uhd # Or wherever your UHD repository is stored
git am --directory fpga ~/patches/*
rm -rf ~/patches # This is for cleanup
== Contributors ==
The following people have contributed mainly to these files (this list
is not complete):
Co-authored-by: Alex Williams <alex.williams@ni.com>
Co-authored-by: Andrej Rode <andrej.rode@ettus.com>
Co-authored-by: Ashish Chaudhari <ashish@ettus.com>
Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com>
Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Derek Kozel <derek.kozel@ettus.com>
Co-authored-by: EJ Kreinar <ej@he360.com>
Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com>
Co-authored-by: Ian Buckley <ian.buckley@gmail.com>
Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Jon Kiser <jon.kiser@ni.com>
Co-authored-by: Josh Blum <josh@joshknows.com>
Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com>
Co-authored-by: Martin Braun <martin.braun@ettus.com>
Co-authored-by: Matt Ettus <matt@ettus.com>
Co-authored-by: Michael West <michael.west@ettus.com>
Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com>
Co-authored-by: Nick Foster <nick@ettus.com>
Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Paul David <paul.david@ettus.com>
Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com>
Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com>
Co-authored-by: Sylvain Munaut <tnt@246tNt.com>
Co-authored-by: Trung Tran <trung.tran@ettus.com>
Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/sim/rfnoc/PkgTestExec.sv')
| -rw-r--r-- | fpga/usrp3/sim/rfnoc/PkgTestExec.sv | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/fpga/usrp3/sim/rfnoc/PkgTestExec.sv b/fpga/usrp3/sim/rfnoc/PkgTestExec.sv new file mode 100644 index 000000000..ba4455912 --- /dev/null +++ b/fpga/usrp3/sim/rfnoc/PkgTestExec.sv @@ -0,0 +1,297 @@ +// +// Copyright 2019 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: PkgTestExec +// +// Description: This package provides infrastructure for tracking the state of +// testbench execution and the results of each test. +// + + + +package PkgTestExec; + + timeunit 1ns; + timeprecision 1ps; + + typedef enum { SEV_INFO, SEV_WARNING, SEV_ERROR, SEV_FATAL } severity_t; + + typedef std::process timeout_t; + + class TestExec; + + string tb_name; // Name of the testbench + string current_test; // Name of the current test being run + int num_started, num_finished; // Number of tests started and finished + int num_passed; // Number of tests that have passed + int num_assertions; // Number of assertions checked for the current test + time start_time, end_time; // Start and end time of the testbench + bit stop_on_error = 1; // Configuration option to stop when an error occurs + bit test_status[$]; // Pass/fail status of each test + + timeout_t tb_timeout; // Handle to timeout for the overall testbench + timeout_t test_timeout; // Handle to timeout for current test + + semaphore test_sem; // Testbench semaphore + + + function new(); + $timeformat(-9, 0, " ns", 12); + this.test_sem = new(1); + endfunction : new + + + // Call start_tb() at the start of a testbench to initialize state tracking + // properties. + // + // time_limit: Max simulation time allowed before at timeout occurs. + // This is a catch-all, in case things go very wrong during + // simulation and cause it to never end. + // + task start_tb(string tb_name, realtime time_limit = 10ms); + // Get the sempahore, to prevent multiple overlapping instances of the + // same testbench. + test_sem.get(); + + $display("========================================================"); + $display("TESTBENCH STARTED: %s", tb_name); + $display("========================================================"); + this.tb_name = tb_name; + start_time = $time; + test_status = {}; + num_started = 0; + num_finished = 0; + num_passed = 0; + start_timeout( + tb_timeout, + time_limit, + $sformatf("Testbench \"%s\" time limit exceeded", tb_name), + SEV_FATAL + ); + endtask : start_tb + + + // Call end_tb() at the end of a testbench to report final statistics and, + // optionally, end simulation. + // + // finish: Set to 1 (default) to cause $finish() to be called at the + // end of simulation, cuasing the simulator to close. + // + function void end_tb(bit finish = 1); + assert (num_started == num_finished) else begin + $fatal(1, "Testbench ended before test completed"); + end + + end_time = $time; + $display("========================================================"); + $display("TESTBENCH FINISHED: %s", tb_name); + $display(" - Time elapsed: %0t", end_time - start_time); + $display(" - Tests Run: %0d", num_finished); + $display(" - Tests Passed: %0d", num_passed); + $display(" - Tests Failed: %0d", num_started - num_passed); + $display("Result: %s", + (num_started == num_passed) && (num_finished > 0) + ? "PASSED " : "FAILED!!!"); + $display("========================================================"); + + end_timeout(tb_timeout); + + if (finish) $finish(); + + // Release the semaphore to allow new instances of the testbench to run + test_sem.put(); + endfunction : end_tb + + + // Call at the start of each test with the name of the test. + // + // test_name: String name for the test to be started + // + task start_test(string test_name, realtime time_limit = 0); + // Make sure a there isn't already a test running + assert (num_started == num_finished) else begin + $fatal(1, "Test started before completing previous test"); + end + + // Create a timeout for this test + if (time_limit > 0) begin + start_timeout( + test_timeout, + time_limit, + $sformatf("Test \"%s\" time limit exceeded", test_name), + SEV_FATAL + ); + end + + current_test = test_name; + num_started++; + $display("[TEST CASE %3d] (t = %t) BEGIN: %s...", num_started, $time, test_name); + test_status.push_back(1); // Set status to 1 (passed) initially + num_assertions = 0; + endtask : start_test + + + // Call end_test() at the end of each test. + // + // test_result: Optional value to indicate the overall pass/fail result + // of the test. Use non-zero for pass, 0 for fail. + // + task end_test(int test_result = 1); + bit passed; + + assert (num_started == num_finished + 1) else begin + $fatal(1, "No test running"); + end + + end_timeout(test_timeout); + + passed = test_status[num_started-1] && test_result; + num_finished++; + $display("[TEST CASE %3d] (t = %t) DONE... %s", + num_started, $time, passed ? "Passed" : "FAILED"); + + if (passed) num_passed++; + + current_test = ""; + endtask : end_test + + + // Assert the given expression and call $error() if it fails. Simulation + // will also be stopped (using $stop) if stop_on_error is true. + // + // expr: The expression value to be asserted + // message: String to report if the assertion fails + // + function void assert_error(int expr, string message = ""); + num_assertions++; + assert (expr) else begin + test_status[num_started] = 0; + $error(message); + if (stop_on_error) $stop; + end + endfunction : assert_error + + + // Assert the given expression and call $fatal() if it fails. + // + // expr: The expression value to be asserted + // message: String to report if the assertion fails + // + function void assert_fatal(int expr, string message = ""); + num_assertions++; + assert (expr) else begin + test_status[num_started] = 0; + $fatal(1, message); + end + endfunction : assert_fatal + + + // Assert the given expression and call $warning() if it fails. + // + // expr: The expression value to be asserted + // message: String to report if the assertion fails + // + function void assert_warning(int expr, string message = ""); + num_assertions++; + assert (expr) else begin + $warning(message); + end + endfunction : assert_warning + + + // Assert the given expression and call the appropriate severity or fatal + // task if the expression fails. + // + // expr: The expression value to be asserted + // message: String to report if the assertion fails + // severity: Indicates the type of severity task that should be used if + // the assertion fails ($info, $warning, $error, $fatal). + // Default value is SEV_ERROR. + // + function void assert_sev( + int expr, + string message = "", + severity_t severity = SEV_ERROR + ); + num_assertions++; + assert (expr) else begin + case (severity) + SEV_INFO: begin + $info(message); + end + SEV_WARNING: begin + $warning(message); + end + SEV_ERROR: begin + $error(message); + test_status[num_started] = 0; + if (stop_on_error) $stop; + end + default: begin // SEV_FATAL + test_status[num_started] = 0; + $fatal(1, message); + end + endcase + end + endfunction : assert_sev + + + // Create a timeout that will expire after the indicated delay, causing an + // error if the timeout is not canceled before the delay has elapsed. + // + // handle: A handle to the timeout process created. Use this + // handle to end the timeout. + // timeout_delay: Amount of time to wait before the timeout expires. + // message: String message to display if the timeout expires. + // severity: Indicates the type of severity task that should be + // used if the timeout expires. Default is SEV_ERROR. + // + task start_timeout( + output timeout_t handle, + input realtime timeout_delay, + input string message = "Timeout", + input severity_t severity = SEV_ERROR + ); + mailbox #(std::process) pid = new(1); + fork + begin : timeout + pid.put(process::self()); + #(timeout_delay); + assert_sev(0, {"Timeout: ", message}, severity); + end + join_none + #0; // Start the timeout process so we can get its process ID + + // Return the process ID + pid.get(handle); + endtask + + + // Cancel the timeout with the given handle. This kills the process + // running the timeout delay. + // + // handle: Handle created by start_timeout() for the timeout process. + // + function void end_timeout(timeout_t handle); + if (handle != null) + if (handle.status != process::FINISHED) handle.kill(); + endfunction; + + endclass : TestExec + + + //--------------------------------------------------------------------------- + // Test Object + //--------------------------------------------------------------------------- + // + // This is the default TestExec object instance shared by all instances of + // the running the testbench. + // + //--------------------------------------------------------------------------- + + TestExec test = new(); + +endpackage : PkgTestExec + |
