# test_sequence.spec — проверочная последовательность для spec_server. status params defaults params set dur 100 set mask 0x0001 start ttl waitidle 1000 status set dur 20 set mask 0x0003 set freq 2500000 set phase 0 set env 2 8191 # scale <= 8191: пик всех четырёх таблиц ровно 8191, # выше срез [26:13] переполняется set pulse 10 start rf waitidle 1000 status # Почему между звеньями waitbuf, а не wait. Маска и длительность — немедленные # параметры: ttl_controller защёлкивает их (pend_mask/pend_dur) в тот момент, # когда старт до него доходит. Пока команда лежит в буфере axi_opcode_ctrl, она # ещё ничего не защёлкнула — поменяй маску сейчас, и уже поставленное в очередь # событие уедет с чужой. waitbuf ждёт снятия buf_valid, то есть момента, когда # команда ушла из буфера в тракт и параметры зафиксированы. # # Глубина очереди — три события (буфер + слот ttl_controller + идущее), поэтому # цепочка идёт без разрывов между окнами. set dur 20 set mask 0xFFFF set pulse 10 start rf waitbuf 1000 set dur 50 set mask 0x0000 start ttl waitbuf 1000 set dur 1000 set mask 0xFFFF start ttl waitidle 5000 status set dur 20 set mask 0xFFFF set pulse 10 start rf waitbuf 1000 start rf waitbuf 1000 start rf waitidle 5000 status # --------------------------------------------------------------------------- # Секвенсор: та же пачка из трёх РЧ-импульсов подряд, но загруженная в BRAM и # запущенная одной командой. seqbegin переводит cmd_send в режим загрузки — # то же самое "opcode, потом param", что и в live-режиме, только вместо # event_controller слово дописывается в память секвенсора по # автоинкрементному указателю. Контракты (Найквист, env_id, длина огибающей # и т.д.) проверяются ТЕМИ ЖЕ обработчиками, что и в live-режиме — просто на # "теневой" структуре состояния для загрузки, а не на боевой. seqend # возвращает cmd_send к live-пути. # # Внутри загруженной программы waitbuf не нужен: слова уже лежат в BRAM в # нужном порядке до старта, между ними нет сетевого окна, в которое можно # было бы влезть с изменением маски/длительности — тот самый гоночный # сценарий, который выше решался через waitbuf, здесь структурно невозможен. # --------------------------------------------------------------------------- seqbegin set dur 20 set mask 0xFFFF set pulse 10 set env 3 8191 start rf set dur 20 set mask 0x0000 set pulse 10 set env 1 8191 start rf set dur 20 set mask 0xFFFF set pulse 10 set env 2 8191 start rf seqend status seqrun waitseq 1000 waitidle 5000 status # То же самое для цепочки TTL-guard / РЧ / TTL-guard из блока выше — там # между звеньями waitbuf обязателен. В загруженной программе он не нужен по # той же причине. seqbegin set dur 20 set mask 0xFFFF set pulse 10 start rf set dur 50 set mask 0x0000 start ttl set dur 1000 set mask 0xFFFF start ttl seqend seqrun waitseq 1000 waitidle 5000 status # --------------------------------------------------------------------------- # seqabort — прерывание проигрывания программы до её естественного конца. # Первое событие короткое и успевает начаться до host-задержки в 5 мс, второе # (TTL на 2 мс) должно быть прервано и не доиграть до конца. # --------------------------------------------------------------------------- seqbegin set dur 2000 set mask 0xFFFF set pulse 1000 start rf set dur 2000 set mask 0xFFFF start ttl seqend seqrun wait 5 seqabort waitidle 5000 status defaults params echo === готово, все команды приняты === # Проверка отказов по контрактам вынесена в test_contracts.spec: там команды # заведомо ошибочные, и код возврата у прогона будет ненулевой. # # python spec_client.py --host <плата> --run test_contracts.spec -k