воскресенье, 12 ноября 2017 г.

Анонимный доступ в Samba

Как настроить полностью анонимный доступ к Samba сервису

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

[global]
workgroup = FAMILY
server string = Cubie Samba Server
dos charset = cp1251
unix charset = utf8
dns proxy = no
security = user
browseable = yes
log file = /media/other/samba/smbd.log
syslog = 0
map to guest = Bad Password
guest account = nobody
browseable = yes

[shared]
comment = Guest access share
path = /media/samba/shared
browseable = yes
read only = no
guest ok = yes
writable = yes
public = yes
available = yes

Комментировать тут особенно нечего, поэтому если кому-то понадобится, пользуйтесь на здоровье.

четверг, 9 ноября 2017 г.

Десериализация в ASP NET Core 2.0

Будни кросс-платформенного Web от Microsoft

ASP NET Core базируется на платформе NET Core, которая, в свою очередь является кросс-платформенной, на данный момент доступна версия 2.0.х (у меня NET Core работает, что под Windows 7, что под Linux Mint 18).  Сам ASP NET Core включает в себя Entity Framework, Json Converter (от Newtonsoft), IoC и т.п. Сегодня пойдет речь о работе с Json, точнее о том, что я в итоге получил.

Приколы с POST и PUT и десериализацией из Json

Предположим у нас есть два проекта в солюшене, пусть они называются ClickPlatform.Dto и ClickPlatform.Mvc. В первом у нас объявлены классы Dto - объектов, а вот втором - Web API с набором контроллеров с методами (Get, Post, Put и Delete для обработки одноименных HTTP-методов и действий).

У нас есть следующий класс Dto:

    public class Listing
    {
          public Listing() { }

          public Listing(Guid id, string name, AdShortInfo[] linkedAd = null, string status = null,                                              TotalStatistics stats = null)
          {
               Id = id;
               Name = name;
               LinkedAd = linkedAd;
               Status = status;
               Stats = stats;
          }

          public Guid Id { get; set; }
          public string Name { get; set; }
          public AdShortInfo[] LinkedAd { get; set; }
          public string Status { get; set; }
          public TotalStatistics Stats { get; set; }
    }

Понятно, что для получения объекта и коллекции объектов используем Get-методы, с сериализацией тут все ок, все хорошо работает. и мы получаем либо коллекцию объектов, либо отдельный объект по id. Чудеса начинаются при использовании методов Post и Put внутри следующего контроллера

    [Produces("application/json")]
    [Route("api/[controller]")]
    public class ListingController : Controller
    {
        .// ...
       
        [HttpPost]
        public void Post([FromBody] Dto.Internal.Listing listing)
        {
    _listingManager.Create(listing);
        }

        [HttpPut("{id}")]
        public void Put([FromRoute]Guid id, [FromBody]Dto.Internal.Listing listing)
        {
            _listingManager.Update(id, listing);
        }
       
        // ...
   }

   Пробуем дернуть Post при этом устанавливаем content-type=application/json и charset=utf-8. и передаем следующий json: {"id":"","status":"active","name":"Evil_One","linkedAd":[], "stats":""}


Точка останова показывает нам, что наш объект - null.


Если мы поставим object, то получим следующее:

[HttpPost]
public void Post([FromBody] /*Dto.Internal.Listing*/ object listing)
{
     //_listingManager.Create(listing);
}


Теперь объект в теле определился, получается, что Json не может десериализовать объект в Dto.Internal.Listing. Почему же так происходит?  Все дело оказывается в том, что если для value type значение в Json не задано, то считается, что там null, а null нельзя использовать для value-типов, поэтому приходится везде ставить Nullable<T>. В вышеприведенном коде поменяет  свойство Guid Id {get; set;} на Guid? Id {get; set;}. И теперь смело можем передавать запрос со значением ""  в качестве Guid

При этом сам Newtonsoft.Json не соизволил проинформировать о том, что он не может десериализовать тип. Что ж вот такая она десериализация объектов в Asp NET.

Послесловие (послевкусие)
Попробовал я ASP NET Core и не могу сказать, что это супер платформа, не могу сказать, что это именно то, что нужно для разработки. В ней вроде как бы все есть, но что-то в ней не так. Многие вещи кажутся странными: как например молчаливая обработка ошибок, подтягивание Nuget пакетов для самых очевидных вещей вроде System.Data и многое другое. Если сюда добавить работу только на VS17 (на мой взгляд, худшая студия начиная с 2003, даже 2010 была лучше).





понедельник, 4 сентября 2017 г.

Как начать работать с HDL и ПЛИС (FPGA)

Предисловие

Планирую написать ряд статей, про внутреннее устройство ПЛИС и их программирование. В данном сообщении я планирую дать направление читателю, что нужно прочитать для того, чтобы начать разрабатывать для ПЛИС.

Современные тенденции

К сожалению, а может быть и к счастью (в зависимости как на это посмотреть) разработка современной электроники, особенно цифровой, но не только сводится к описанию цифровых функций и автоматов сводится к описанию их на основе одного из HDL (Hardware Description Language) -языков описания аппаратуры. На данный момент, существуют следующие языки описания аппаратуры: AHDL, VHDL, Verilog и System Verilog. Сами ПЛИС (CPLD, FPGA) представляют собой квадратные матрицы ячеек (состоящих из сотен - тысяч, в зависимости  от ресурсов ПЛИС, логических элементов), к этим ячейкам подходят магистрали источников синхросигналов (клоков) и линий питания (+5 или +3,3 В) и земли.  К слову говоря, современные ПЛИС (7 серия от Xilinx, 5 поколение Cyclone и т.п.) - это SoC в которых кроме, самой ПЛИС присутствует процессорное ядро и аппаратная поддержка различных интерфейсов таких, как : USB, Ethernet, CAN, SPI, I2C, RS232 и др.

