четверг, 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 г., а сам язык является наиболее популярным для программирования ПЛИС. Поэтому ждем перемен (с).

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

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