惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
Scott Helme
Scott Helme
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Stack Overflow Blog
Stack Overflow Blog
Forbes - Security
Forbes - Security
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
S
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
N
News | PayPal Newsroom
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Project Zero
Project Zero
Cyberwarzone
Cyberwarzone
Vercel News
Vercel News
M
MIT News - Artificial intelligence
云风的 BLOG
云风的 BLOG
Google Online Security Blog
Google Online Security Blog
Simon Willison's Weblog
Simon Willison's Weblog
MongoDB | Blog
MongoDB | Blog
Martin Fowler
Martin Fowler
T
Tenable Blog
I
InfoQ
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
G
Google Developers Blog
D
DataBreaches.Net
博客园 - Franky
Know Your Adversary
Know Your Adversary
Spread Privacy
Spread Privacy
S
Security @ Cisco Blogs
Hacker News: Ask HN
Hacker News: Ask HN
J
Java Code Geeks
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Full Disclosure
C
Cisco Blogs
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
I
Intezer
The GitHub Blog
The GitHub Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
F
Fortinet All Blogs
Jina AI
Jina AI
V
Visual Studio Blog
L
LINUX DO - 热门话题
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Как ускорить верификацию: советы для инженеров и менеджеров аппаратной разработки
alinkagalich · 2026-04-22 · via Все публикации подряд на Хабре

Как ускорить верификацию: советы для инженеров и менеджеров аппаратной разработки

Уровень сложностиСредний

Время на прочтение18 мин

Охват и читатели2.4K

Туториал

Привет, Хабр! Меня зовут Алина, я руковожу группой модульной верификации в YADRO. Свой путь в отрасли я начинала со схемотехники и разработки RTL под FPGA. На Хабре даже есть моя статья про использование опций синтеза в Vivado, написанная еще до того, как различные стратегии на основе AI стали нормой. В черновиках лежит вторая часть той статьи, где я делаю вид, что понимаю математику, которая лежит в основе синтеза цифровой схемы из RTL :) Однако тот текст так и остался черновиком, а я ушла в верификацию и работаю в ней уже больше шести лет.

Скорость верификации IP-компонентов зависит не только от верификаторов. Чтобы ее увеличить, ряд полезных практик в свою работу могут внедрить и соседние команды — управления проектами, RTL-дизайна и архитектуры. Далее в статье я такими практиками поделюсь.

Согласно исследованию Wilson Research Group от 2023 года, более 65% ASIC-проектов выходит за изначально планируемые сроки разработки. Более 50% проектов получают хотя бы два респина, прежде чем выйти на рынок. Причина большинства респинов — ошибка в цифровом дизайне. Исследование также показывает, что основной причиной функциональных ошибок являются ошибки проектирования. Многие инженеры по верификации и менеджеры проектов упоминают здесь и проблемы, связанные с изменением, некорректностью и неполнотой спецификаций.

Причины функциональных ошибок в ASIC-проектах

Причины функциональных ошибок в ASIC-проектах

Производители всеми силами стремятся улучшить эту удручающую статистику. Верификация — один из самых ресурсоемких этапов проекта, занимающий больше половины общего времени. Но объем работы верификаторов с годами только растет, как и число логических элементов на микросхеме. В процессе мы обрабатываем очень много артефактов от разных команд — RTL-код, спецификации от архитекторов, референсные модели, готовые тесты. А еще у нас есть собственные артефакты: код верификационного окружения, логи компиляции и запуска, разнообразные отчеты о пассрейте и покрытии тестов, статистика и многое другое.

Мы анализируем все эти артефакты и сопоставляем их, определяя, насколько IP-компонент соответствует заданным требованиям. Артефакты могут быть очень разными, поэтому нам нередко приходится выходить за пределы привычных пайплайнов — например, решать инфраструктурные проблемы.

Доля времени, что тратят на верификацию в разных ASIC-проектах

Доля времени, что тратят на верификацию в разных ASIC-проектах

