t27.aiEnglish

Сравнение двух трасс

Вы научитесь

Как сравнить два прогона и пусть трасса назовёт самый ранний такт расхождения.

Два прогона одного тестбенча, до изменения и после: самый быстрый вопрос — где они разошлись. Диф по трассе отвечает с точностью до одного изменения сигнала: самый ранний такт, где эталонный прогон говорит 1, а новый говорит 0. Виджет сравнивает файлы именно так, кадр за кадром, и отказывается говорить «одинаково», когда байт различается. Spec урока — тестбенч, ведущий инструмент сравнения VCD: ожидание против факта, с печатью несовпадения, а не разглядыванием.

Попробуйте

Откройте диф на двух собственных файлах; затем найдите в тестбенче сравнения место, где печатается самый ранний несовпадающий такт.

Открыть интерактивный урок →

Bitstream diff: two 7-series .bit files, frame by frame
Bitstream diff: two 7-series .bit files, frame by frame ↗

Drop two Xilinx 7-series bitstreams: header, packets and every 101-word frame compared in your browser, the first differing frame address decoded. Nothing is uploaded.

specs/fpga/testbench/vcd_conformance_compare_tb.t27

// SPDX-License-Identifier: Apache-2.0
// t27/specs/fpga/testbench/vcd_conformance_compare_tb.t27
// VCD Conformance Compare Testbench
// Tests the conformance comparison engine: batch compare, masking, value extraction
// phi^2 + 1/phi^2 = 3 | TRINITY

module VcdConformanceCompare_Testbench {
    use fpga::vcd_conformance_compare::VcdConformanceCompare;

    const CLK_PERIOD : u32 = 20;
    const MAX_COMPARES : u32 = 128;

    var clk : bool = false;
    var rst_n : bool = false;
    var compare_en : bool = false;
    var total_checks : u32 = 0;
    var pass_count : u32 = 0;
    var fail_count : u32 = 0;

    var test_passed : u32 = 0;
    var test_failed : u32 = 0;

    fn tick() {
        clk = false;
        clk = true;
    }

    fn reset() {
        rst_n = false;
        tick();
        tick();
        rst_n = true;
        tick();
        total_checks = 0;
        pass_count = 0;
        fail_count = 0;
    }

    fn run_compare(vcd: [u32], vcd_count: u32, expected_vals: [u32], expected_count: u32) -> u32 {
        var matches : u32 = 0;
        var i : u32 = 0;
        while i < expected_count {
            if i < vcd_count and vcd[i] == expected_vals[i] {
                matches = matches + 1;
            }
            i = i + 1;
        }
        return matches;
    }

    test test_reset_clears_state {
        reset();
        invariant total_checks == 0;
        invariant pass_count == 0;
        invariant fail_count == 0;
    }

    test test_run_compare_all_match {
        var vcd : [u32] = [10, 20, 30];
        var expected : [u32] = [10, 20, 30];
        var result : u32 = run_compare(vcd, 3, expected, 3);
        invariant result == 3;
    }

    test test_run_compare_partial_match {
        var vcd : [u32] = [10, 20, 30];
        var expected : [u32] = [10, 99, 30];
        var result : u32 = run_compare(vcd, 3, expected, 3);
        invariant result == 2;
    }

    test test_run_compare_no_match {
        var vcd : [u32] = [10, 20];
        var expected : [u32] = [99, 88];
        var result : u32 = run_compare(vcd, 2, expected, 2);
        invariant result == 0;
    }

    test test_run_compare_empty {
        var result : u32 = run_compare([], 0, [], 0);
        invariant result == 0;
    }

    test test_run_compare_vcd_shorter {
        var vcd : [u32] = [10];
        var expected : [u32] = [10, 20];
        var result : u32 = run_compare(vcd, 1, expected, 2);
        invariant result == 1;
    }

    test test_max_compares {
        invariant MAX_COMPARES == 128;
    }

    test test_clk_period {
        invariant CLK_PERIOD == 20;
    }

    invariant max_compares_positive : MAX_COMPARES > 0;

    bench bench_vcd_compare {
        reset();
        compare_en = true;
        var i : u32 = 0;
        while i < 100 {
            tick();
            i = i + 1;
        }
        compare_en = false;
    }
}

Открыть spec урока в плеере ↗

Все уроки