Три кита разработки цифровых устройств с использованием ПЛИС (FPGA)

 1. Основа всего это алгебра логики (булева алгебра) и способы построения простых цифровых схем и автоматов с использованием алгебры логики.

2. Схемотехника входных и выходных каскадов логических элементов (для понимания, что такое высокоимпедансное Z-состояние, нагрузочные характеристики элементов, схемы с открытым коллектором).

3. И, конечно, 3 этап это способы построения простых цифровых схем с использованием языков описания аппаратуры.

Алгебра логики

Основными в алгебре логики являются следующие вещи:

1) Принцип двойственности
2) Теорема Де-Моргана 
 
 Эти два принципа можно посмотреть, например, здесь: https://studme.org/2002061028280/tovarovedenie/algebra_logiki . Позже сам напишу про алгебру логики.

Так же следует упомянуть про способы представления (алгебраическое, табличное и в виде карт/диаграм Карно и Вена) и минимизации логических функций через карты Карно или другие методы, например, метод Мак-Класки (https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%9A%D1%83%D0%B0%D0%B9%D0%BD%D0%B0_%E2%80%94_%D0%9C%D0%B0%D0%BA-%D0%9A%D0%BB%D0%B0%D1%81%D0%BA%D0%B8).

Одна неплохая презентация про алгебру логики: https://drive.google.com/file/d/0B9GLCHSwsJn8cURyT3BOUEVxdVE/view?usp=sharing

После понимания математических основ цифровой электроники нужно двигаться к способам реализации простых цифровых схем клмбинационной логики (логики не зависящей от состояния схемы):

- мультиплексоры
- дешифраторы
- преобразователи кода
- и другие схемы.

Вот, например, https://drive.google.com/open?id=0B9GLCHSwsJn8NmxtTVNUOVZZbWs

 Следующий шаг - изучение последовательностных схем (схемы зависящие от состояния и сигналов на входе схемы).  Такими схемами являются:

-триггеры
-счетчики
-регистры
-генераторы
и др.

Например, https://distant.msu.ru/pluginfile.php/38192/mod_resource/content/1/%D0%9B%D0%B5%D0%BA%D1%86%D0%B8%D1%8F%204.pdf

или

https://drive.google.com/open?id=0B9GLCHSwsJn8YkJZeGtVZzZ4LTQ

а также ознакомиться с описанием цифровых автоматов (которых, 2 основных вида: Мили и Мура (https://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D0%9C%D1%83%D1%80%D0%B0_%D0%B8_%D0%9C%D0%B8%D0%BB%D0%B8)

Схемотехника логических элементов

Данный раздел в большей степени относится к разаботке цифровых устройств с использованием дискретных микросхем, однако, в ряде моментов при проектировании с использованием ПЛИС эти знания также оказываются необходимыми

Прежде всего схемотехника зависит от типа логики: ТТЛ (ТТЛШ), КМОП и ЭСЛ: http://www.inp.nsk.su/students/radio/lectures/Pulse/07.pdf

Параметры логических элементов:
 http://myrepititor.ru/electronics/82-Osnovnye_xarakteristiki_i_parametry_logicheskix_eleme.html

http://audioakustika.ru/node/1555

Языки HDL, способы проектирования
У меня довольно большаыя подборка книг по ПЛИС: https://drive.google.com/open?id=0B9GLCHSwsJn8Z0Y3U24ybmxjVjA

Если использовать Verilog, то стоить начать с Verilog и VerilogTutorial, если VHDL - то "Языки Verilog и VHDL", кроме того среди этого архива есть документ с "Золотыми ссылками по HDL".


Что будет в продолжении?

В будущем планирую пройтись по каждому из этих пунктов и написать цикл статей с примерами дизайна цифровых схем (на github).

суббота, 29 июля 2017 г.

C++ symbol lookup error при запуске приложения

Суть проблемы
 
Недавно, занимаясь одним из своих С++ проектов обнаружил следующее занимательное поведение программы, использующих динамическую библиотеку. На самом деле, неважно какая библиотека вызвала данную проблему, я уверен, что это не имеет никакого значения. Но в моем случае данная проблема возникла с библиотекой libuhd. Я собрал для себя специальную версию ibuhd, успешно скомпилировал и слинковал приложение с либой и бац! при запуске:
linux; GNU C++ version 4.8.5; Boost_105800; UHD_003.010.001.001-0-unknown

/home/michael/Projects/eclipse/C++/wirelessdriver/UhdRadio/Debug/UhdRadio: symbol lookup error: /home/michael/Projects/eclipse/C++/wirelessdriver/UhdRadio/Debug/UhdRadio: undefined symbol: _ZN20radio_ctrl_core_30004makeEbN5boost10shared_ptrIN3uhd9transport12zero_copy_ifEEES5_jRKSs




Причина в отсутствии функции в классе библиотеки или самого класса! Собирал я это чудо cmake, и, как оказалось, в cmake также можно задавать видимость определенных классов, но предварительно я снял все ограничения, экспортировал все, что есть. Сижу недоумеваю, пью кофе и тихо матерюсь ("С++, что же ты со мной делаешь!").

Дьявол скрывается в мельчайших деталях

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

~/Projects/eclipse/C++/wirelessdriver/UhdRadio/uhd-release_003_010_001_001/host/build/lib> nm -D libuhd.so | grep _ZN20radio_ctrl_core_30004makeEbN5boost10shared_ptrIN3uhd9transport12zero_copy_ifEEES5_jRKSs
00000000004e1ff0 T _ZN20radio_ctrl_core_30004makeEbN5boost10shared_ptrIN3uhd9transport12zero_copy_ifEEES5_jRKSs


Да, что же такое! Нужные символы есть, возможно не все зависимости (библиотеки) есть в системе, но ldd показывает, что все ОК (показывает откуда (путь) подлинковываются либы). И тут меня осенило!!! Я собирал целую массу версий uhd и параллельно ставил ее из пакетов, а что же говорит ldd относительно этой либы в моей утилите???  А говорит он, что либа при запуске приложения берется не из того, же источника откуда проводилась линковка! Понятно, что для запуска либа должна быть в LD_LIBRARY_PATH, но оба пути находятся в этой переменной, а при запуске либа тянется из первого в порядке упоминания пути, а моих изменений там вовсе НЕТ. Правим и наслаждаемся спокойной работой дальше.

Заключение

С++ , GCC люблю я вас! Настолько много в вас неожиданных сюрпризов...

вторник, 11 июля 2017 г.

Бесплатный сыр SSL

SSL, паранойя браузеров и зеленый HTTPS

Собственно ситуация довольно простая: имею собственный сервер, на котором развернут Gitlab + CI в лице Hudson: пишу код, тружусь, собираю автоматически билды проектов и т.п. В один прекрасный момент захотелось, чтобы сервис был развернут на HTTPS ( это не прихоть, просто, иногда люблю зайти на свой сервер из общественных мест с общего wi-fi, а шифрования нет, что может привести к доступу ко всей информации любому, кто способен запустить wireshark или tcpdump и т.п. Примерно около двух с половиной лет назад, по довольно тривиальной схеме я создал самоподписанный сертификат по следующей схеме (из под Linux):

1) Нужно сгенерировать CSR (Certificate Signing Request), который состоит из открытого (public) и закрытого (private) ключа и доп информации. При генерации CSR нужно записать/запомнить пароль!!!!, иначе дешифровать ключ не получится и придется генерировать CSR и ключ заново.

openssl req -newkey rsa:2048 -keyout gitlab.key -out gitlab.csr

2)  Генерируем сертификат:

openssl -key gitlav.key -new -x509 -days 1536 -out gitlab.crt
 
Параметр days задает время действия сертификата - 1536. Теперь самоподписанный сертификат готов, но, современные браузеры начинают жутко параноить и разрывают соединение при наличии на сервере такого сертификата. Использование сервиса, начинает доставлять неудобства.

3) Дешифровать  ключ, который понадобится Nginx для работы по SSL:

