Перейти к содержанию
    

dxp

Свой
  • Постов

    4 600
  • Зарегистрирован

  • Посещение

  • Победитель дней

    18

Весь контент dxp


  1. Ещё пять копеек. Дешёвая ПЛИСка (Gowin, какой-нить), на которой скрафтить желаемое количество МАС'ов, и любой МК по вкусу, лучше с аппаратным контроллером памяти, чтобы отмапить доступ к внешним МАС через шину памяти. Просто ещё один вариант со своими + и -.
  2. Проект jupyter позволяет написать приложение, в которое внедряется ядро (jupyter kernel), позволяющее иметь полный контроль (инспекцию) надо всеми потрохами приложения в реальном времени через jupyter console. Мы таким образом делали прогу, которая качала видеопоток с камеры, производила его анализ и обработку. Тяжелые в вычислительном плане функции были написаны на C/C++ и подключены через boost::python. Сама прога была реализована с помощью PyQt. Собственно, цель была в упрощении разработки алгоритмов обработки видеопотока в камере (тепловизор). Камера включалась в bypass режим, когда "сырой" поток значений пикселов с сенсора лился на РС, а тут это программа его обрабатывала в реальном времени, корректировала ключевые параметры видеотракта и управляла сигналами сенсора, подстраивая его. Поэтом отработанный, отлаженный алгоритм портировался на "железо" (ПЛИС+набортный процессор). Внешне это выглядело так. Запускается программа (PyQt), появляются её окна (картинки на разных этапах обработки видеотракта) и запускается консоль (jupyter console). В любой момент можно командой через консоль включить, выключить что-то, поменять значение того или иного параметра или вывести в цикле и наблюдать динамику изменения параметров видеотракта (да вообще любых объектов в программе). Можно, например, дать команду сграбить эн кадров (хоть тыщу), и потом спокойно их анализировать, обрабатывать через интерактивный режим Python в jupyter. К примеру, посмотреть шумы отдельных пикселов во времени (поиск аномально ведущих себя элементов приёмника -- для тепловизионных это обычное дело). Ну, и всякие гистограммы, профили строк или столбцов на разных уровнях экспозиции смотреть -- в общем, тут только фантазия и потребности ограничивают. Доступ ко всем объектам в реальном времени без останова программы. Очень эффективный и мощный метод разработки оказался: по сути программный видеотракт (software-defined) с полным доступом к потрохам (инспекция и контроль). Понятно, что это можно использовать с любыми приборами: получаешь работающую железку с полным доступом к внутренностям в реальном времени и мощным фремфорком для анализа и обработки. До этого варианта был ещё написанный на Qt (честный С++), но там работать было не очень удобно -- доступа такого не было, если что-то надо сделать, то это сначала написать, скомпилировать, запустить. В итоге интерфейс управления через консоль начинал обрастать и становится едва ли не сложнее самой программы. Это и натолкнуло на идею переписать на Python (PyQt), чтобы облегчить/ускорить процесс обновления программы. Ну, и попутно предпринимались попытка как-то скрестить это с мегаудобным IPython. Так набрели на эту тему с внедрением jupyter kernel. По производительности вариант на чистом Qt и этот на PyQt+jupyter kernel оказались почти эквивалентными (системный монитор загрузки CPU показывал одни и те же значения ±1%) -- это в основном благодаря тому, что все тяжёлые функции были вынесены на уровень C/C++ и numpy, а Python был в своей основной роли orchestration language.
  3. При логических операциях целые неявно приводятся к булевому типу и потом выполняется операция. Та же логика действует в обычном: int x = ...; ... if(x) begin ... end
  4. Название темы опровергает ваш тезис. Проблема? За несколько лет интенсивного использования и не догадывался, что это проблема. Запускать сборщик заново? Это проблема? svh файлы генерируются за доли секунды. Если их содержимое не изменилось (сборочный тул проверяет это по хэшам), то дальнейшая цепочка сборки не выполняется. Что касается времени выполнения, то процесс компиляции по сравнению с прогоном на рантайме по длительности отличается на пару порядков (1-2 минуты компиляция, час-полтора прогон). О какой экономии тут речь? Генерация нетлиста занимает дни? Это что за процесс такой? Боюсь спросить, а сколько времени занимает прогон тестов этого нетлиста? Месяцы? А если под генерацией нетлиста подразумевается синтез и PnR, то это совсем другая история. C DPI тоже дружим, но по другому поводу -- связь с инструментарием внешнего (по отношению к симулятору) мира.
  5. Не ведаю, что такое "иерархичность yaml-дерева", даже к стыду не знаю, что такое "yaml-дерево". Если имеется в виду, что значения словаря может в свою очередь тоже могут являться ключом для другого словаря, то для определения параметров этого не надо. Гораздо важнее возможность вычислять значения параметров на основе других (определённых выше) и импортировать другие yaml файлы с параметрами, которые так же можно использовать при вычислениях (что штатное "yaml-дерево" не поддерживает, т.к. это просто формат хранения). И это у нас есть. Не лучше. Не знаю, что там написано на С++, но на Python такие вещи делаются куда проще: и пишутся, и читаются, и сопровождаются. А DPI -- это симулятор онли. У нас же эта система параметров используется в первую очередь для обслуживания синтеза, включая генерирование IP ядер, создание проекта синтезатора (Vivado), компиляцию HLS модулей и применение параметров общего назначения, из которых генерятся не только svh заголовки для SV, но и tcl файлики для симулятора и синтезатора. Вся кухня работает по зависимостям, т.е. лишней работы не делается. И зачем рантайм конфигурация, если это можно сделать на этапе компиляции? Рантайм нужен там, где по-иному не получается или неэффективно (негибко, громоздко). В случае заранее заданных параметров всё известно на этапе компиляции. На рантайме симулятору и другой нагрузки достаточно.
  6. Если оно работает, так ли важны читаемые? И, насколько знаю, сорцы стоят куда дороже, чем просто исполняемая библиотека. IP нередко вообще в зашифрованном или обфусцированном виде продают. Для читабельного варианта, да, не вариант. 🙂 Но в остальном норм. И, наконец, есть сорцы на С++ исходника, по которым понять алгоритм намного проще. И моделировать тоже.
  7. Если ошибка в симуляционном прогоне, то, например, квеста возвращает таки 0. Не 0 она возвращает, когда именно ошибка работы самого симулятора -- файл не найден, ресурс недоступен и т.п. И мне как раз понадобилось, чтобы симулятор возвращал не 0, когда именно ошибка при прогоне теста -- чтобы сборочная система останавливалась, не пыталась дальше собирать проект. Ничего лучше не придумал, как передавать код ошибки через файл. Дак HLS выдаёт синтезируемый Verilog, его и брать. Там проблемы ровно те же, что и портировании FPGA сорцов под ASIC -- замена блоков ПЛИС на ASIC'овские (блоки памяти, аппаратные блоки и т.п.).
  8. А это, часом, не Y-конденсатор? Это к вопросу, почему именно такое исполнение.
  9. Сомнительно. Объекты const должны обеспечивать взятие адреса и находиться в том же адресном пространстве, что и остальные объекты памяти. А flash (progmem) в AVR -- это другое, отдельное адресное пространство.
  10. В чистом С вам придётся в каждой структуре хранить указатель (vptr) на массив указателей (vtbl), создавать для каждого типа структуры этот массив, правильно инициализировать его. Адресом этого массива нужно проинициализровать vptr в каждой структуре, не перепутав где чей массив указателей. Вызов этот будет выглядеть как цепочка разыменовываний с вызовом в конце. И т.д. Тут немалое поле для ошибок. Вместо профита это будет выглядеть как микрофилиал ада. В С++ это ООП сводится к определениям и вызов - одна строчка. Одинаковая вне зависимости от конкретного типа и объекта. В этом суть полиморфизма - вид один и тот же, а поведение разное. И компилятор тут не ошибается, делает всю эту путанную рутину на раз. Кроме того, наследование даёт возможность нативно и прозрачно расширять функциональность. На С вам придётся либо переписывать руками код, либо включать в структуру структуру-"предка" в качестве члена, а это порождает для неё дополнительный уровень иерархии там, где он совсем не нужен. Ну, а так и С тогда "синтаксический сахар" для ассемблера. 🙂
  11. Раз "пошла такая пьянка", то ещё пять копеек. Классы сами по себе - не ООП. Классы - это объектный подход. Это инкапсуляция, абстракция, это возможность выражать объектами сущности реального мира. А ООП - это иерархии классов с наследованием, виртуальными функциями и т.п., т.е. повторное использование кода и динамический полиморфизм, достигаемый с помощью методов (виртуальных функций). С++ является надмножеством С с натяжкой. Это таки разные ЯП с разными стандартами, есть прямые несоместимости. С++ является в известном смысле потомком С, поэтому унаследовал основы синтаксиса и процедурную парадигму программирования. Но в целом это другой ЯП, который помимо процедурной парадигмы нативно поддерживает ещё две: объектную и объектно-ориентированную. Благодаря объектному подходу у программиста появляется возможность оперировать программными сущностями как аналогами объектов реального мира. Т.е. если программист хорошо знаком с предметной областью (а это необходимое условие для качественного результата), то он может строить программу как модель реального мира. Например, можно взять листок бумаги и нарисовать структурную схему того, что должна реализовать программа: при этом "квадратики" объектов схемы - это классы, а стрелочки, соединяющие "квадратики" - это открытые (публичные) функции-члены классов - интерфейс классов. Таким образом, фактически получается "скелет" программы, можно начинать писать код, наполняя в дальнейшем классы деталями реализации. Этот подход разительно отличается от принятого в С. С++ своими средствами (классы, инкапсуляция и абстракция) его провоцирует, а в С нужно предпринимать усилия (как приводилось выше: размещать код в структурах, явно передавать "this" и подобный "закат Солнца вручную", а главное - нет реального сокрытия деталей реализации и отделения интерфейсов от реализации). Переход от Сишного подхода к С++ному проходит не совсем просто (у всех по-разному), тут нужна некоторая ломка стереотипов при переходе от процедурного подхода к объектному. Но потом доминирующим становится объектный, как более высокоуровневый. Объектно-ориентированный подход - это уже средство следующего уровня, он позволяет строить более сложные программы на уровне архитектуры и системы. Главное, что он даёт - это возможность нативного расширения функциональности (наследование) и эффективное управление большим количеством "родственных" объектов (иерархии классов) через динамический полиморфизм. Все три подхода хороши в своих нишах. Процедурный - на уровне реализации кода функций. Объектный - на уровне "сущностей" программы. Объектно-ориентированный - на уровне системы. Выражаясь военным языком: процедурная парадигма - это тактический уровень, объектная - оперативный, объектно-ориентированная - стратегический (с известной натяжкой, конечно). Главная проблема тут - неправильное применение средств по отношению к контексту. Например, когда начинают пихать классы где надо и где не надо или (особенно это) лепить иерархии классов там, где они не нужны, из-за чего получается сложная, плохо управляемая и трудно понимаемая программа. Особенно этим страдают новички, которые познакомившись с тем или иным средством языка, пытаются его применить любой ценой. Опытный программист как раз в первую очередь отличается от неопытного тем, что хорошо знает, чувствует, где какое средство адекватно или нет, поэтому не совершает подобных ошибок, которые всегда стоят дорого - вплоть до необходимости переписывать программу заново.
  12. Тоже имели проблемы с позолоченными пятаками при пайке BGA. Тоже на флюс (Flux-plus), никогда до этого проблем с таким способом монтажа не имели. А тут приехали платы с позолотой, хотя требования такого не было - по умолчанию у них там HASL стоит, всегда им ограничивались, но тут кто-то проявил ненужную инициативу. И в итоге сразу же на первых трёх пайках получили проблемы - снимаешь микросхему, там порядка 30% пятаков остались золотыми. Обезжиривание не помогло. Может, конечно, более точная дозировка флюса решила бы проблему, но в конечном итоге просто аккуратно облудил пятаки, и остальные платы (порядка десятка штук) запаялись без проблем. Пайка во всех случаях (как и до этого и после этого) велась в конвекционной печке с термопрофилем. Я так понял, что эти позолоченные пятаки правильно паять всё же с помощью пасты - когда паста нанесена прямо на пятаки, они гарантировано смачиваются, и тогда уже проблем с соединением шаров нет. В дальнейшем во избежание всегда явно указывал тип финишного покрытия явно (HASL - шаг шаров 0.8, 1.0 мм, золото актуально для более мелких шагов выводов, там где требования по плоскостности более высокие).
  13. gcc slon.c -Wpointer-sign slon.c: In function ‘main’: slon.c:9:10: warning: pointer targets in assignment from ‘signed char *’ to ‘char *’ differ in signedness [-Wpointer-sign] 9 | p_char = p_schar; | ^ slon.c:10:10: warning: pointer targets in assignment from ‘unsigned char *’ to ‘char *’ differ in signedness [-Wpointer-sign] 10 | p_char = p_uchar; gcc slon.cpp slon.cpp: In function ‘int main()’: slon.cpp:9:12: error: invalid conversion from ‘signed char*’ to ‘char*’ [-fpermissive] 9 | p_char = p_schar; | ^~~~~~~ | | | signed char* slon.cpp:10:12: error: invalid conversion from ‘unsigned char*’ to ‘char*’ [-fpermissive] 10 | p_char = p_uchar; | ^~~~~~~ | | | unsigned char* В С режиме получили предупреждение. Но только если указать -Wpointer-sign, иначе молча проглатывает. По сути в С тип char является "гипотетическим" и "полиморфным", ведущим себя либо как signed char, либо как unsigned char. И как абстрактная сущность он отличается от конкретных signed char и unsigned char. Предупреждение тут уместно скорее именно как предупреждение, чтобы не использовали char там, где нужны числовые типы, а не символьные. В С++ режиме без всяких -W и прочего сразу по умолчанию ошибка. Потому что тут char -- отдельный самостоятельный, конкретный тип. По-моему, разница в поведении компиляторов более чем очевидна.
  14. (что уже как бы намекает, что это разные типы, раз их перечисляют), но Вы почему-то отрицаете это: ладно, стандарты нужно трактовать однозначно, поэтому (там же) 17 пункт говорит, что char - это целый тип. 14 пункт говорит, что char, а так же любые знаковые и беззнаковые целые (т.е. signed / unsigned char в том числе (см. 17 пункт)) - базовые типы. И в не зависимости от реализации и их (возможно) одинакового представления - они являются разными типами. Все еще не однозначно? Разумеется нет. 🙂 Из этих всех фраз следует, что char относится к целым типам, что char относится к базовым типам, но ни разу не следует, что char, signed char и unsigned char являются разными типами. В п.15 прямо говорится, что тип char при реализации фактически является либо signed char'ом, либо unsigned char'ом. Единственное что как-то более-менее явно указывает на то, что char является отдельным от других типом, -- это упомянутая вами сноска (там присутствует слово Separate). Но по смыслу это, имхо, противоречит п.15. А однозначно -- это в стандарте С++: "Plain char, signed char, and unsigned char are three distinct types". И не в сноске, а в основном тексте. Если в С так же, что мешало именно так и написать?
  15. В чём вы видите противоречие? Что char чаще по умолчанию знаковый? Реализация имеет право. А по-хорошему приличный компилятор должен выдавать предупреждение, когда char используется в арифметике.
  16. Строго говоря, текст сноски противоречит смыслу основного пункта. В сноске сказано, что, типа, char является отдельным типом, но в основном пункте сказано, что его поведение или как у знакового, или как у беззнакового, а если это так, то он сам по себе никаких отдельных свойств не несёт и по сути является псевдонимом signed char или unsigned char. Ну, и странно, что такую важную вещь написали где-то в сноске мелким шрифтом. В С++ это прямо сказано в основном тексте без намёков и экивоков.
  17. IAR -- это и С, и С++ компилятор. Режим зависит от параметров запуска. В каком режиме запустите, такое поведение и будет. И оно по факту разное даже согласно базовым документам (стандартам). Если IAR не соблюдает указанное поведение, то это баг. Давно с ним не работал, ничего сказать не могу.
  18. Из вашей цитаты это не следует. Тут сказано, что тип char, знаковые и беззнаковые целые типы и типы с плавающей точкой являются основными типами. Никаких заявлений про signed char, unsigned char тут нет. А вот следующим пунктом говорится Т.е. реализация должна определить тип char того же диапазона, представления и (самое главное) поведения, что либо signed char, либо unsigned char. Т.е. char в С по факту всегда либо знаковый, либо беззнаковый. Некоторые компиляторы (тот же IAR) предоставляют выбор пользователю в этом вопросе. А вот в С++: Т.е. явно и непосредственно сказано, что это три различных типа. По смыслу char нужен для хранения представления символов, а signed char и unsigned char -- это по сути целые малой разрядности. Поэтому для строк и символов рекомендуется использовать char, а для чисел singed char и unsigned char. Имхо, С++ в этом вопросе логичнее, чем С. В С так сложилось исторически, и менять уже, не ломая совместимость, они не могут.
  19. В С знаковость char зависит от реализации. В С++ сhar, signed char и unsigned char -- это три разных типа.
  20. Тут говорится о навыках работы с электронной техникой -- это печатные платы, умение перерезать дорожку, кинуть перемычку, снять-поставить элемент и т.п. Т.е. то, что применяется при реверсе изделия. Требование знаний схемотехники тоже говорит за это. С чего взяли, что тут речь про микросхемы? Микросхемы -- написали бы "микроэлектроники". Электронная техника -- это то, что разрабатывает большинство участников этого форума: схемы, печатные платы, фирмварь, сопутствующий софт. А в микроэлектронике и схемотехника специфичная, и больше надо знать особенности конструирования ИМС, топологию, технологии изготовления и т.п. Это совсем другая тема, чем обычная традиционная схемотехника, ориентированная при применение ЭКБ. Инвазивный -- подразумевающий вмешательство. Т.е. взяли прибор, вскрыли корпус, начали тыкать тестером/осциллографом, перерезали дорожку, посмотрели, что изменилось, сняли элемент, снова посмотрели -- всё с целью понять, как работает, чтобы потом повторить (в данном случае).
  21. В Vivado есть требование к определённой версии симулятора. Например, 2018 требовала квесты (если квесты) 10.6с, и любая другая версия порождала предупреждение. С квестой 10.4а не работало -- не могла квеста расшифровать secureip библиотеку. Но вот 10.4е уже могла, и хотя предупреждение оставалось, всё работало. И даже если подсунуть квесту 10.7с. то всё равно предупреждение (и тоже всё работает). Т.е. Vivado проверят на точное совпадение. Хотя ключи там меняются не так часто, и реально весьма широкий диапазон версий симуляторов работает с криптованными библиотеками. И да, по убунтой Vivado и Questa прекрасно работают. А для Vivado убунта прямо указана в поддерживаемых ОС.
  22. MR, кстати. необязательная вещь, вполне несложно и руками сливать, тут нужно просто аккуратность и некоторая дисциплинированность. Это может делать любой член команды самостоятельно. Но люди неидеальны, и всегда хватает раздолбаев, которые регулярно будут ломать общую кодовую базу -- не по умыслу, по недосмотру/лени. Если каждый участник группы перед заливкой выполняет вот такой проверочный прогон, то всё ок. Проблема в том, что на практике этого не происходит -- люди забывают, а некоторые забивают на это (в open-source это просто непреодолимая проблема в принципе). Поэтому ограничение по записи в общую ветку является просто предохранительной мерой. В итоге, в базе всегда лежат хорошие комиты, и история этой ветки не замусорена горбатыми комитами, а красиво подчёркивает фичи/фиксы с помощью комитов слияния. Ну, а MR используется просто потому, что оно есть в софте -- как средство уведомления и как средство слияния. Безо всяких проблем сливать можно и руками (git merge --no-ff -e <branch> всего-то делов). И вообще, для этой операции и человек-то не нужен -- можно скрипт написать, который будет брать MR, прогонять, если успех, сливать в общую ветку. Но мы пока не достигли ощущения необходимости автоматизации на таком уровне.
  23. Речь не про то, что всё работает в продукте, а про то, что оно не ломается на сборке. Когда ломается на сборке -- это просто мешает остальным работать с этой базой. Первый человек влил вчера вечером, а сегодня он в отпуске. Сборка сломалась потому, что человек недосмотрел и забыл просто исходный файл добавить в реп -- человек, в общем-то, квалифицированный и ответственный, но недосмотрел, бывает. Теперь (сегодня) его физически нет (уехал на Алтай), проект не собирается из-за отсутствия файла в репе. Вся остальная команда (8 человек) не может пользоваться этой кодовой базой -- приходится извращаться, откатываться на предыдущие стабильные комиты. И это простой случай, который лечится на раз -- и диагноз сразу ясен, и метод лечения тривиален. А бывают варианты похуже, когда при слиянии конфликты возникают, неправильное разрешение которых ломает логику работы. Поэтому в нашей группе мы делаем заливку в общую ветку только через merge request: к записи в эту ветку имеет доступ один человек, он, получив MR, просто запускает прогон: общий функциональный тест, цель которого выявить ошибки типа "отсутствует файл", правильность соединения модулей на топе, какое-то минимальное тестирование проекта в сборе, идёт тест недолго, после чего проект запускается на синтез -- идёт проверка целостности другим тулом. PnR не делается, т.к. это долго и на этом этапе не нужно, т.к. цель -- обеспечить целостность кодовой базы, чтобы любой член группы мог в любой момент взять из общей ветки топ и стоить на нём свою фичеветку, будучи уверенным, что его работа не станет колом, из-за чужих ошибок. Описанное -- это ещё не CI. CI идёт следом по цепочке -- там полная сборка и расширенный набор тестов (в перспективе и в железе на стенде). Здесь же главное -- не сломать сборку и тем самым не тормозить работу других членов группы. А то, как процесс встаёт колом, я повидал. В других подразделениях (программеры) исповедуют как раз описанный вами подход: все без ограничений льют в общую ветку и регулярно ломают сборку. Бывало, что не могли неделями привести в стабильное состояние -- одни багованные фичи накладывались на другие и разгрести это оказывалось не так просто. Коллега, который с этим работал, в итоге за три недели не дождавшись стабильного топа общей ветки, просто взял какой-то старый комит и пилил временно на основе него -- ему не нужны были эти новые правки, которые ломали сборку. Матерился, конечно. Если бы у них был вот этот этап предварительной проверочной сборки (просто на собираемость), когда проблема обнаруживается ещё до вливания кода в общую ветку и борьба с ней идёт в локальной фичеветке, то этого безобразия просто не было бы. Элементарная дисциплина -- нерабочие, непроверенные на целостность собираемости правки не попадают в общую базу, которая является стартовой точкой для новых фич/фиксов для всех членов группы.
×
×
  • Создать...