23

С чего начать изучение FPGA (ПЛИС) ?

Приветствую посетителей сайта pikabu.ru. Я решил сделать несколько статей про разработку на FPGA. Надеюсь, это вам будет интересно.

С чего начать изучение FPGA (ПЛИС) ? Плис, Fpga, Схемотехника, Разработка, Электроника, Adruino, Длиннопост

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


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


Если вы не вняли моим предупреждениям, и читаете эти строки, значит либо вам реально интересно узнать про FPGA, либо вам совсем делать нечего, что вы читаете этот бред сумасшедшего пост.


Долго думал чего бы мне начать... Поскольку думать это не моё, поэтому буду импровизировать и выкладывать посты, как получиться. Но я постараюсь излагать материал более-менее последовательно, ну а дальше, либо меня заберут санитары, либо улечу в такие минуса, из которых не выбираются самостоятельно. Ну да ладно, будь что будет….

С чего начать изучение FPGA (ПЛИС) ? Плис, Fpga, Схемотехника, Разработка, Электроника, Adruino, Длиннопост

Поскольку я личность крайне ленивая, и мне лень переключать каждый раз раскладку клавиатуры, то зарубежную аббревиатуру FPGA (Field-Programmable Gate Array), что переводиться как Программируемая Полем Вентильная Матрица (ППВМ), я со своей легкой руки заменяю на ПЛИС, что означает Программируемая Логическая Интегральная Схема.


Что же такое ПЛИС, зачем она вообще нужна, когда есть микроконтроллеры, например макетная плата Arduino? Если в вкратце объяснять, то в основе платформы Arduino лежит микроконтроллер, по сути представляющий собой миниатюрный компьютер, имеющий ОЗУ, порты ввода\вывода, набор минимальной периферии, память команд, содержащую инструкции, которые он (контроллер) выполняет, т.е. программу, написанную пользователем, под конкретную архитектуру контроллера.


ПЛИС - это же набор логических элементов, настраивая, и объединяя которые, вы строите цифровую схему, которая выполняет заложенную вами функцию. Уф... Понятно объяснил? Да знаю я, что непонятно! Я сам ничего не понял из своего объяснения, когда прочитал!


Попробую привести пример: представьте, что вам нужно получить от четырех датчиков данные передаваемые по четырем 8 битным шинам. И вычислить среднеарифметическое этих данных, с отбрасыванием дробной части. И делать это надо с максимально возможной скоростью. Допустим наш контроллер, тактируется частотой 10 МГц. Для нахождения среднеарифметического, сначала надо сложить четыре числа. В зависимости от архитектуры контроллера на это уходит от 1 до 5 тактов. Не факт что архитектура контроллера позволяет сложить сразу четыре числа, но допустим, он умеет это делать. Потом сумму этих чисел надо ещё поделить на 4. Надеюсь, вы помните, что деление на числа степени двойки можно заменить сдвигом? Т.е деление на 2 - это сдвиг двоичного числа на 1 разряд вправо, деление на 4 это сдвиг на 2 разряда вправо, деление на 8 это сдвиг на 3 разряда вправо, и.т.д. На контроллере нам, как минимум, придется потратить 1 такт на осуществление этого сдвига. Итого в самом лучшем случае нам потребуется 2 такта машинного времени для нахождения среднеарифметического 4 чисел. Максимальная частота, с которой можно запихивать данные в контроллер составит в самом лучшем случае 5МГц, быстрее контроллер просто не успеет обрабатывать данные.


А если нужно больше? Да не знаю я зачем нужно больше! И вообще не задавайте глупых вопросов! Хочу просто!


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


Как же дела обстоят с ПЛИС? А на ПЛИС мы просто создаём схему, которая будет делать сложение 4 чисел, и сдвигать результат сложения на 2 разряда вправо. И всё это выполнять можно спокойно менее чем за такт, ПЛИС с этим справиться без проблем. Главное сделать правильную схему. Более того, в ПЛИС останется куча места для творчества, и таких вот модулей, которые могут находить среднеарифметическое, можно сделать очень много. И все эти модули будут работать одновременно и независимо друг от друга. Ограничение накладывает лишь количество портов.


Итак - ПЛИС позволяет вести обработку большого количества данных максимально быстро, и одновременно.