openssl rsa -in gitlab.key -out gitlab_dec.key

Немного теории об SSL

Как работает SSL для чего нужны открытые, закрытые ключи и сертификаты? Сама безопасность обеспечивается шифрованием данных, на сервере и у клиента: при установке соединения клиент и сервер договариваются о выборе типа шифрования, сервер передает на клиент сертификат и открытый ключ, закрытый ключ остается на стороне сервера. Далее происходит генерация сеансового ключа на стороне клиента (шифрование случайной последовательности открытым ключом),  и передача их на сервер, расшифровать данные можно только с помощью закрытого ключа (т.к.) шифрование является асимметричным. Закрытый ключ находится на сервере и недоступен никому.

StartSSL и иже с ними

Жадные капиталисты за работу своих центров сертификации, хотят  деньги, поэтому, чтобы стать обладателем сертификата нужно раскошелиться на, сумму от 50 до 200$. Для хостинга своих небольших сайтов и Web-сервисов такая цена является неоправданно высокой, поэтому лучше найти варианты с бесплатным SSL. Из известных мне сервисов это StartSSL и Letsencrypt. Изначально я подсел на первый и, поэтому решил работать с ним дальше.

Полезные команды на заметку

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

openssl x509 -noout -modulus -in gitlab.crt | openssl md5
(stdin)= ca2097c19fa0af553533037e290dfb02
openssl rsa -noout -modulus -in gitlab_dec.key | openssl md5
(stdin)= 933b16d478523d8d8f3fbfceb57644e0
openssl rsa -noout -modulus -in gitlab.key | openssl md5
Enter pass phrase for gitlab.key:
(stdin)= ca2097c19fa0af553533037e290dfb02

Как видно из выхлопа консоли у одного ключа совпадает хэш с сертификатом, а у другого нет

Что делать в случае использования StartSSL

Да, я выбрал Start SSL и в 2016-м получил свой первый зеленый сертификат на целый год работы,все было хорошо. Но сертификат буквально неделю назад испарился и возобновить его нет возможности, необходимо создавать новый, что же попробуем создать новый. Сразу скажу, что сертификат выпускается на доменное имя, поэтому для того, чтобы его получить нужно где-то взять имя. Я использую dnsexit, они предоставляют бесплатные доменные имена 2го уровня в зонах типа linkpc.net и т.п.

1) Прежде всего подтверждаем, что являемся владельцами домена. Раньше в StartSSL можно было разместить страничку на сервере и пройти валидацию, теперь все только через e-mail адрес домена, который выдает whois. Я заплатил 12$ за редирект почты в dnsexit на свою почту и получил код валидации домена.

