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

dxp

Свой
  • Постов

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

  • Посещение

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

    14

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


  1. Кто заменяет? И что -- таки она существует -- невозможность его заменить?
  2. Каждый раз после паузы. Или отвлечения на другие части проекта. И не говорите. Вообще этот С++ -- понапридумывали какой-то фигни: какие-то классы с сокрытием представления, мутная перегрузка функций и операторов -- никогда не знаешь, что там вызывается на самом деле, шаблоны -- это вообще тихий ужос, особенно в руках извращенцев из Boost'а и комитета по стандарту языка. Не зря Линус его не любит и запретил. То ли дело С!
  3. Отвечу вам первый и, возможно, последний раз. По существу возразить нечего, начали всякую чушь нести про "некогда длинно писать", "надо было ещё вчера" и прочая ерунда, как будто набор букв как-то значительно влияет на продуктиность труда программиста. Теперь до имени докопались. Как будто не понятно, что пример всего лишь иллюстрирован принцип, и в реальном проекте код проектируется совсем не так -- указывать цвет при каждом вызове для каждого объекта... есть решения получше. У вас у самого в примере лажа: линия (отрезок) имеет координату и длину, этого категорически недостаточно для описания отрезка на плоскости -- нужен ещё либо угол (если это полярные координаты), либо длину заменить парой координат второго конца отрезка (как в моём варианте). Но я не стал на это обращать внимание, т.к. это в обсуждаемом контексте совершенно не важно, т.к. обсуждается стиль написания кода, а не проектирование графических элементов. Вы привели пример, на это вам привели другой пример, где вполне сочетается передача множества параметров с самодукументированным видом, причём, предоставляя полную гибкость -- можно выбирать произвольный набор параметров, не привязываясь к порядку, и без потери эффективности, т.к. все функции тривиальные и встраиваемые. По делу (по технике) вы ничего возразить не смогли. Спровоцировать на флуд и тем более флейм меня не получится. Нет технических аргументов -- обусуждение закончено. Не встречал ничего более уродливого и бесполезного, чем doxygen. Загажнные мусором исходники, бестолковое, ничего не объясняющее описание, информативность которого даже ниже нормально написанного (самодкументированного) кода.
  4. Не догоняю, чем вам реализация так не нравится. Эти функции-члены -- суть интерфейс класса. Через них устанавливаются значения объекта -- это тут для простоты написана struct, а в норме это class, где представление сокрыто и защищено. Всё общение только через явный интерфейс. Поведение его простое и прозрачное. Это самый что ни на есть базовый С++, что тут может быть не так с реализацией, не пойму. А в этом примере просто вызовы функций зацеплены в "паровозик", только и всего.
  5. Когда вы встречаете это: Line({10, 20}, 50, RED, &win); вам сразу всё понятно, что тут происходит или таки надо посмотреть код этого самого Line? Подозреваю, что таки надо. Ну, и в случае класса это один раз нужно сделать. А если вы знакомы с этим приёмом, то вам и все остальные элементы, выполненные по аналогии, сразу станут понятны, может даже и смотреть не придётся. Приём этот называется Named Parameter Idiom (https://isocpp.org/wiki/faq/ctors#named-parameter-idiom). Через пару месяцев, когда снова попадётся этот код Line({10, 20}, 50, RED, &win);, скорее всего опять придётся смотреть код этой функции -- какой аргумент там что означает, а вот Line(win_handler).start({10, 20}).end({30, 40}).col(0).draw(); вопросов скорее всего не вызовет, т.к. идиома запоминается намного легче, чем позиционные параметры какой-то функции, а параметры тут читаются с листа.
  6. С чего бы ей возвращать ссылку на какой-то левый объект? Это надо специально постараться ещё туда этот объект как-то передать. Ну, а от ошибок ни один способ не защищает, одни помогают их минимизировать, другие нет.
  7. Хорошего то, что читается на раз и запись компактная. Реализация тривиальная -- один раз посмотрел и дальше можно не гадать, всё делается одинаково. В программе, которая рисует графику, таких вызовов (рисования объектов), как правило, достаточно много, читается такой код легко, даже если вызовы пишутся в произвольном порядке. Главное, чтобы draw() была в конце. А если какая-то из функций не вернёт ссылку на себя, получится ошибка времени компиляции.
  8. C компилятор без проблем даст поменять местами double и int. Или int и int. Или double и double... От этого не легче -- вкрадывается подлая ошибка, замыленный глаз не видит, проявляется это где-то в другом месте, отладка весьма муторна и сильно портит продуктивность. Проблема общая: если параметров больше 3, запоминать это уже тяжело. Просто в HDL в отличие от конвециональных ЯП в силу своей природы в норме могут иметь десятки параметров (портов модуля), поэтому там сразу озаботились именованными аргументами. С++20 тож могёт (и тип явно приводить не надо): struct lparams_t { int pos_x; int pos_y; int len; int color; int win; }; void draw_line(lparams_t params) { ... } int main() { draw_line( {.pos_x = 10, .pos_y = 20, .len = 100, .color = 0, .win = 1} ); return 0; } Что касается общего подхода, то было бы желание делать читабельный и сопровождабельный код. На приведённом примере: т.к. рассматривается элемент графики, на С++ это в норме реализуется в виде класса: #include <iostream> struct Point { int x; int y; }; struct Line { Line(int o) : owner(o) { } Line &start(Point p) { p1 = p; return *this; } Line &end(Point p) { p2 = p; return *this; } Line &col(int c) { color = c; return *this; } void draw() { std::cout << "owner: " << owner << " | " << " p1.x: " << p1.x << ", p1.y: " << p1.y << " | " << " p2.x: " << p2.x << ", p2.y: " << p2.y << " | " << " color: " << color << std::endl; } int owner; Point p1; Point p2; int color; }; int main() { int win_handler = 1; Line(win_handler).start({10, 20}).end({30, 40}).col(0).draw(); Line(win_handler).start({11, 22}).end({33, 44}).col(5).draw(); Line(win_handler).start({55, 66}).end({77, 88}).col(9).draw(); return 0; } Выхлоп: owner: 1 | p1.x: 10, p1.y: 20 | p2.x: 30, p2.y: 40 | color: 0 owner: 1 | p1.x: 11, p1.y: 22 | p2.x: 33, p2.y: 44 | color: 5 owner: 1 | p1.x: 55, p1.y: 66 | p2.x: 77, p2.y: 88 | color: 9 Разумеется, графика на С++ так не пишется, там в полный рост ООП с иерархиями классов, наследованием и виртуальными функциями, здесь просто принцип показан. Писанины при вызове не больше, читабельность на уровне -- сразу понятно без изучения формальных параметров, что тут к чему. В общем, было бы желание писать аккуратный самодокументирующийся код, а способы находятся.
  9. Гуры программирования вроде Б.Страуструпа говорят, что хороший стиль выполнения фунций таков, что аргументов функций не должно быть много -- лучше всего один-два, три тоже приемлемо в обоснованных случаях, особенно, если это редкоиспользуемый аргумент со значением по умолчанию. Если надо больше передавать, то упаковывать в объект структуры или класса и передавать по констатнтой ссылке. Размер функции тоже не должен быть большим -- функции на пять экранов -- плохо. Полтора экрана максимум. Если выходит больше -- то рефакторинг с разбиением на функции (накладные на их вызов можно нивелировать, сделав их встраиваемыми). Такой стиль написания кода значительно облегчает и разработку, и чтение, и сопровождение. Если много параметров для передачи надо засунуть в вызов, то требуются именованные агрументы. Например, в Verilog/SystemVerilog синтаксис модуля похож на Сишный, и там обычно много портов (аргументов -- по аналогии с функциями), такова природа языка. И там тоже можно передавать значения сигналов, соблюдая порядок, но если их больше двух, то повсеместно испольют именованные: fifo_sc_m #( .DATA_ITEM_TYPE ( pkt_tag_t ), .DEPTH ( ZONE_PROPS_QUEUE_DEPTH ), .MEMTYPE ( "lutram" ) ) pkt_tag_queue ( .clk ( clk ), .rst ( rst ), .tail ( pkt_tag_q.tail ), .head ( pkt_tag_q.head ), .push ( pkt_tag_q.push ), .pop ( pkt_tag_q.pop ), .full ( pkt_tag_q.full ), .empty ( pkt_tag_q.empty ), .wr_rst_busy ( pkt_tag_q.wr_rst_busy ), .rd_rst_busy ( pkt_tag_q.rd_rst_busy ) ); Это введно в язык (Verolig) изначально, т.к. сразу были понятны проблемы позиционной передачи портов, когда их много. Получается по сути тот же вариант, что выше привёл @Forger со упаковкой агрументов в структуру. Различаемость аргументов при чтении кода, когда их много, крайне важна. Иначе получается write-only код. Спорить, доказывать никому ничего не буду. Это мнение опытных в Computer Science людей (кроме Б.Страуструпа встречал подобные рекомендации и от других гур, но навскидку не вспомню, да и не суть). И я с ним согласен -- многолетний опыт только подтверждает это..
  10. Он поддерживает традиции старой Opera (его разработчик этой старой Opera инициировал после того, как Opera охромилась и стала уг): возможности настройки интерфейса под свои предпочтения. Для меня в первую очередь возможность панель вкладок размещать сбоку, что позволяет открывать много вкладок без потери их идентифицируемости (читабельности) -- да, это съедает место сбоку, но на широких мониторах горизонтальное пространство не такое дефицитное, как вертикальное. А вкладок у меня обычно много (на этом экране их не так много, т.к. это окно для оперативной работы -- форум почитать, спонтанные поисковые запросы и т.п., в других окнах их много больше -- обычно они там тематически подобраны, удобно переключаться между их наборами с помощью Workspaces). Ну, и настройка горячих клавиш почти подо всё (хотя не так круто, как в старой Opera). Может, другие браузеры тоже подтянулись по этим вопросам, но на момент переезда со старой Opera на этот, никто из популярных (Chome, Yandex, новая Opera, Firefox и проч.) так не умел. Всякие плагины боковых панелей выглядели костыльно и работали плохо, а горячие клавиши назначать вообще не позволяли. Ещё радует то, что браузер автоматомитически запоминает, сколько было открыто окон и какие в них вкладки. В случае аварийного завершения работы браузера или компьютера последующий запуск браузера всё восстанавливает -- это прям вообще классная фича, иначе утерянный контекст восстановить бывает непросто, а каждый раз открытый набор вкладок сохранять как сессию обременительно. Всякие остальные плюшки вроде Workspaces, Skins, заметок тоже в наличие. Я очень не люблю программы, которые навязывают свою манеру использования, и большинство браузеров, к сожалению, таковыми и являются: типа авторы программы лучше меня (пользователя) знают, как мне работать -- чувствуешь себя придадком к программе. Vivadi благодаря богатым опциям настройки интерфейса и его функциональным возможностям позвояет себя чувствовать хозяином программы. 🙂
  11. Давно замечал этот эффект: выделяешь текст, жмёшь, например, на B (Bold), выделение молча снимается, текст жирным не выделяется. Так можно повторить несколько раз. Обычно помогает, если второй раз (когда первый не сработал) выделять текст иначе -- например, в первый раз выделяли от начала текста, а второй -- с конца. Неприятная особенность. Браузер тоже Vivaldi но думается, дело не в браузере -- это тот же Chrome под капотом. И проявляется это с самого начала перехода на новый движок, версий браузера с тех пор сменилось не один десяток. Про другие браузеры сказать не могу, не пользуюсь.
  12. Зависит от реализации. Например, у Zynq7000 внутренняя память 256к находится на уровне L2 (там же, где и L2 кэш), тактовая там в два раза ниже, чем на ядре, зато шина от ядра к этой памяти в два раза толще системной, то обеспечивает тот же поток. Скорость, конечно, будет меньше из-за большей латентности доступа. Но настоящая беда со скоростью, когда надо интенсивно лазить наружу -- в SDRAM.
  13. Ну, не сам кэш, а управление свойствами регионов, где и свойства кэширования задаются. Но скорость -- это одно, и сильно падает она преимущественно при доступе во внешнюю память, а baremetal программа вполне может работать во внутренней памяти (которая обычно там есть в количествах 64..256 кбайт). Тем не менее с тормозами оно хотя бы работает. А вот корректная работа с периферийными регионами просто невозможна. Однако, ADI это для промышленного применения двигали. Точно не помню, но вроде попадался даже чуть ли не какой-то мелкий осциллограф (лет 10-15 назад, китайский клон какого-то то ли LeCroy (типа WaveAce), то ли ещё кого), где управляющим процессором был Blackfin. Подозреваю, что GUI прибора реализовывался не на baremetal.
  14. Ещё раз. Я спросил (не у вас), можно ли выключать MMU безопасно. Вы встряли с ответом, сказав, что можно, что Cortex-M сам знает, где что лежит. У Cortex-M нет никакого MMU, там просто захардкодили свойства регионов адресного пространства. В сложных системах на Cortex-A это делается с помощью MMU, где всё это программируется через регистры. Т.е. речь изначально шла про системы с MMU. И в них именно MMU рулит свойствами регионов адресного пространства. При чём тут МК вообще? Да, выключен обычно. И его включают. И далеко не только в Linux. Его включают ещё на этапе первичного загрузчика (самый первый код, который запускает BootROM, определив через bootstrap pins источник, откуда грузить код. Чаще всего это, что называют Preloader, у Xilinx оно называется FSBL -- First State Bootloader), на этапе ассемблерного пролога задолго до вызова main этой программы. Если вы его не включали, это не значит, что оно не было включено. Его для вас заботливо включили ещё на этапе первичного загрузчика, где инициализируется вся эта непростая аппаратура (L1 Cache, L2 Cache, SCU, MMU). После выполнения первичного загрузчика вы имеете готовую к использованию для baremetal аппаратуру. Трансляция адресов в MMU при этом не включена. Это вторая функция MMU. Но MMU при этом включено и обеспечивает корректность работы с регионами памяти на низком уровне, включая методы кэширования.
  15. Тогда о чём речь? Мы говорим про "выключить MMU", можно ли это безопасно сделать. Выключить можно то, что есть. Оно есть в Application процессорах. Можно ли безопасно выключать MMU в Application процессорах? При чём тут вообще МК?
  16. В Cortex-M может и знает, а вот в Cortex-A уже не очень. Потому как там внеочередное выполнение инструкций с переименованием регистров, чтение бёрстом размером в линию кэша и т.п, что запросто приводит к неприятным эффектам при доступе к MMR. И в Cortex-M, насколько мне известно, никакого MMU нет. И для поддержания корректности таких обращений ARM придумал в AXI специальные поля, которые инфраструктуре доступа в память сообщают, как осуществлять физический доступ в память к той или иной области. И управляет этими полями как раз MMU. формируя AXI транзакцию. И, помнится, в Cortex-M AXI не используется, там AHB/APB.
  17. А кто разруливает корректность обращения к разным типам памяти? Например, блокирует спекулятивное чтение из MMR регистров периферии, где недопустимо читать некоторые регистры (адреса памяти) просто так, т.к. чтение является разрушающим? Или запись в подобные области, где требуется строго соблюдать порядок обращения (чтобы команды включения периферийного устройства и записи в его регистры не поменялись местами -- современные CPU такое запросто делают, когда не обнаруживают связи между обращениями)?
  18. Какой-то смысл есть. ADI вложили прилично усилий в uCLinux для своего Blackfin, у которого нет MMU (хотя в остальном проц вполне для своего времени норм -- быстрый, кэши и т.п.). Позиционировали они его в том числе и как мультимедийный процессор для построения на его основе разного рода музыкальных и видео плейеров. Если всё это делать на baremetal, то это путь портирования кучи софта, который уже есть, который отлажен и исправно работает -- это разного рода кодеки, конвертеры форматов. А имея Linux -- пусть даже в кастрированной версии uCLlinux, весь этот зоопарк софта заезжает туда практически без изменений. Плюс поддержка файловых систем из коробки. Плюс полноценные сетевые возможности. Плюс GUI. И т.д. Главная проблема uCLinux как системы без поддержки MMU в том, что она очень уязвима для сценария, когда на ней запускают сторонние приложения, когда любое приложение может в случае ошибки завалить всю систему. Поэтому в пользовательские OC uCLinux не пошла. Но для сценария, когда на ней строят закрытую платформу, не предназначенную для запуска стороннего софта, когда к коду ОС и приложений имеет доступ только ограниченный круг разработчиков дивайса, картина существенно меняется. Да, на этапе разработки ошибки приложений будут по-прежнему заваливать ОС, но это обычное дело -- когда пишут драйвера (модули ядра) полноценного Linux, ситуация точно такая же. А когда разработка закончена, ПО оттестировано, у потребителя уже никаких дополнительных рисков нет -- он использует дивайс в рамках, предоставленных производителем. Другое дело, что профита от мощных процов без MMU при нынешнем развитии микроэлектроники (чипдизайна и технологий производства) почти нет -- стоимость MMU исчезающе мала на фоне остального, а преимущества, которое оно даёт, очень большое, начиная от поддержки разных моделей памяти (Normal, Device, Strongly-ordered, в терминологии ARM) и заканчивая аппаратной трансляцией адресов (защищённый режим работы памяти). Поэтому по факту uCLinux уже отошёл в историю.
  19. Разве можно MMU отключать, если он есть? Или речь про отключение только трансляции адресов?
  20. Matlab/Python не для моделирования в смысле симулятора (Matlab-то тоже не симулятор, не про Simulink речь), а для моделирования алгоритма. Ну, средствами языка программирования -- высокоуровневые ЯП для этого удобны.
  21. Насколько понял, смысл следующий: Идеальные компоненты дают возможность моделировать именно принцип, алгоритм, но уже детально. При этом паразитные параметры, которые учитываются моделью, тут не мешают. Отладив алгоритм, можно перейти к реальным моделям в другом мощном бесплатном симуляторе, имея референсную идеальную модель, и в нём уже подбирать компоненты так, чтобы их неидеальные свойства портили картину в пределах допустимого. Идеальные (сиречь, упрощенные) модели позволяют существенно увеличить скорость моделирования. А учитывая, что и модели специальные, то они тоже оптимизированы для сокрости. Т.е. это инструмент первой пробы. Когда от расчётов осуществляется переход к моделированию, то на первом этапе вот такой симулятор может оказаться очень кстати. P.S. Сам не пользовался. 🙂 Может просто не дорос -- пока хватало моделирования с помощью Matlab/Python.
  22. Имеется в виду, что клок -- это сигнал, который присутствует всегда, независимо от того, идут данные или нет -- например, сигнал SCK в SPI -- это не клок, а просто сигнал синхронизации. Поэтому к начальной фазе клока привязаться нельзя, а только к тому или иному фронту. Поэтому инвертирование для клока по барабану -- дальнейшая логика "привяжется" к нужному фронту или PLL (если она там) зацепится за как надо. Я про 600 ppm выше и писал -- это как бы и указывает, что если PCIe физику можно тактировать от разных источников, то про "переполюсовку" тут вообще говорить не приходится. 🙂 Про джиттер тоже, вроде, были чиселки в спеке, "но это не точно" (с ходу не вспомню).
  23. Ну, так это имеет смысл только для данных, не для клока.
×
×
  • Создать...