Артефакты влияют на сроки запуска тестов для прототипа — это один из критериев успеха всего проекта. Верификаторы могут пройти этот путь за несколько недель, а могут биться не один год.

Далее я расскажу о практиках в работе команд управления проектами, RTL дизайна и архитектуры — практиках, помогающих ускорить успешную верификацию IP-компонента. Их я разделю по «бичам верификации» — темам, которые традиционно вызывают у верификаторов больше всего проблем.

Менеджмент требований

Трекинг и маркировка

Бывает, что архитекторы большой подсистемы придумывают фичу или приносят новое требование от бизнеса, для которого эта фича нужна. В фиче определяют узкие места, несут ее разработчику, который фичу имплементирует. А у верификатора падают тесты. И только тогда, в последнюю очередь, он узнает о существовании этой самой фичи. Чтобы такого не случалось, важно иметь налаженную систему трекинга требований и информирования всех заинтересованных.

В этой системе верификатору поможет маркировка требований к спецификации: тогда к ним легко будет привязать план верификации, тесты, точки покрытия, чекеры и другие рабочие артефакты. Они помогают отслеживать покрытие верификации: какие требования каким образом успели охватить.

В грамотных системах трекинга все требования хранятся в едином формате и имеют уникальные идентификаторы. А при появлении новых высокоуровневых требований можно сразу посмотреть, какие низкоуровневые изменения для них требуется поддержать. Важность систематизации требований хорошо описана у К. Вигерса и Дж. Битти в «Разработке требований к программному обеспечению». Многие практики из книги можно применить и к аппаратной разработке.

Если вы ведете требования в Confluence, то для систематизации и учета требований можно попробовать плагин Requirement Yogi. Он умеет связывать между собой требования и фильтровать их, фиксировать срезы требований (baseline) в определенный момент. Для продуктивного использования инструмент стоит донастроить: прописать жизненный цикл требований и процесс работы с ним. Гибкость плагина позволяет адаптировать его под уже существующие рабочие процессы.

Requirement Yogi. Источник

Requirement Yogi. Источник

Хороший пример явной связи артефактов верификации и требований — AXI Verification IP от Synopsys. Спецификация протокола AMBA AXI хорошо декомпозирована при помощи многоуровневого списка. В каждом нумерованном разделе описаны определенные требования к протоколу. В комплекте с AXI Verification IP идет иерархический верификационный план (Hierarchy verification plan, HVP), каждый пункт которого имеет явную ссылку на конкретные пункты спецификации AMBA AXI. В HVP уже есть наполнение метриками из VIP, к которым при необходимости можно добавить собственные метрики: точки покрытия, точки проверок, утверждения.

Параллельные процессы

Часто бывает, что разработка и верификация идут бок о бок: спецификацию создают вместе с RTL и параллельно отлаживают на верификационном окружении. Так продвигают сразу несколько IP-блоков, и требования к ним уточняют по ходу проекта. Это нормально в гибких методологиях, но в разработке IP-компонентов вы не сможете предсказать окончание верификации, пока спецификация не будет зафиксирована всеми сторонами.

План верификации, который составляют параллельно спецификации, устаревает с каждым обновлением в требованиях. Поэтому и планировать ресурсы на верификацию в этот период едва ли возможно — ни инженерные, ни машинные. Планы устаревают в момент создания :)

Этот процесс почти неизбежен, но его можно контролировать. Для этого все изменения спецификации после ее фиксирования должны проходить через явный процесс Change Requests. В нем должно быть явно сформулировано изменение требований или новое требование. А после — проведен анализ влияния на трудозатраты и инфраструктуру со стороны всех вовлеченных команд. Так можно выявить требования, которые кажутся хорошими и нужными на бумаге, но затраты на их имплементацию и верификацию превысят пользу на текущем этапе. Далее такие требования можно отсеять или выставить им корректный приоритет.

Golden-сценарии