2) После валидации домена необходимо зайти в Certificate Wizard и создать csr на базе приватного ключа:
openssl req -newkey rsa:2048 -keyout um-gitlab.linkpc.net_enc.key -out um-gitlab.linkpc.net.

 3) Скачиваем сертификат из StartSSL ToolBox панели, нам нужен вот этот сертификат:

Нажимаем Retrieve и забираем весь архив. И вот тут-то начинается самое прекрасное. У Start SSL есть инструкция по установке сертификата на NGINX, только по этой инструкции сертификат поставить невозможно. Для того чтобы домучить процесс нужно запросить промежуточный сертификат, который имеет имя BR Intermediate. Из папки OtherServer взять сертификат домена и корневой сертификат (root.crt), теперь эти 3 сетификата нужно объединить в следующем порятке:
          1. Сертификат домена
          2. Промежуточный сертификат
          3. Корневой сертификат

Объединяем все это дело утилитой cat:

cat gitlab.crt BR\ Intermediate.crt root.crt > ssl-unified.crt

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

Проверить правильно ли сгенерировались и объединились сертификаты можно с помощью данного онлайн ресурса: https://www.sslshopper.com/ssl-checker.html Если цепочка является полной, то все ок.

И здоровенная ложка дегтя!!!!

На текущий момент у StartSSL проблемы с Chrome > 57 и Firefox, эти браузеры считают сертификаты не валидными. Поэтому я сижу, грущу и использую Konqueror. В службе поддержки мне сказали, что, вероятно, через 1-2 месяца они решат проблему с этими браузерами. Ресурсы для отслеживания этой темы:
https://blog.mozilla.org/security/2016/10/24/distrusting-new-wosign-and-startcom-certificates/
https://bugzilla.mozilla.org/show_bug.cgi?id=1311832

Насколько сыр оказался бесплатным?

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

четверг, 29 июня 2017 г.

Все необходимое ношу с собой (С++)

Ох уж эти зависимости

Это "удивительная" история связана с тем, что возникла необходимость использования различных библиотек, т.к. периодически возникает необходимость использования логирования, модульных тестов и т.п. в проектах, компилируемых и запускаемых под Linux. Для Windows и ряда дистрибутивов Linux ситуация довольно простая, т.к.

1) Для Windows в Visual Studio проектах можно использовать нативные nuget-пакеты.

2) Для дистрибутивов Linux, в которых есть менеджер пакетов (.deb или .rpm) многие библиотеки и их зависимости могут быть установлены таким способом.

Но есть большое НО:

1.  Не все библиотеки могут быть в менеджере пакетов nuget или в менеджере пакетов Linux (хотя речь, конечно, идет о проектах под Linux).

2. Дистрибутив может быть довольно старым, и в менеджере пакетов нет свежих библиотек.

3. Сам дистрибутив не имеет менеджера пакетов (Arch, Gentoo, различные маленькие и легковесные дистрибутивы).

Как же быть? Примеры работы с различными библиотеками

Самый подходящий вариант - собирать библиотеки вместе с проектом, написать Makefile или bash-скрипт для выполнения этой работы. Как правило проекты библиотек располагаются в директории contrib.

Log4Cpp - неплохая библиотека для логирования сообщений в проектах, имеет богатые настройки и кучу различных аппендеров (менеджеров разных видов записи, например в раскрашенном виде в консоль, в циклически перезаписываемый файл и т.п.). К сожалению библиотека (ее актуальная версия) собраны с использованием autotools, что само по себе уже капкан, т.к. проекты automake не переносимы в пределах разных версий тулсета (во всяком случае мне не встречались такие проекты). liblog4cpp.so отсутствует в моей системе (OpenSuse 42.1), поэтому я использую следующий скрипт (после configure) для сборки:

#! /bin/bash
# Check that configure was not executed
if [ ! -f libtool ]; then
    ./autogen.sh
    ./configure --with-pthreads
fi
# Check that make was not executed
#if [ ! -d ./srx/.libs ]; then
#make
#fi
make clean
make


Gtest - библиотека для написания модульных тестов. Собирается куда как проще, т.к. создана без помощи этих ужасных autotools, ее я собираю следующим способом:

#! /bin/bash
GTEST_DIR=.
#../../contrib/gtests
#=.