За счёт чего это получается? Приведу маленькую, мною придуманную притчу: взялись как-то ПЛИС и контроллер гвозди забивать на скорость. Контроллер взял свой самый большой молоток, оптимизировал свой алгоритм забивания гвоздей на максимальную производительность. И за 1 удар он своим молотком забивал 1 гвоздь. Контроллер смотрит на ПЛИС и ухмыляется. Не догнать его, он работает на пределе, и никто не может его обогнать! На что ПЛИС невозмутимо открывает свой чемоданчик и берет 100 маленьких, невзрачных молоточков, каждый из которых забивает гвоздь за 10 ударов. Видя, как ПЛИС забивает одним молотком гвозди, контроллер просто катается по земле от смеха, так-так она будет забивать гвозди еще миллионы циклов машинного времени, и ей никогда его не догнать. Но, глянув внимательно ещё раз, он увидел, что трудиться то 100 молотков, и постепенно ухмылка контроллера сменяется гримасой отчаяния. Ведь он уже далеко позади. ПЛИС не только догнала контроллер, но и пошла в отрыв, который стремительно увеличивается, и контроллеру за ПЛИС не угнаться !


В чём же дело? Почему контроллер проиграл ПЛИС? А всё дело в том, что, как я уже говорил ранее, контроллер это маленький компьютер, и он выполняет программу, т.е. последовательность операций, заложенную в него программистом. Причем операции выполняются какое-то фиксированное время, которое зависит только от архитектуры контроллера. И это ограничение обойти физически невозможно, поскольку архитектура контроллера – это набор функциональных блоков, которые физически расположены на кремниевой подложке микросхемы. И вы можете только оптимизировать код по критерию минимизации времени выполнения, т.е. написать максимально быструю программу.

С чего начать изучение FPGA (ПЛИС) ? Плис, Fpga, Схемотехника, Разработка, Электроника, Adruino, Длиннопост

На ПЛИС в отличие от контроллера, можно сказать, что нет такого понятия, как архитектура. В ПЛИС есть большая куча... Нет не так! В ПЛИС ОЧЕНЬ большая куча, универсальных логических элементов, которые могут реализовать базовые функции. Например, в ПЛИС Cyclone 3 EP3C10E144C8 таких логических элементов аж 10320 штук

С чего начать изучение FPGA (ПЛИС) ? Плис, Fpga, Схемотехника, Разработка, Электроника, Adruino, Длиннопост

Логический элемент может быть сконфигурирован как D-триггер, может быть мультиплексором, может быть элементом ИЛИ, может быть дешифратором и пр. Объединяя эти логические элементы, которые сконфигурированы на выполнение определённых функций, разработчик постепенно формирует цифровую схему, которая и выполняет возложенные на неё обязанности. Поскольку всю цифровую схему придумывает разработчик сам, он может реализовать арифметические операции так, что они могут выполняться быстрее, чем в контроллере, т.к. в контроллере, все операции вычисления выполняются универсальным элементом – АЛУ (арифметическое логическое устройство), которое умеет делить, складывать, умножать, сдвигать и пр. АЛУ предназначено для всей математики, поэтому одни операции АЛУ выполняет быстрее, а другие медленнее, это зависит от архитектуры контроллера.


На ПЛИС вы сами формируете схему выполнения этих операций. И скорость работы математики будет зависть только от правильности составленной схемы. Более того в ПЛИС, логические ячейки могут работать одновременно, и во власти разработчика реализовывать несколько независимых потоков вычислений. К примеру один модуль делит, второй умножает, третий складывает, четвертый двигает. Задача разработчика - правильно синхронизировать эти параллельные потоки, чтобы схема работала, так как вам надо. Так-же на ПЛИС реально реализовать собственный микроконтроллер, который даже можно программировать как обычный...


Казалось бы если ПЛИС - такая крутая и быстрая штука, то зачем вообще нужны контроллеры? Во-первых - экономическое обоснование. Сравните цены контроллера и ПЛИС, и увидите разницу в цене более чем в 10 раз. Во-вторых - не всегда нужна высокая производительность, которую можно достичь на ПЛИС. Например, вы считываете с датчика температуры показания, и выводите на простенький индикатор. В данной задаче разница в скорости выполнения измерений за 100 тактов на контроллере, или за 1 такт на ПЛИС, на результат почти не влияет, поскольку температура – это очень инертная вещь, которая изменяется бесконечно долго по меркам машинного времени. Зачем покупать дорогую ПЛИС, когда можно купить копеечный контроллер, который прекрасно справиться со своей задачей? Да и запрограммировать контроллер гораздо легче, чем ПЛИС. Ведь вы, наверное, догадались (я на это очень надеюсь), что ПЛИС не выполняет программу , а внутри неё реализуется цифровая схема, придуманная вами. А цифровую схему надо ещё придумать, отладить, протестировать, добиться стабильности, о чём я постараюсь рассказать в следующих постах.


Процесс создания цифровой схемы внутри ПЛИС во многом похож на создание схемы из кучи корпусов микросхем средней степени интеграции, таких как К155 или К555 серии, либо других серий логики. Только очень, и очень быстрой. Не каждый новичок обладает достаточными знаниями, чтобы с ходу взяться рисовать схемы. Ведь написать программу для контроллера и отладить её куда проще, чем нарисовать схему. Да и для работы с ПЛИС надо знать не только цифровую схемотехнику, но и различные интерфейсы. Например, если приёмопередатчик RS232 (COM порт) на большинстве контроллеров "вшит" внутри контроллера и в контроллере его надо правильно сконфигурировать, то на ПЛИС надо его реализовать самостоятельно. Допустимый вариант найти в интернете готовую схему RS232 контроллера для ПЛИС, со всеми багами и глюками оставленные разработчиком…


Именно из-за сложности и времени разработки, высокой цене отладочных плат, и отсутствия задач, где требуется высокая производительность, достигаемая на ПЛИС, она не снискала такой популярности в отличие от контроллеров. В частности небезызвестная платформа Arduino, разобраться с которой может и школьник, за несколько дней. А ведь на ПЛИС ещё и моделировать схему надо, есть куча подводных камней, таких как, пересечение доменов синхрочастоты, метастабильность триггеров, глитчи, синхронизация асинхронного сброса, и прочая лабуда. Вы пока не запоминайте всякие умные слова, потом может быть, я чуть подробнее коснусь этих тем. Это я просто нагнетаю обстановку.


Итак, если ПЛИС дорогая, разработка сложная, и долгая - тогда зачем она нужна? Взять контроллер "пожирнее" и все! А ответ скрывается в моих примерах. В ПЛИС если правильно создать схему, можно добиться производительности в обработке данных, которая контроллерам и не снилась. Более того, в опредёлённом круге задач современные ПЛИС могут дать фору и современным моделям микропроцессоров! ПЛИС крайне выгодно применять, когда скорость вычислений не очень критична, но требуется большое количество портов ввода\вывода, либо одновременность и независимость работы этих портов ввода\вывода. С этим у ПЛИС проблем нет. За счёт параллельности работы, логических ячеек в ПЛИС можно реализовать ряд устройств, работающих независимо друг от друга - и таким образом сэкономить на количество корпусов на печатной плате - что в итоге может существенно снизить стоимость изделий.


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


Итак, если вы вдруг всё же решитесь взяться за изучение ПЛИС - то начинать надо в первую очередь с основ цифровой схемотехники. После того, как вы познаете тайный смысл слов таких как: счётчик, мультиплексор, компаратор, шифратор, дешифратор, исключающее ИЛИ и прочие умные слова, услышав которые, у вас появлялось стойкое желание спрятаться под кровать и биться в припадке (у меня так и было, честно-честно), необходимо выбрать среду моделирования и софт производителя ПЛИС. Я считаю, что начинать изучать ПЛИС надо с Altera, поскольку их среда разработки - Quartus, крайне проста и удобна в освоении за счёт простого и понятного интерфейса, в отличие от ISE фирмы Xilinx. В принципе, есть и другие производители ПЛИС такие как: Lattice Semiconductor, Actel, но это скорее экзотика, которая не очень походит для изучения ПЛИС.


После выбора среды разработки на ПЛИС, крайне желательно установить среду моделирования Modelsim, производства компании Mentor Graphics. Хотя софт от разработчика ПЛИС и предоставляет инструменты отладки и моделирования схем, однако у них очень ограниченный функционал, да и Quartus от Altera недвусмысленно намекает, что моделируйте схемы в Modelsim. Но на начальном этапе, можно эти намёки игнорировать.


Итак, основы схемотехники вы познали, софт разработки и моделирования установили. Необходимо определиться со способом описания схем в ПЛИС. В настоящее время в основном используется 3 основных способа описания схем на ПЛИС:


Первый – это рисование цифровых схем из элементов, такие как триггеры, счётчики, мультиплексоры и пр. Т.е точно также, как создавали схемы раньше. Например, в САПР Quartus этот способ ещё доступен, но данный способ подходит только для простых схем, поскольку в больших проектах схема становиться не читаемая.