Хорошая практика — когда разработчик, верификатор и архитектор договариваются о наборе «золотых» сценариев, которые всегда должны отрабатывать в соответствии с ожиданиями. Это помогает командам сфокусироваться и всегда поддерживать хотя бы ограниченную работоспособность разрабатываемого IP. Если принятые golden-сценарии достаточно соответствуют целевым, мы всегда будем уверены, что в любом случае новые фичи не поломают IP-компонент.

Набор золотых сценариев на одной из моих предыдущих работ называли check-in regression. Его запускали каждые четыре часа. Результаты рассылали не только разработчикам и верификаторам RTL, но и руководству — в том числе владельцу продукта, которого называли chip owner. Любые падения в «золотом» наборе приводили к разбирательствам, чинить нужно было безотлагательно. Однажды мне, тогда мидл-инженеру, пришлось откатить правки своего техлида, чтобы исправить падения в check-in.

Менеджмент конфигураций

RTL-разработку можно разделить на два больших направления. Первое — это реконфигурируемые IP-компоненты, которые могут как быть универсальными, так и иметь специальное предназначение (процессорный кластер, модули периферии, модули ускорения цифровой обработки и т. д.). Второе — это сборка IP-компонентов в одну большую SoC, куда входит архитектура тактового древа и сбросов, системы отладки, внешние интерфейсы и многое другое. Все это в конечном счете влияет и на реконфигурируемые IP-компоненты.

Define или defparam

Чтобы помочь в верификации больших подсистем, необходимо выровнять подход к менеджменту конфигураций среди различных блоков. Конфигурирование RTL-блоков — установка размера шины, буферов и т. д. — может проходить на уровне define либо через параметры, специальные конструкции SystemVerilog на более высоком уровне абстракции.

Пример с `define:

`define ADDER_IN_W 8 
`define ADDER_OUT_W (`ADDERS_IN_W+1) 