rm -rf ${GTEST_DIR}/libgtest*
rm -rf ${GTEST_DIR}/*.o
g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} -pthread -c ${GTEST_DIR}/src/gtest-all.cc
ar -rv ${GTEST_DIR}/libgtest.a gtest-all.o


EasyCmdLineReader - легковесная библиотека для работы с аргументами командной строки. Эта библиотека собирается моим кастомным makefile-ом https://github.com/IzyaSoft/EasyCli/blob/master/Makefile , шаблон для сборки произвольной либы может быть взят отсюда: https://github.com/IzyaSoft/EasyMakeSharedLib . Но данная библиотека легко собирается через просто make (который можно запустить также из шелл скрипта).

Итог

Opensource предоставляет шикарные возможности для контроля используемого в проектах кода, однако он и создает ряд проблем для сборки. Вышеупомянутый способ использования библиотек в проектах, когда нет возможности использования пакетов имеет и ряд недостатков: прежде всего хранение в репозитории дополнительных файлов исходного кода используемых библиотек, сложности в сборки (все тот же autotolls, а также зависимости, которые могут не поддерживаться конкретным Linux дистрибутивом).




воскресенье, 18 июня 2017 г.

Gated clock в HDL

Что такое Gated clock (and/or signal ripple) и его последствия

Недавно занимался одним из своих старых проектов (Quartus 9.1) и, перечитывая, в очередной раз, предупреждения компиляции проекта, обнаружил, что появился такой интересный ворнинг : "Found 1 node(s) in clock paths which may be acting as ripple and or gated clocks -- node(s) analyzed as buffer(s) resulting in clock skew".  Данное предупреждение оказалось связано с моим модулем, управляющим работой двухканальным счетчиком (каждый из счетчиков работает попеременно), сам модуль формирует сигнал адреса и сигналы разрешения и сброса счетчиков.

Прежде всего попытаемся понять, что же означает данное предупреждение. А означает оно то, что на линии тактового сигнала (клока) присутствует логический вентиль (gate). Поскольку мы имеем дело с конкретной микросхемой, а не с математической функцией, то прохождение сигнала через логические элементы всякий раз будет добавлять задержку на время переключения вентиля из 0 в 1 или из 1 в 0. Другая часть предупреждения говорит о том, что наличие вентиля будет приводить к пульсациям. На самом деле, в этом случае могут быть проблемы с переключением на линии клока, например, время переключения вентиля 10 нс, на линии клока пришло переключение из 0 в 1 (posedge), за эти 10 нс, предположим клок переключился из 1 в 0 и, потом, снова из  0 в 1 непрерывно с малыми интервалами, так вот gated clock отфильтрует часть переключений и, как следствие, часть важной информации может быть потеряна.

Как же удалось этого добиться?

Сам удивляюсь как я смог спроектировать такую ерунду, но вот часть кода, описывающая мой модуль.

assign counter0_enable = ~counter_address;
 assign counter1_enable = counter_address;

d_trigger counter0_force_clear_trigger (.clk(counter0_enable), .data(vcc), .reset(counter0_reset), .enable(enable), .out(counter0_force_clear));
- d_trigger counter1_force_clear_trigger (.clk(counter1_enable), .data(vcc), .reset(counter1_reset), .enable(enable), .out(counter1_force_clear));

counter_address генерируется периодически по другому сигналу с помощью Т-триггера. Самое интересное, что к этому эффекту приводит генерация сигналов в counterХ_enable через триггер. И как же быть в такой ситуации? Почитав, что пишут в интернетах и немного подумав, я использовал для клока триггеров исходный сигнал, а операцию выбора работы триггера по адресу перенес в enable (т.е. force_clear сигналы генерируются только в моменты когда enable на триггерах равен 1):

d_trigger counter0_force_clear_trigger (.clk(~channel), .data(vcc), .reset(counter0_reset), .enable(enable & counter1_enable), .out(counter0_force_clear));
+ d_trigger counter1_force_clear_trigger (.clk(channel), .data(vcc), .reset(counter1_reset), .enable(enable & counter0_enable), .out(counter1_force_clear));
На RTL View данная ситуация (gated clock) проявляется следующим образом:










Согласно этому изображению, проблема в шунтировании двух D-триггеров гэйтами.

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



суббота, 3 июня 2017 г.

Странности в Verilog-2001


Немного истории или появление ПЛИС и HDL
Ха-ха, здравствуйте-здравствуйте, дорогие читатели. Недавно я писал про странности, связанные с софтом, а именно - Vivado, но дело дошло до самого языка.Вообще для программирования FPGA/PLD/ПЛИС используют языки программирования, позволяющие описать прохождение цифровых электрических сигналов и реакцию цифровых схем на эти сигналы. В данной статье я не буду затрагивать вопросы, связанные с цифровой схемотехникой, булевой алгеброй (алгеброй логики и т.п.). Прообразом ПЛИС стали Программируемые логические матрицы (ПЛМ/PLM), построенные на основе N-в-1 логических элементах (ИЛИ/И), к которым подведены от 1 до N сигналов. Программирование осуществляется с помощью плавления перемычек между входами логических элементов:
Любая логическая функция и любые последовательностные схемы могут быть реализованы на базисных элементах. 

После ПЛМ появились ПЛИС представляющие собой несколько десятков слоев ПЛМ (например, семейство MAX7000). Далее ПЛИС стали сохранять конфигурацию во внутреннюю оперативную память, а конфигурация при старте загружалась с Flash-памяти.

Для описания связей между  логическими элементами (задания какие перемычки нужно включить, а какие убрать) были придуманы языки для описания аппаратуры (HDL): AHDL, VHDL и Verilog.  Наиболее востребованными являются 2 последних, лично я предпочитаю Verilog, т.к. он отдаленно напоминает классику - язык С, а VHDL - Pascal.

Этот странный Verilog

В этом разделе я опишу, пожалуй лишь несколько из странностей Verilog.

1. Доступ к параметрам модуля из функции

Доступ к параметрам  модуля невозможен из функции, например есть модуль:

module my_module #
(
      parameter PARAM_1 = 1
)
(
    // ports defenitions
);

localparam _PARAM_1_LOC = PARAM_1;

function[1:0] some_func();
// local variables defined here ...
      // <!!!!! в этой функции мне недоступен PARAM_1, но доступен PARAM_1_LOC
endfunction;

endmodule

Несмотря на то, что функция some_func принадлежит модулю my_module у нее нет доступа к параметрам модуля, но есть доступ к локальным параметрам.

2. Инверсия порядка бит в байте

Иногда необходимо изменить порядок следования бит в векторе на обратный, очень бы хотелось сделать так:

reg[7:0] byte_vector;

reg[7:0] inversed_byte_vector;
 // где-то внутри always
inversed_byte_vector = byte_vector[0:7]; // ОШИБКА КОМПИЛЯЦИИ

 К сожалению, это не работает, приходится использовать конкатенацию или цикл:

inversed_byte_vector = {byte_vector[0], byte_vector[1], ....byte_vector[7]}


3. Доступ к вектору по индексам

 Известно, что чтобы получить доступ к произвольной части вектора достаточно обратиться к нему указав индексы, по которым необходимо сделать срез:

reg [31:0] my_vector;
reg [7:0] vector_part;

// где-то внутри always блока
vector_part = my_vector[29:22];

Но доступ по индексам возможен только тогда, когда передаются константы, поэтому приходится городить такие конструкции.

// присвоение внутри функции
reg[7:0] shift;
begin
shift = `MAX_DATA_WIDTH - NUMBER_OF_BYTES * 8;
// потом я не могу вырезать данные так:
result = data[MAX_DATA_WIDTH : shift]; // ошибка

для того, чтобы получить то, что я хочу, я должен сделать так:
result = data[`MAX_DATA_WIDTH - 1 : `MAX_DATA_WIDTH - NUMBER_OF_BYTES * 8];

 4. Чудесный мир литералов

Данная вещь куда как более тривиальна, но менее очевидна, для того, чтобы присвоить двоичное значение какому-нибудь регистру можно его записать как:

my_reg  = 8'b10001111; // Разрядность в битах, одинарная кавычка, латинская "бэ" и бит за битом (старшие биты идут вперед).

Но, что делать если нужно записать значение в 16-ричной системе счисления, т.к. 64 бита писать нереально утомительно, даже если пользоваться конкатом, для этих целей существует представление hex-литералов:

my_reg = 64'hAABBCCDDEEFF0011;
Хоть синтаксис и С подобный, но никаких тебе 0x и т.п.

Это не баги, это фичи
Verilog, конечно же, неплох, для описания HDL, но хочется, чтобы таких неудобств в нем было как можно меньше, учитывая, что последний раз стандарт выходил в 2001 г., а сам язык является наиболее популярным для программирования ПЛИС. Поэтому ждем перемен (с).

четверг, 25 мая 2017 г.

Обратная сторона It

Субъективизм
 Этот пост является исключительно моим субъективным мнением посвященным "темной" стороне it (на самом деле худшим проявлениям людских качеств). В этом рассуждении и я не желал и не стремился кого-нибудь обидеть, хотя мне в общем-то пофиг.

Как все начинается

До того, как я начал работать в it и участвовать в проектировании и разработке электронных схем и ПО уровня Enterprise, я считал, что разработчики это люди увлеченные техникой, идеями глубокого познания самого мира через исследование прикладных сторон жизни. Со временем это мнение начало меняться в силу того, что программисты  и инженеры в большинстве не отличаются от людей, выбравших другие профессии. Для  многих "специалистов" it это способ выгодно пристроить свою жопу, сесть на теплое место и не париться (получать неплохие по сравнению, с другими отраслями, деньги). В It есть огромные плюсы: например, можно на протяжении нескольких лет делать примерно одно и тоже (постараюсь описать на примере нескольких пациентов) не напрягаясь, особенно если тебя не напрягают (это не работа на заводе во вредных условиях и т.п.) и при этом получать зарплату в 2-3 раза выше средней по региону. Такое поведение относится к области психологии, но при этом хорошо описывается законами физики (закон сохранения Энергии, принцип Ле Шателье и т.п.)

Прежде всего нужно разобраться с тем, почему так происходит (почему мои коллеги по профессии глупы, невежественны и заносчивы) нужно понять, а что может мотивировать человека делать ту или иную работу (тут скорее всего следует сказать не делать работу, а торчать на работе):
  •  1. Материальное вознаграждение
  • 2. Слава/признание других троглодитов/чувство собственной важности и крутизны
  • 3. Страх неизвестности, что придется искать новую работу , а это уже новые вызовы, особенно, если квалификация не соответствует материальным запросам.
Как мне кажется, третья причина  очень сильно склоняет людей к консерватизму, нежеланию перемен, изучению чего-то нового и т.п. Для себя я четко определил, что раз жизнь относительно коротка, то не зачем делать либо скучную/неинтересную работу, либо сидеть на одном месте если есть более перспективные в финансовом плане варианты. Подобный консерватизм на корню убивает желание изучать новое (новые технологии, состояние отрасли, да хотя бы языка с использованием которого ты пишешь код). Жизнь это движение, а застой убивает все, т.е. в it все абсолютно как в жизни.


Я просижу тут до пенсии/смерти (выйду ногами вперед)
Карьера штука, конечно же, хорошая, однако если человек сидит N лет подряд и он такой же, каким был эти N лет назад (я не рассматриваю назначение человека на новую позицию/должность ). Такой человек по уровню, как правило, балансирует между джуниором и мидом (хотя может по позиции быть и сенионом, и тимлидом), но при этом он конечно же считает, что развивается и становится лучше. Но для того, чтобы оценить это нужно задать вопрос себе: "А сделал ли я за эти пять/десять лет хоть одно решение, которое можно считать проектированием вообще? Или я всегда стоял за чье-то спиной? Может быть я решил хоть одну по-настоящему сложную и интересную задачу? Или быть может я тянул весь проект и я был архитектором системы?".  У меня есть друг, который был обеими руками за все самые лучшие принципы проектирования, он говорил я учусь у тебя и тому подобное, но по факту оказалось, что он не может сделать ни одной серьезной задачи, более того он стал выбрасывать непроверенный код на "от****сь" в тех задачах где он мог себя неплохо показать, увы этот человек меня все больше и больше поражает своей некомпетентностью.

Я инженер, мне книги читать необязательно 
Был у меня уникальный коллега, который считал, что раз он получил диплом инженера, то книги читать вовсе не обязательно, что он все умеет идеально, а остальное посмотрит в интернете. Цензурно я не могу это прокомментировать, т.к. перед глазами стоит картина, как отец в выходные читал самые разнообразные книги по инженерном делу, деталям машин, изобретательству  или просто по прикладной математике. Но "крутым" инженерам это не нужно, они же новые Королевы, Александровы и др. выдающие инженеры.


Зона комфорта или плевать на все
Тут я опишу печальный личный пример. У меня был начальник (начальник небольшого отдела разработки), который отстаивал идеи хорошего проектирования, уменьшения хаоса в системе и т.п., однако, случилось несчастье и этого прекрасного во всех отношениях человека не стало. А он был бетонной стеной, защищавшей всех нас (разработчиков) от тупорылого технически неграмотного руководства и лагеря альтернативно одаренных бизнес-аналитиков, причем все говорили: "Ух да, аналитики козлы, вообще ничего не понимают". Но после всего этого, они забыли все и стали с руководством предельно любезными, продали все принципы ради того, чтобы получать регулярно премии от аналитиков.

Да, в принципе, ничего нового
Да абсолютно так, все уже было написано ранее, возможно, отчасти в русской классике (например, Горе от Ума). Данный пост не является нытьем или чем-то в этом духе, просто для самого себя, хотелось до конца прояснить все эти моменты. Лень, нежелание двигаться вперед, попытка быть угодными всем, отказ от принципов делают нас слабыми и безвольными. В общем не стоит прогибаться...


среда, 17 мая 2017 г.

Как справиться с багами в Vivado (Xilinx)

Предыстория 

До недавнего времени моя работа с ПЛИС (FPGA, PLD) касалась лишь работы с микросхемами серии MAX7000 Altera (Intel), на тот момент времени мне казалось, что хуже Altera ничего нет из-за изобилия недостатков их ПО (Quartus), например:

  • - компилятор Altera не синтезировал ряд синтаксических конструкций: циклы, не позволял иметь более 2х always-блоков внутри одного модуля.
  • - сам Quartus обожал абсолютные пути, которые впоследствии удалось заменить на относительные через "." и "..", разбивал настройки проектов на несколько файлов (из-за чего я не сразу мог их найти) поэтому для настройки проектов на разных машинах приходилась вбивать руками пути и т.п.
Мое мнение об превосходной отвратительности ПО Altera прожило ровно до того момента, пока я не погрузился в чудесный мир от Xilinx с Vivado. Начал я с последней, на тот момент времени (осень 2016),  версией - 2016.2 Сам перенос проекта на другую версию Vivado сопряжен с рядом проблем, о которых я напишу позднее, поэтому до полной реализации устройства я не решился переносить проект и продолжил работу с 2016.2.

Сказать ужасно значит вовсе не описать качества продуктов Xilinx.

1. Документация по софтовым продуктам, чипам, проектированию и т.п. доступна в разных документах с именами UGXXX, где XXX - номер документа. Документация временами и правда UG, многие вещи необходимо искать в многостраничным pdf, в которых на зерно информации тонна воды, документы не всегда актуальны (созданы для более ранних версий Vivado).

2. Сам принцип дизайна, у 12-13 версий Quartus проектирование строилось относительно создания топового модуля с использованием HDL, у Xilinx нужно нарисовать блок дизайн, затем на основе него создать топовый модуль,  причем обязательно нужно создавать процессорное IP - ядро и IP-ядро сброса, подцеплять к минимальной системе источники тактового сигнала (клок), подцеплять DDR оперативку и т.п. Хотя это SoC, поэтому тут все сложнее, чем для более простых семейств ПЛИС, но тем не менее Xilinx  не предусмотрела ситуации когда мне нужно только логические ячейки без всех наворотов (без AXI и т.п.).

3. Работа Vivado: сотни предупреждений на собственные IP-ядра (ядра от Xilinx) при синтезе.

4. Дизайн: ориентирован на IP-ядра, а не на модули. Я не думаю, что на легковесные модули типа таблицы преобразований или инвертора нужно создавать IP-ядро, однако Vivado сильно параноит при использовании модулей.

5. Ресурсы. Очень долго выполняется синтез и имплементация проекта занимающего процентов 10-20% всех ресурсов от Zynq-7020. Например на 4-ядерном E2-6110 (слабенький 1,5 ГГц и TDP всего 15 Вт) полный цикл - 1 час. На топовых процессорах летает (на моем i7 - 1-2 минуты). По ощущениям Quartus на слабых машинах работал в разы быстрее. На аппаратной виртуальной машине, созданной на KVM с 4 ядрами и 5 Гб оперативки может упасть с Out Of Memory Exception (даже жирный своп не помогает от этой болезни).

6. Кривые и забагованные Vivado и Xilinx SDK, которые могут вылететь и закончить работу по абсолютно любым причинам с потерей всех результатов работы (на практике я не решился использовать частичный результат работы синтеза или имплементации при вылете на одном из шагов для продолжения с этого шага).

7. Отсутствие средств для инверсии логических сигналов на блок-дизайне (да мне пришлось создать модуль инвертора с телом в 3 строчки verilog кода)

8. Куча других более мелких причин...

Использование СКВ (системы контроля версий) для работы с проектом 

Наиважнейший момент при разработке на ПЛИС. Отдельную функциональность/фичу я реализую в отдельной ветке и потом уже объединяю с основной ветвью (как правило, это master). На мой взгляд, идеальный выбор это git, для ряда своих проектов я использую github. У меня была ситуация когда по непонятным причинам код в двух ветках оказался полностью нерабочим, я не мог ничего сделать несмотря на массу попыток и относительно простых изменений в дизайне, поэтому пришлось откатиться на ветку, от которой я создал ранее обе эти ветви. Если бы у меня не было СКВ или СКВ с неудобной работой с ветками (CVS, Subversion) я бы попал в неприятное положение (получил бы нерабочий дизайн в trunk) и, возможно, мне пришлось бы создать весь дизайн заново.

Для всех своих проектов я использую следующие правила размещения создаваемых мною файлов:

./src - директория с моими HDL - исходниками, если использовать %ProjectName%.srcs/sources_1/..., то, во-первых, это выглядит ужасно, а, во-вторых, мы получим кашу из генерируемых Vivado файлов и собственных HDL-исходников, сама же Vivado любит на каждый чих делать толпу изменений в файлах. Если вы что-то поменяли в одном из модулей и желаете сделать коммит изменений одного конкретного модуля, то такой подходя позволяет быстрее находить измененные модули в списке измененных файлов .
/tests - файлы тестбенчей на HDL-модули
/constraints - директория для сохранения файлов ограничений (как временных, так и физических), здесь ситуация аналогичная с src
/app - рабочее пространство (воркспэйс) С/С++ Xilinx SDK-проектов (софтина, созданная на базе Eclipse, но с бОльшим числом проблем, чем у Eclipse.
/config - файлы аппаратной конфигурация SoC.
/ip - каталог моих IP-ядер.

Чтобы в коммите не было по 1000+ изменений файлов (я не шучу их реально несколько сотен минимум), нужно правильно настроить .gitignore (список не отслеживаемых файлов/директорий с возможностью задания имен по шаблону). Например, в качестве образца можно использовать такой шаблон: https://github.com/OpticalMeasurementsSystems/2DImageProcessing/blob/master/.gitignore

А вот и сами проблемы

Описания самих проблем будет значительно меньше по объему, чем всей предыстории. Если мне удастся записать видео в момент наступления проблемы и ее решения, то позднее я добавлю ссылку и на видео. Список при обнаружении проблем и решения будет обновляться.

1. Синтез/имплементация падают с генерацией исключения и демонстрацией мессадж бокса - проблема в кэше, для лучшего эффекта стоит удалить директории %ProjectName%.hw, %ProjectName%.cache, %ProjectName%.runs.

2. Синтез/имплементация зависли на длительное время - некоторые проблемы, когда Vivado падает не отображаются в виде мессадж боксом, но они видны в окне Log. Решение сбросить синтез имплементацию (нажать на кнопку Cancel в правом верхнем углу), прибить директорию %ProjectName%.runs.


3. На блок дизайне не обновляется размер некоторых портов, например, Concat IP-ядро. Для этого можно попробовать сначала сбросить Output Products (Reset Output Products при клике правой кнопкой мыши по экземпляру HDL Wrapper'а в иерархии исходных файлов модулей), а затем сгенерировать их заново (Generate Output Products).

4. При запуске Xilinx SDK появляется Splash Screen, потом пропадает, сам SDK не запускается. Нашел 2 причины с проблемами запуска SDK:
       1) Оказалось, что у меня на компьютере было установлено 2 версии Java Development Kit (x32 и x64 параллельно), удалил x32 и SDK стал запускаться без проблем.
       2) Хардкорное решение: удаление папки .metadata, тогда из воркспэйса пропадают все проекты кроме hardware platform, восстановить проекты легко File->Import->General->Existing Project Into Workspace, выбрать галочками необходимые для импорта проекты, нажать ОК.
Видео рения этой проблемы здесь: https://www.youtube.com/watch?v=R_dwpoqsmX4

      3) [Дополнение]: Заметил, что если удалить файл lock в metadata и директорию  eclipse.cdt.ui из плагинов там же в metadata, то можно избежать повторного муторного добавления проектов в воркспэйс (не знаю, работает ли это во всех случаях или нет).

5. Неожиданно перестал собираться BSP, вероятно, в воркспеэйсе появился доп. хардварный проект, а BSP связан с другим железом, для решения этой проблемы удаляем все лишние hardware проекты и обновляем железный проект через правый клик по проекту -> Change Hardware Description File (выбираем экспортированный hdf) и вуаля, после этого можно собрать BSP и приложение.


6. Не открывается репозиторий одним из гит клиентов (GitKraken и т.п.) - это связано с запущенным SDK, который блокирует доступ к скрытой директории .git, решение - закрыть SDK.

Почему все так ужасно?

Можно сказать, что это болезнь всего ПО, заточенного под Embed-проектирование, оно все, как правило, ужасно и изобилует большим количеством багов, а современные тенденции к генерации HDL-кода из ПО для моделирования типа Matlab + SimuLink приводят к разрастанию самого кода ввиду неоптимальных подходов, плохой поддержке этого кода, к созданию "одноразового (write only)" кода и т.п., уменьшают порог вхождения и увеличивают степень энтропии создаваемого продукта людьми далекими от какого-либо понимания принципов работы цифровой электроники и программирования.


Распространение Windows-приложений (Chocolatey)

Менеджеры пакетов для ОС Windows В большинстве дистрибутивов Linux есть свои менеджеры пакетов: в Ubuntu/Mint это apt и deb, в OpenSuse э...