С чего начать изучение FPGA (ПЛИС) ? Плис, Fpga, Схемотехника, Разработка, Электроника, Adruino, Длиннопост

Второй способ – это использовать среду Matlab но, к сожалению, я про этот способ почти ничего не знаю.


И самый продвинутый и удобный способ - описание на языке HDL - hardware description language (Язык описания аппаратуры). На данный момент самые распространённые языки это Verilog и VHDL. Также активно развиваются языки System verilog, System C, про них я говорить не буду, поскольку знаю про них чуть больше чем ничего.

С чего начать изучение FPGA (ПЛИС) ? Плис, Fpga, Схемотехника, Разработка, Электроника, Adruino, Длиннопост

Изначально как Verilog, так и VHDL применялись для описания схем, созданных в схемном виде, и для моделирования этих схем. Но потом умные люди смекнули, что можно эти языки применять и для создания этих схем. И появилось RTL (Register transfer level) подмножество этих языков - уровень регистровых передач. Т.е теперь можно писать программу описывать схему в виде текста, которая средствами САПР будет синтезироваться в схему, на ПЛИС, которая вам нужна. И это оказалось весьма и весьма удобно, именно поэтому текстовый ввод получил наибольшее распространение.


Но из-за того, что основная и первоначальная задача этих языков – это моделирование, появилась жуткая путаница, поскольку часть языковых конструкций применяется для моделирования, а другая часть для синтеза. И часто начинающий разработчик на ПЛИС не читает документацию и стандарты к выбранному HDL языку, и применяет языковые конструкции, которые в реальную схему синтезироваться не могут, и долго не может понять, а почему схема не работает? Появлению этой путаницы немало поспособствовали авторы книг по HDL языкам. Очень многие авторы сначала долго и муторно пишут про подмножество языка, предназначенного для моделирования, а про синтезируемое подмножество пишут только в середине, или посвящают этому несколько глав в конце книги. Получается, что человек прочитал половину книги, а это всё предназначено только для моделирования синтезируемой части языка. А ведь, правда. Кто сразу садиться за моделирование? Чтобы приступить к моделированию, необходимо иметь объект моделирования, т.е. синтезируемую схему. А как её получить читателя не научили.… Более того, правильное написание синтезируемой части языка, основные правила практически не раскрываются в книгах, а если и раскрываются, то очень поверхностно. В итоге получается, что те, кто учиться на примерах, поставляемых фирмой Altera или Xilinx, описывают схемы гораздо лучше, чем те кто учился по книгам, но моделируют хуже.


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


В дальнейшем, если я продолжу писать посты, я буду везде давать примеры на языке VHDL, которым владею. Посоветовать выбрать какой-то конкретный язык описания: Verilog или VHDL я не могу. Причина в том, что каждый язык имеет преимущества и недостатки. Холивары на эту тему идут до сих пор. Но в любом варианте язык – это инструмент. Посмотрите примеры описаний на языках HDL в интернете, и выберете тот, который вам нравиться внешне, большего посоветовать не могу.


Итак, давайте подведём краткие итоги всего написанного мной:

1. ПЛИС штука нужная, быстрая, и дорогая. И применять её надо там, где она реально нужна. И выбор «ПЛИС или микроконтроллер» зависит в первую очередь от класса задачи, срока реализации.

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

3. Для начального обучения разработки на ПЛИС достаточно установить среду моделирования, или среду разработки. На начальном этапе отладочная плата не нужна, поскольку работу схемы можно смоделировать.

4. Книги, безусловно, нужны, но книги не панацея, и лучшее понимание синтезируемой части языка дадут примеры, которые выкладывают в свободный доступ разработчики ПЛИС, в частности Altera и Xilinx. Практика и ещё раз практика.

5. Начать изучение ПЛИС лучше всего с написания простейших логических элементов, таких как, мультиплексор, триггер, счётчик, и пр. И постепенно наращивать сложность схем, параллельно читая книги, и осваивая новые языковые конструкции, и самое главное, понимая, во что они реально синтезируются внутри ПЛИС.


Ссылки рекомендуемые к просмотру:

1. http://www.kit-e.ru/articles/circuit/2008_3_161.php

2. http://we.easyelectronics.ru/plis/mk-vs-plis.html

3. http://we.easyelectronics.ru/plis/osnovy-vhdl-primer-prosche...

4. http://we.easyelectronics.ru/plis/vhdl-s-nulya.html

5. https://electronix.ru/forum/index.php?showtopic=88290&st=135

6. https://habrahabr.ru/post/274829/