module adder_defines
(
...
input logic [`ADDER_IN_W-1:0] a,
input logic [`ADDER_IN_W-1:0] b, 
output logic [`ADDER_OUT_W-1:0] sum
);

Тот же пример с параметрами:

module adder_params #(
parameter int IN_W = 8, 
parameter int OUT_W = IN_W + 1 
) (
...
input logic [IN_W-1:0] a, 
input logic [IN_W-1:0] b, 
output logic [OUT_W-1:0] sum
);

Конфигурирование блоков может использовать любой из этих подходов. Современные симуляторы поддерживают изменение конфигурации любым способом при помощи опций командной строки. У каждого подхода есть свои преимущества. В случае define мы чуть ускоряем симуляцию — «развертывание» define идет на этапе элаборации, а параметры подставляются только на этапе компиляции. Кроме того, глобальная область видимости `define увеличивает гибкость: конфигурировать блок можно с любого уровня иерархии. Но при таком использовании инструмент становится очень опасным: контроль над конфигурацией можно легко потерять, в результате чего верифицируемая конфигурация IP будет отличаться от той, что инстанцируется на самом деле. Чаще всего так получается, когда конфигурацию начинают задавать внутри тестового окружения, а не в составе RTL.

Конфигурация RTL была причиной бага, который я отлаживала два дня на одной из прошлых работ. Сейчас эта история воспринимается как полезный опыт, но в момент дебага ситуация накалилась почти сразу, так как подходил срок выпуска финальной поставки RTL.

У меня был проект, где RTL конфигурировали с помощью define. Так было записано в том числе и пороговое значение для детектирования сигнала. Однажды утром я обнаружила, что все мои тесты упали, потому что в файле тестового окружения define переопределили на строковое значение. Поскольку этот файл зачитывался после файла с корректно заданным значением, в качестве порога использовался ASCII-код заданной строки, то есть полная ерунда. Практика code review с командой за океаном у нас по разным причинам не была развита, поэтому ломающее обновление сразу попало в основную ветку. Отлаживать такое непросто, поскольку, как я упоминала, у define не ограничен скоуп видимости. Проблемное значение нужно будет прослеживать по изменениям через симуляции, что может занять очень много времени.

В целом серебряной пули по конфигурированию RTL нет. Все зависит от сложности вашего IP, его целей и маршрута разработки, который у вас принят. Важно придерживаться единого подхода к конфигурации в разных командах. Или организовать передачу IP между командами таким образом, чтобы в состав поставки входил не только реконфигурируемый RTL, но и список конфигураций, который необходим для инстанцирования на верхнем уровне и верификации.

Мониторинг конфигураций в подсистемах

Верификаторы получают от разных команд блоки на разных уровнях подсистемы. Поэтому очень полезно иметь точную информацию о том, в какой конфигурации блоки инстанцируются в ту или иную систему. Я часто видела, что конфигурации блоков, спускаемых с верхнего уровня, неявно меняются через define и параметры, значения которых заданы через define.

По этой причине, чтобы узнать истинную конфигурацию IP-блока, нужно скомпилировать систему с уровня, на котором задается конфигурация. Например, конфигурация небольшого скремблера может быть получена только после компиляции всей подсистемы тракта цифровой обработки. Это вынуждает нас завязываться на исходники, которые не имеют отношения к нашему IP. Кроме того, отслеживание конфигурации становится трудозатратным: об изменении мы узнаем по факту, когда тесты упадут или верификационное покрытие неожиданно просядет.

Конфигурацией IP-блока в большой подсистеме почти невозможно управлять со стороны верификации. Но, если есть явный сабсет конфигураций, который мы проверили на верификации, или явно известна конфигурация для инстанса проекта, то при помощи SystemVerilog-утверждений в RTL можно явно проверять, что инстанцировна валидная конфигурация.

Действия при нарушения этих assertion можно обсудить внутри команды. Но даже простое сообщение в логе об использовании непроверенной конфигурации может сильно ускорить отладку. Верификатор сможет сразу переключиться на новую для него конфигурацию и перезапустить тесты, чтобы оценить пассрейт и покрытие.

Скорость симуляции

Третий бич верификаторов — скорость симуляции — с расширением проекта бьет все больнее. На больших подсистемах запускают нагрузки, близкие к целевым, например, загрузку ядра Linux.

Эффективное использование тестового окружения и возможностей симулятора позволит найти больше багов, не переходя к тестированию на аппаратных платформах: косимуляции, прототипах, FPGA или специальных эмуляторах. Скорость верификации на этих платформах выше в десятки раз, поэтому Linux можно загружать несколько часов, а не ждать неделю.

Однако возможности отладки у разных платформ ограничены, требования к инфраструктуре и квалификации инженеров выше, да и стоимость как у новенького «боинга». Про платформы тестирования и прототипирования для pre-silicon верификации вообще можно написать отдельную статью. Для нас же важно запускать в симуляторе как можно больше тестовых сценариев и получать результаты за разумное время.

На длительных целевых нагрузках начинается активная борьба за производительность, и верификатору важно управление скоростью симуляции. Разумеется, если у вас бесконечный проект, неограниченные сервера и вы любите сгонять за чаем после каждого запуска регрессии, этот раздел можно сразу пропустить. Мне в таком мире жить не приходилось :)

Возможный эффект от перехода на другие платформы

Возможный эффект от перехода на другие платформы

Размещение верификационных конструкций в RTL-коде

Очень хороший паттерн в RTL-разработке — использование SystemVerilog-конструкций assertion и coverpoint, которые проверяют корректность микроархитектурных решений. А также полноту тестовых сценариев: сформировать тестовые воздействия, чтобы «раскачать» схему и попасть в нужное состояние, может быть весьма непросто. Внутренние assertion и coverpoint позволяют не только проверить, что это произошло, но и подскажут разработчику и верификатору необходимый сценарий. 

Эти конструкции лучше размещать внутри RTL, поскольку верификатор может не знать обо всех деталях микроархитектуры. А если стратегия верификации подразумевает RTL как черный ящик, то и не должен знать.

Пример таких конструкций внутри модуля сумматора

module adder (
…
);

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            sum_reg <= '0;
        else
            sum_reg <= a + b;  
    end


`ifdef VERIFICATION_EN

    property p_sum_correct;
        @(posedge clk)
        disable iff (!rst_n)
        (sum_reg == a + b);
    endproperty

    assert property (p_sum_correct)
        else $error("[ASSERTION FAILED] sum_reg != a + b at time %0t", $time);


    covergroup cg_adder @(posedge clk);
…
        }
    endgroup : cg_adder

   cg_adder cg_inst = new();

    always @(posedge clk) begin
        if (rst_n) cg_inst.sample();
    end
`endif // VERIFICATION_EN

endmodule : adder

Здесь под define VERIFICATION_EN размещены две конструкции. Assertion проверяет, что суммирование происходит корректно , а covergroup обеспечивает проверку покрытия общих и краевых условий. Для обычного сумматора такие проверки могут быть избыточными. Но для модулей на 1000+ строк синтезируемого кода верификационная часть может сильно ускорить поиск и отладку краевых случаев. Поскольку define использует часть модуля под VERIFICATION_EN только для верификации, в ней допускается размещение несинтезируемых конструкций, которыми так славится SystemVerilog. 

Такое инвазивное размещение конструкций assertion и coverpoint также расширяет возможности для формальной верификации, особенно если использовать дополнительные конструкции — например, assume и restrict. 

Цели тестов могут быть разными, поэтому отладочные верификационные конструкции могут быть критически важны или не нужны вовсе. В последнем случае с ними лишь замедлится симуляция. Чтобы убедиться, что сценарий отрабатывает верно и нагружает что нужно, нам важно максимальное количество проверок и точек покрытия. Запуская большой набор тестов для отлова багов, мы можем отключить точки покрытия, но оставить assertion. Если далее мы запускаем еще бо́льший набор тестов на стабильном RTL с целью собрать покрытие, то наоборот: можем отключить assertion и оставить точки покрытия. А в очень сложных целевых сценариях типа загрузки Linux точки покрытия нам ни к чему.

Внимание к assertion

Утверждения (assertion) и точки покрытия интересны еще и тем, что их нужно уметь писать: для них предусмотрен специальный синтаксис. Вообще, SystemVerilog можно разделить на три огромных раздела: SystemVerilog Assertions, SystemVerilog Coverage и «основной» SystemVerilog — конструкции функциональной верификации. По каждому разделу можно найти немало книг и пособий применительно к функциональной и формальной верификации. Неумело описав assertion, мы можем получить драматическое снижение скорости симуляции и ничего взамен. Каждый цикл симуляции у нас будет срабатывать новый assertion и бесконечно ожидать своего завершения. 

Таким образом, помимо code review, очень хорошей практикой будет использование своего code style. В некоторых командах для assertion-конструкций даже используются специальные обертки define или обертки функций. Готовые обертки маскируют детали написания assertion. Например, можно объявить обертку, которая на каждом переднем фронте тактового сигнала будет проверять утверждение, переданное ей в качестве аргумента:

`define assert_clk( arg ) \ 
assert property (@(posedge clk) disable iff (!rst_n) arg ) 

ERROR_q_did_not_follow_d:  `assert_clk(q==$past(d)); 

Лейбл ERROR_q_did_not_follow_d позволяет однозначно найти в симуляторе или инструменте формальной верификации это утверждение. Опциями симулятора можно даже отключать утверждения по их лейблам. При отсутствии лейбла у утверждения или точки покрытия инструмент назначит их автоматически. Вот только ориентироваться в этих машинных именах будет гораздо сложнее.

Точно такие же обертки можно создать и для точек покрытия. Обертки удобны: они значительно сокращают количество строк кода и помогают при кодогенерации. Также они помогают избежать синтаксических ошибок. Как уже упоминалось ранее, синтаксис точек покрытия и утверждений специфичен. Есть конструкции, которые успешно зачитываются тулами и формально не нарушают стандарта, однако работают совсем не так, как кажется на первый взгляд.

Использовать утверждения и точки покрытия конструкций, как и точки функционального покрытия, в симуляционных запусках следует осознанно. На подсистемах среднего и большого уровня держать их включенными по умолчанию точно не стоит. Разве что у вас нет сроков сдачи проекта, зато есть бесконечные вычислительные ресурсы…

Актуальность утверждений и покрытия

Историю с assertion и покрытием продолжает поддержка этих конструкций в актуальном состоянии. Хотя код верификационных конструкций не является синтезируемым, разработчики тратят время на их создание и использование. Поэтому конструкции всегда должны соответствовать набору фичей и параметрам разработанного IP-блока. Иначе, если в симуляцию попадет ненужный assertion, мы вполне можем получить снижение скорости симуляции и километровые файлы логов — это в лучшем случае. А в худшем — баги, непокрытые точки и утверждения, которые придется разгребать.

Неопределенные значения

В стандарте SystemVerilog определены типы данных с четырьмя допустимыми значениями: 0, 1, x (не определено) и z (не имеет значения). Чаще всего используется тип logic. Неопределенные значения могут вводиться не только намеренно, но и при неаккуратном стиле кодинга. Их вызывают, например:

  • неинициализированные после сброса регистры,

  • операции, приводящие к неизвестным результатам,

  • некоторые нарушения синхронизации,

  • висящие провода,

  • провода с несколькими драйверами.

Все эти ситуации — потенциальные источники ошибок и разницы поведения дизайна в кремнии и в симуляторе. Появление неопределенности даже на один такт в одном из регистров может вызвать ее лавинообразное распространение по всему последующему конвейеру. Очень часто неопределенности возникают в операторах if, case или в условных присвоениях. Поиск неопределенных значений в регистрах и проводах можно реализовать набором утверждений, о которых шла речь выше. 

Современные симуляторы умеют работать с неопределенными значениями. Детали реализации обработки неопределенностей чаще всего не раскрываются, но стратегии обработки доступны в документации симуляторов. Обычно эти стратегии из пессимистичных прогнозов, согласно которым принимают решение о появлении X-значения. Часто режим обработки неопределенностей включен по умолчанию — его называют X-propagation.

Однако симуляция с учетом неопределенных значений достаточно требовательна к используемой памяти, а сама скорость симуляции заметно ниже. Для каждой переменной типа logic — а таких переменных подавляющее большинство — в каждый таймслот необходимо определить значение из четырех, а не из двух возможных. В IP среднего размера эта разница может быть не особо заметна, а вот на уровне большой SoC и сложных нагрузках снижение производительности симулятора может быть существенным. При этом, как и в предыдущих пунктах, предполагается, что переход к сложным долгим нагрузкам происходит при достаточно высокой зрелости RTL, когда ошибки, связанные с X-propagation, уже отлажены на более простых нагрузках.

Другие факторы

На скорость симуляции могут влиять и некоторые RTL-конструкции. В целом рекомендацию можно сформулировать так: используйте присвоения всей шине целиком, а не обращение к конкретным битам.

Однажды мне пришлось работать со сгенерированным исходником SystemVerilog, где нужно было выполнить операцию XOR над большей частью бит у 40-битной шины. Кодогенерации не составило труда реализовать XOR между десятком бит в явном виде. Выглядело это примерно так:

c_ecc_out_1= cin[29]^ cin[28]^ cin[27]^ cin[26] ^ cin[25] ^ cin[24]^ cin[23] ^ cin[22] ^ cin[21] ^ cin[20] ^ cin[19] ^ cin[18] ^ cin[17] ^ cin[16] ^ cin[15] ^ cin[14] ^ cin[13] ^ cin[12] ^ cin[11] ^ cin[7] ^ cin[4] ^ cin[1] ^ cin[0];

Гораздо быстрее в симуляторе отработает конструкция, которая использует маску и всю шину целиком:

c_ecc_out_l = ^ (cin & 40'h003ffff893);

Другой пример — использование конкатенации вместо операции сдвига. В примере два 48-битных вектора используют битовый сдвиг, который неявно указывает симулятору значение нижних бит:

c_v = c_s << 8

В случае конкатенации нижние биты указаны явно и будет обработано симулятором быстрее:

c_v = { c_s [39:0], 8'h00 };

Code style

Использование линтов

Такие инструменты, как Synopsys Spyglass, а также open source линты — например, у AMIQ Verissimo или симулятора Verilator — помогают найти некоторые типичные ошибки, которые проявляются на функциональной симуляции. Например, если подключить провода различной ширины, на функциональной симуляции часть битов при передаче из одного провода (модуля) в другой будет потеряна и данные в чекпойнтах не сойдутся.

Линты умеют подсвечивать эти проблемы и оценивать их критичность в зависимости от своих настроек. Важно не игнорировать эти ошибки, а разбирать их до передачи RTL на функциональную верификацию. Да, линты могут выдавать ошибки, не актуальные на текущей стадии проекта, но их можно фильтровать с помощью настроек severity и осознанного написания исключений.

Уровень сложности блока

Уровень сложности верифицируемого блока не должен меняться в пределах этого блока. Все особенно сложные компоненты — перемножители матриц или пересинхронизаторы для перехода из одного тактового домена в другой — лучше выносить в отдельные модули и инстанцировать их по необходимости.

Иногда такие компоненты просто размазывают по блоку, где они используются. Но если выносить их отдельно, это может дать большие преимущества в стратегии верификации. Вынесенную в отдельные модули сложную логику можно проверифицировать отдельно. Это позволит лучше отработать краевые случаи, ведь сгенерировать их в составе более крупного блока, где уровень абстракции может быть намного выше, явно сложнее.

Если компоненты все-таки размазали, это тоже не конец света. Но при верификации может потребоваться больше времени и деталей реализации блока. Подхода с черным ящиком может оказаться недостаточно, и в ход пойдут разные возможности подглядывания в дизайн. SystemVerilog предоставляет такие возможности конструкциями force-release. Однако их использование — это крайняя мера для отладки, в регулярные запуски их включать не стоит.

Наконец, вынесение сложных блоков в отдельные модули дает преимущества и для формальной верификации. Изменения в небольших блоках можно проверять формально, что позволяет быстрее проверять и интегрировать изменения через меньший набор проверок. 

Опции симулятора

Однажды мы верифицировали цифровой дизайн, и при этом у нас был небольшой трек по запуску некоторых сценариев на gate-level уровне — когда мы запускаем сценарии верификации не на RTL-коде, а на уровне логических примитивов. Примитивы сами по себе редко используются в написании RTL. Список примитивов и их соединений генерируется после синтеза и передается инструментам Place&Route для создания топологии. Такой список называют нетлистом (netlist). Его особенность в том, что логические примитивы вносят задержки, которые отсутствуют при моделировании RTL.

Анализ задержек можно проводить инструментами статического временного анализа (STA), и в большинстве случаев этого достаточно. Однако в некоторых специфичных случаях моделирование нетлиста может дать подсказку по оптимизации RTL, чтобы задержки сошлись. Если STA проходит, то ожидается, что результаты запуска функциональных тестов на RTL и его нетлисте различаться не будут. 

Но у нас тесты с ходу не сошлись, а начали падать на gate-level уровне. Мы, конечно, начали грешить на задержки, внесенные логическими примитивами, и копать в эту сторону. По факту, проблема оказалась гораздо проще: опции симулятора в двух запусках не соответствовали друг другу. После выравнивания опций симулятора результаты сошлись.

Чтобы написать качественный RTL, вовсе не нужно знать все опции симулятора. Но полезно помнить, что опции симулятора могут быть причиной расхождения в некоторых случаях специфичного дебага, когда результаты тестирования на разных уровнях абстракции или коммитах не совпадают, хотя вроде бы и должны. Опции симулятора могут кардинально изменить результат симуляции.

В целом я считаю, что любой инженер должен быть заинтересован в изучении любого инструмента, который использует в разработке. Это позволит повысить качество кода, скорость отладки и итоговой поставки.

Vendor-specific директивы

Метакомментарии — это обычные комментарии с префиксом // или в скобках /* …*/, которые передают специализированную информацию инструментам EDA-разработки. Информация эта, как правило, выходит за рамки того, что может быть передано в рамках семантики SystemVerilog. Обычно она содержит простые переключатели «вкл/выкл» или настройки режимов инструментов. Выглядит это следующим образом:

// synthesis_off 
<some SV code>
// synthesis_on

В коде на Verilog я видела и более экзотический пример, в котором симулятору явно указано использовать четыре возможных состояния для конкретной переменной, даже если опциями симулятора и стандартом задано другое:

wire /*4value*/ [31:0] tri_data;

Использовать метакомментарии нужно аккуратно, всегда сохраняя возможность полностью от них избавиться. С ними мы становимся зависимы от своих вендоров и инструментов. Нельзя будет гарантировать повторяемость результатов в других инструментах и маршрутах верификации. Внутри команды вы, конечно, вряд ли измените маршрут разработки без предварительного обсуждения с командой. Однако директивы могут сыграть злую шутку при передаче разработанного IP заказчику, использующему другие EDA-инструменты.

Помимо вендор-лока, метакомментарии опасны тем, что могут неявно изменять конфигурацию запускаемого инструмента, что чревато трудоемкой отладкой. Конечно, вы можете принять такие риски, но я бы советовала либо реализовать механизм отключения всего, что зависит от вендора, либо вовсе к такому не прибегать.

Унификация code style всего RTL

RTL-разработкой могут заниматься разные команды. Потом результаты их работы интегрируют и передают получившуюся большую систему на верификацию. Мы прогоняем тесты и начинаем отладку ошибок. Когда у всех RTL-команд проекта предусмотрен единый code style, отладка сильно упрощается. В едином коде гораздо проще ориентироваться, особенно во время отладки при переходе между блоками, что часто приходится делать при первичном анализе проблем.

Однажды я участвовала в верификации подсистемы, куда был проинтегрирован блок, разработанный сторонней командой. В блоке были и assertion, и coverpoint — в общем, вся инфраструктура для верификации. Но когда мы включили assertion и запустили тесты, у нас просто не скомпилировался RTL. Мы даже не дошли до запуска тестов.

Впоследствии выяснилось, что assertion стороннего блока использовали внутренний code style команды разработки, который явно разрешал написание assertion, не соответствующих стандарту SystemVerilog, но при этом поддерживаемых в их симуляторе. А при запуске у нас, в другом симуляторе, все упало. 

Симуляторы по-разному относятся к нюансам стандартов. Например, Synopsys VCS позволяет себе больше вольностей, а Cadence Xcelium сразу наказывает за ошибки. В некоторых симуляторах можно самостоятельно настроить эту строгость в соответствии со стандартами SystemVerilog. Однако пользоваться этой возможностью стоит только в крайнем случае — например, при интеграции стороннего IP. Внутри команды лучше воспитывать инженерную культуру и минимальную толерантность к ошибкам. Допустив отход от стандарта, никогда не знаешь, в каком месте это выстрелит. 

Заключение

Рынок диктует свои правила скорости выхода на рынок для полупроводниковых продуктов и выполняемых ими задач. Процесс и проблемы верификации цифровых схем масштабируются не так быстро, потому что здесь сходится много независимых треков: разработка требований, RTL-дизайн, моделирование, инфраструктура. Поэтому крайне важно стремиться оптимизировать и улучшать верификационные процессы. В том числе путем внедрения методологий и правил в процессы других команд. Это позволит сократить время разработки и вывода продукта на рынок, одновременно повысив уровень уверенности в его качестве и надежности.

Если вы занимаетесь верификацией, обратите внимание на наши вакансии — для разных уровней и в разных рабочих группах: