Pull to refresh

Comments 12

Какая суровая магия! Особенно описание аппаратуры на Scala (впервые в жизни такое вижу, я знаю только VHDL и Verilog).
Как раз в выходные думал, не вспомнить ли молодость, не заказать ли отладочную плату с FPGA (в университете был курс, работали с платой на Spartan-3E от Digilent), но понял, что я же абсолютно не знаю, как сделать что-то сложнее счётчика, где взять готовый модуль контроллера для той же DDR SDRAM. А тут аж целый процессор, уважуха!

я где-то слышал, что, вроде бы, бесконечный цикл — это Undefined Behavior
Это в С++. В С, насколько я помню, нет понятия undefined behavior.
И это undefined behavior только в том случае, если цикл не делает ничего из нижеперечисленного:
  • Вызывает библиотечную I/O функцию
  • Читает или модифицирует volatile объект
  • Выполняет atomic операцию либо операцию с объектом синхронизации.

Спасибо! :) На всякий случай уточню: моего кода здесь и 0.1% не наберётся — я его только портирую на нестандартную плату


Если надумаете покупать плату, рекомендую попробовать для начала синтезировать целевой дизайн: я вот сначала думал вообще на втором "Марсоходе" попробовать RocketChip, а оказалось, он даже минимальный приблизительно 16K ячеек (против 10 у платы). А когда я переключился с Tiny ядра на Small, использование подскочило до ~30K (и 60K у Big)! А я ещё думал, не купить ли что поизвестнее да попроще!..


Кстати, сейчас на чём только аппаратуру не пишут: Haskell, Scala, даже Python. Но на Scala добрые люди целый процессор написали!

Это ещё вопрос, что сложнее: написать с нуля код под целевую платформу, или портировать готовый, но неподходящий.

Спасибо за совет, тоже была такая мысль, что неплохо бы иметь проект, синтезировать его, посмотреть, сколько нужно ресурсов. Но как же я его напишу, если даже не знаю, какого производителя лучше взять FPGA :) Но вы правы: для того, чтобы погрузиться в проектирование и синтез, что-то напроектировать и даже верифицировать, железка не нужна.

Есть вообще чудо техники: FireSim — ему даётся маленький инстанс на Amazon, ключ API и исходник на Chisel, а он сам развернёт сборочные инстансы, FPGA-инстансы, прогонит тесты. Правда смущает вот что:


  • после прочтения этой статьи я как-то начал опасаться сочетания постоплатной системы и API-ключей. Впрочем, с тех пор, возможно, всё десять раз поменялось
  • не знаю, нет ли риска "спалить" FPGA-ускоритель аппаратно (а стоит он, наверное, весьма немало)

А вообще было бы забавно (даже без FireSim и API-ключей): "На AWS нет нужной архитектуры процессора — сейчас исправим!" — ПЛИСины там стоят огромные и стоимость аренды гуманная (подсказка: спотовые инстансы существенно дешевле, если подходят в плане доступности под задачу — не "всегда on-line", а "когда-нибудь посчитать подешевле").

Кстати, как говорится, на правах рекламы: если вдруг будет интересно из серии "написать с нуля", тут я экспериментировал с генерацией композитного сигнала как раз на "Марсоходе", но предупреждаю, там редкостный гов^Wнеидиоматичный код с точки зрения HDL, зато с нуля. :)

В С, насколько я помню, нет понятия undefined behavior.
Хаха
список более чем на 10 страниц в PDF
The behavior is undefined in the following circumstances:
— A ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint is violated(clause 4).
— A nonempty source file does not end in a new-line character which is not immediatelypreceded by a backslash character or ends in a partial preprocessing token orcomment (5.1.1.2).
— Token concatenation produces a character sequence matching the syntax of auniversal character name (5.1.1.2).
— A program in a hosted environment does not define a function namedmainusing oneof the specified forms (5.1.2.2.1).
— The execution of a program contains a data race (5.1.2.4).
— A character not in the basic source character set is encountered in a source file, exceptin an identifier, a character constant, a string literal, a header name, a comment, or apreprocessing token that is never converted to a token (5.2.1).
— An identifier, comment, string literal, character constant, or header name contains aninvalid multibyte character or does not begin and end in the initial shift state (5.2.1.2).
— The same identifier has both internal and external linkage in the same translation unit(6.2.2).
— An object is referred to outside of its lifetime (6.2.4).
..........
Хм, спасибо, не знал. В общем-то, эти все условия понятные, для совсем тяжелых случаев, больше disclaimer, чем особенность языка. В С++ много случаев undefined behavior разрешены для оптимизации (хотя случай с бесконечным циклом вряд ли относится к этой категории).

Я бы не рекомендовал пытаться разделить UB на логичный и "да к этому же никто не придерётся" :)


Например, как может повести себя приблизительно такой код? (пример скопирован со StackOverflow)


// Zero-filled global buffer of 16 characters
char destBuffer[16];

void Serialize(bool boolValue) {
    // Determine which string to print based on boolValue
    const char* whichString = boolValue ? "true" : "false";

    // Compute the length of the string we selected
    const size_t len = strlen(whichString);

    // Copy string into destination buffer, which is zero-filled (thus already null-terminated)
    memcpy(destBuffer, whichString, len);
}

Отгадка

Вы самую интересную часть опустили:
int main()
{
    // Locally construct an instance of our struct here on the stack. The bool member uninitializedBool is uninitialized.
    FStruct structInstance;

    // Output "true" or "false" to stdout
    Serialize(structInstance.uninitializedBool);
    return 0;
}


Да, классный пример, спасибо, не видел его. Лично я считаю требование инициализировать переменные (то есть, запрет использовать неинициализированные) абсолютно логичным. И вот реальный пример, как это помогает в оптимизации кода. Си так не смог бы :)

Ой, главное, написал же какой-то пример с неинициализированной переменной, потом думаю: "Вдруг там не воспроизведётся, лучше скопипасчу" :) Вот и докопипастился не посмотрев, извините. :) Только то ли я туплю, то ли это корректный сишный код тоже?

В общем-то, эти все условия понятные, для совсем тяжелых случаев, больше disclaimer, чем особенность языка. В С++ много случаев undefined behavior разрешены для оптимизации
Например, как я помню, переполнение signed int — undefined behavior и в C, и в C++, одинаково используется компиляторами для оптимизации.
if (counter++ == INT_MAX) { ... }
Вот простой примерчик, выражение может быть оптимизировано C компилятором в:
if (0) { ... }
и в итоге в ничто.
Sign up to leave a comment.

Articles