Найдены дубликаты

+3

зарубежную аббревиатуру FPGA (Field-Programmable Gate Array), что переводиться как Программируемая Полем Вентильная Матрица (ППВМ)

Откуда такой около-эзотерической перевод "программирование полем" (пусть и электрическим)? Даже мой препод 20 лет назад этим страдал; наверное, советских источников начитался.


"Field-" у америкосов используется в смысле "посреди чистого поля" -- не снимая изделие с его рабочего места, без нужды везти в мастерскую. Ищем в толковых словарях "field service", "field repair".

раскрыть ветку 3
0

вроде, устоявшееся название "Программируемая пользователем...", и да, field тут означает "на лету", после того, как устройство было изготовлено.

раскрыть ветку 1
0

Возможно Вы и правы. Но исправить уже не могу. Время вышло...

0

К сожалению английский язык не мой родной язык, и дословный перевод я мог сделать и с ошибкой. Каюсь. Дадите правильный вариант перевода - подправлю.

В конце концов я везде применяю более понятную русскому человеку аббревиатуру - ПЛИС.

+2

Есть хорошая книжка(описание на хабре https://habrahabr.ru/post/306982/):

Digital Design And Computer Architecture (Russian Edition) Second Edition

(Цифровая схемотехника и архитектура компьютера)

Авторы: Дэвид Мани Харрис и Сара Л. Харрис

+1

Стандарт OpenCL, разработанный KRONOS GROUP, уже успел завоевать

популярность среди разработчиков программного обеспечения для решения задач с

высокой вычислительной сложностью. Основанный на языке С, он позволяет существенно

сократить время разработки кода для гетерогенных систем с самым разнообразным

составом вычислительных устройств. Широкое распространение стандарт получил, во

многом благодаря поддержке со стороны модулей GPU. В отличие от своего аналога nVidia

CUDA SDK, OpenCL не ограничивает круг поддерживаемых устройств каким-либо

конкретным брендом, а напротив, позволяет собрать под «одной крышей» разных

производителей и разные классы вычислителей.

Одно из новых направлений в развитии гетерогенного программирования –

применение языка С и стандарта OpenCL для проведения вычислений на ПЛИС

(программируемых логических интегральных схемах, FPGA). Гибкость

реконфигурируемой архитектуры FPGA весьма привлекательна для реализации

вычислительно сложных алгоритмов и позволяет производить синтез высокоэффективных

решений, отличающихся от других архитектур существенно меньшим энергопотреблением

при схожих показателях быстродействия.

подробно http://eulerproject.com/study.html

+1
Прочитал с огромным интересом (и даже вечное «ться» этому не помешало).

Главный вопрос:
Если ПЛИС – это такая специальная железка, то нельзя ведь просто так описать её, скомпилировать и успокоиться?

Надо ж ещё договориться с фирмой, чтобы её сделали под меня две штуки (чтобы, когда одну я сожгу, осталась вторая), и, когда через месяц её сделают и через ещё две недели она придёт ко мне (если Почта России не сопрёт такую ценную вещь) – я смогу убедиться, что проглядел досадный баг и го заказывать по новой? :)
раскрыть ветку 5
0
Если ПЛИС – это такая специальная железка, то нельзя ведь просто так описать её, скомпилировать и успокоиться?

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

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

раскрыть ветку 4
0
Но ведь всё равно она готовится индивидуально?
раскрыть ветку 3
0
Почему больше не пишешь про ПЛИСины?
раскрыть ветку 2
+2

У меня есть заготовки следующего поста, но как-то вдохновения писать нет... Я думаю несколько по-другому построить структуру постов. Если я буду долго и нудно писать всякие основы-основ - то это никого не обрадует, поскольку это будет скучно и долго. А вот если я сначала приведу несколько примеров простеньких устройств, тогда может народ и заинтересуется.

раскрыть ветку 1
0
Именно так) мк уже наскучили, хочется попробовать плисины. Пиши..
0

Спасибо, буду ждать след. посты

0

пробовал на ней майнить биткоины?

раскрыть ветку 2
0

Специализированные процессоры (ASIC) могут содержать FPGA модули для решения ряда задач. Возможно в нынешних биткойн молотилках тоже есть такие модули.

-2

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

0
Подписался.
-1

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

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

P.S Спасибо, что напомнили про эту книгу, запамятовал, что он тоже достойна к прочтению.

Похожие посты
Похожие посты закончились. Возможно, вас заинтересуют другие посты по тегам: