Не исключено. В своё время пофиксил пару багов в qucs, который увы уже не очень развивается. Но пока мои проекты для FPGA достаточно просты, чтоб уходить в сторону более сложных абстракций. Пару тысяч строк на верилоге можно и руками набросать без синтаксического сахара.
Почему при разработке сложной цифровой аппаратуры Вам все еще нужен уровен абстрации в виде проводов и D-триггеров ?
Ну вот так получается :) Сами же упоминали важность изучения вывода низкоуровневых утилит. Бывает что нужно разбираться куда пропадают сигналы, которые в исходниках есть, а из netlist'a пропадают, или почему появилась метастабильность.
Может быть пора оторваться и перейти на уровень повыше ?
Я бы рад, но увы пока даже перейти на уровень Verilog'a не всегда выходит. Возможно это потому что у меня недостаточно опыта.
Вангую, с цифровым синтезом будет всё то же самое.
Хорошо если так, но проект пока ИМХО слишком молод и ментейнеров/контрибьюторов не так много.
Конечно, весьма привлекательно использовать SpinalHDL, но это дополнительный слой абстракции. Недостаточно будет знать этот HDL, всё равно потребуется разбираться в языке, в который он транслируется. И любой баг в трансляторе может стоить много часов отладки. Как правильно написано в статье, иногда требуется погружаться на несколько уровней ниже Verilog'a/VHDL'a чтоб понять какие чудеса натворил оптимизатор.
PS: посылаю лучи ненависти Libero SoC от MicroSemi, даже 20 лет назад тулчейн от Altera был лучше чем это современное поделие (v2024.1).
PPS: собирал icestorm из исходников под WSL чтоб залить битстрим на плату с iCE40 - заняло считаные секунды.
Я написал несколько килобайт кода для 8008 ;) Сложно назвать его легендарным, конечно, но ISA весьма простая, хоть и регистров не хватает совсем и приходится дергать память постоянно. Хорошо если память быстрая, и за такт отдаст данные, но 8008 поддерживает асинхронную работу (есть пин READY, который дергается когда память готова отдать данные на шину).
Для тех кто хочет более универсального решения (не только для MSX), могут глянуть на HxC эмуляторы. Есть варианты с SD картой или с read-only образами, загружаемыми через USB в эмулятор.
Советую почитать релевантные доки - MCS-4_Assembly_Language_Programming_Manual_Dec73 / MCS-4_UsersManual_Feb73 / MCS4_Data_Sheet_Nov71. Или даже просто datasheet на процессор.
Я не знаю, какая ISA взята за основу, но это точно не i4004. Регистра B в i4004 не существует (в i8008 - есть), а регистры просто индексные - rr0..rr15. Опкоды левые. Некоторых инструкций даже в теории нет в i4004 (HLT появился только в i4040).
Запись в память куда сложнее, чем просто одна инструкция. Да и память не линейна, о организована в виде банков и регистров памяти.
Если что, у писал 2 эмулятора (i4004 и i4040), которые совместимы с железом с точностью до тактов.
Интересно. Я совсем не шарю в схемотехнике, но чтоб такого избежать, просто стараюсь следовать двум правилам: 1) держать дорожки подальше друг от друга, даже если возможности технологии изготовления ПП позволяют расстояние в 0.2мм и 2) вешать развязывающие кондеры рядом с пинами питания на всех IC.
Есть у меня в планах взять что-нибудь из MCS-48, так что посмотрим не постигнет ли меня фейл)
Как бы там ни было, true/false лежат в памяти всегда, вне зависимости от того, будут они использованы в коде или нет, их наличие не надо проверять, их не требуется записывать, они не обрабатываются GC.
Очевидно, что 1/0 даже и не нужно хранить в памяти. Они используются как immediate значения в коде. Компилятор не будет записывать их куда-либо отдельно в ячейку памяти, а просто будет использовать в качестве операндов инструкций.
В любом случае, такие микро-оптимизации нужно проводить ну очень редко. И в целом я соглашусь, что заменять семантически более подходящие true/false на 1/0 ради выигрыша сотых долей процента (и то в лучшем случае) - не стоит.
Аналогии очень редко применимы, и сравнивать движок JS с машиной не совсем корректно.
Например, некоторые разработчики (особенно пришедшие из Backend или под их вилянием) полагают, что использовать 1|0 вместо true|false - оптимальнее. Хотя, как мы видим, в JS это не совсем так, хоть разница в производительности и не велика.
Почему же не так? Использование 1/0 в качестве значений для полей объекта быстрее чем true/false просто потому что они хранятся напрямую в словаре свойств объекта, а не как ссылки на базовые true/false объекты. Да, у нас будет некий оверхед на деоптимизационную ловушку для SMI, но в целом 1/0 будет выигрывать у true/false.
Да и в общем, на уровне ассемблера, работать с числами 1/0 компилятор умеет эффективнее чем с указателями и может использовать больше оптимизаций. Так что в большинстве сценариев 1/0 будет быстрее чем true/false.
Занятно, что именно в этом кейсе знание о том, что true-false - ссылочные значения, а не просто числа в памяти, может подсказать ответ. Но странно, что вы сделали противоположный вывод об оптимизации :)
Вопрос риторический
Не совсем. В изначальном комментарии хотел отметить то, что набор практических советов был бы полезнее, чем просто описание небольшого фрагмента движка v8. Если не знать еще множества нюансов (как в примере выше), то использовать информацию о том, как хранятся примитивные типы весьма сложно.
Конечно, всё это очень интересно, но в чём практический выхлоп? Я не говорю про то, что писать быстрый код на JS не следует. А скорее про то, как конкретно именно эта информация может помочь писать быстрый код? Скажем, знание о формах объектов (object shapes) или нюансах GC, можно использовать в реальном коде.
Единственное что приходит в голову, это то, что лучше использовать гомогенные массивы со Smi, чтобы они имели оптимальный тип PACKED_*_SMI.
Моё предположение, что ограничения по частоте шли не столько от самого процессора, как от переферии. У меня был резервный план - попробовать разогнать i4040, если бы не получилось решить задачу только программно. Однако отмечу, что эмулятор памяти на stm32f4, написанный на C (O3, gcc), уже с трудом справлялся с 740кГц. Скорее всего, я сумел бы написать более эффективный код эмулятора, который поддерживает более высокую частоту, но до этого дело не дошло.
Математика нужна, чтобы просто знать о существовании ряда алгоритмов / формул. Не обязательно даже понимать как они работают. Скажем, попалась тебе задача, и ты уже можешь прикинуть как её решать наиболее оптимально. Для многих прикладных задач существуют лучшие практики их решений, но нужно уметь увидеть то, что конкретная проблема в абстрактной форме ложится на известный алгоритм.
PS: само собой, всё это не нужно чтобы перегонять JSON'ы из одного формата в другой, паралельно реализуя CRUD. Но, к примеру, при разработке распределенных систем "матан" уже встречается не так уж и редко.
Результат не поменяется - операции с памятью синхронные. Вот 8008 уже имеет READY пин для ожидания когда медленная память сможет выполнить операцию в/в. Но 4004/4040 читают шину данных в следующий такт после передачи адреса. У меня, кстати, есть плата для 4040 с достаточным количеством памяти, но мне было интересно ещё и поработать над железной частью.
Многие вещи упрощены. Как уже писали выше про инструкцию на такт. Или к примеру про локальные переменные на стеке, про то что стек растет вниз, про упрощенные float'ы, и т. д.
Но для новичка я думаю нюансы и не нужны, и как обзорная статья вполне норм должна зайти.
Не исключено. В своё время пофиксил пару багов в qucs, который увы уже не очень развивается. Но пока мои проекты для FPGA достаточно просты, чтоб уходить в сторону более сложных абстракций. Пару тысяч строк на верилоге можно и руками набросать без синтаксического сахара.
Ну вот так получается :) Сами же упоминали важность изучения вывода низкоуровневых утилит. Бывает что нужно разбираться куда пропадают сигналы, которые в исходниках есть, а из netlist'a пропадают, или почему появилась метастабильность.
Я бы рад, но увы пока даже перейти на уровень Verilog'a не всегда выходит. Возможно это потому что у меня недостаточно опыта.
Хорошо если так, но проект пока ИМХО слишком молод и ментейнеров/контрибьюторов не так много.
Конечно, весьма привлекательно использовать SpinalHDL, но это дополнительный слой абстракции. Недостаточно будет знать этот HDL, всё равно потребуется разбираться в языке, в который он транслируется. И любой баг в трансляторе может стоить много часов отладки. Как правильно написано в статье, иногда требуется погружаться на несколько уровней ниже Verilog'a/VHDL'a чтоб понять какие чудеса натворил оптимизатор.
PS: посылаю лучи ненависти Libero SoC от MicroSemi, даже 20 лет назад тулчейн от Altera был лучше чем это современное поделие (v2024.1).
PPS: собирал icestorm из исходников под WSL чтоб залить битстрим на плату с iCE40 - заняло считаные секунды.
Ну они только недавно добавили дисплей в руль. Все остальные команды давно уже пришли к цифровому табло вместо кучи индикаторов.
Ну вроде как 8008 ;) Написал на JS небольшой эмулятор/отладчик/редактор кода.
Я написал несколько килобайт кода для 8008 ;) Сложно назвать его легендарным, конечно, но ISA весьма простая, хоть и регистров не хватает совсем и приходится дергать память постоянно. Хорошо если память быстрая, и за такт отдаст данные, но 8008 поддерживает асинхронную работу (есть пин READY, который дергается когда память готова отдать данные на шину).
Есть сборки под HcX, к примеру здесь несколько вариантов -https://lotharek.pl/productdetail.php?id=350 (у меня один из таких адаптеров, работает норм).
Если говорить за open source, то https://github.com/SukkoPera/OpenFlops получше gotek'a. Компактная версия, которая укладывается в дисконтный 100x100 размер платы - https://www.pcbway.com/project/shareproject/Floppy_Disk_Drive_emulator_OpenFlops_smaller_version_4f72f1eb.html
Для тех кто хочет более универсального решения (не только для MSX), могут глянуть на HxC эмуляторы. Есть варианты с SD картой или с read-only образами, загружаемыми через USB в эмулятор.
Нет, неверные.
Советую почитать релевантные доки - MCS-4_Assembly_Language_Programming_Manual_Dec73 / MCS-4_UsersManual_Feb73 / MCS4_Data_Sheet_Nov71. Или даже просто datasheet на процессор.
Я не знаю, какая ISA взята за основу, но это точно не i4004. Регистра B в i4004 не существует (в i8008 - есть), а регистры просто индексные - rr0..rr15. Опкоды левые. Некоторых инструкций даже в теории нет в i4004 (HLT появился только в i4040).
Запись в память куда сложнее, чем просто одна инструкция. Да и память не линейна, о организована в виде банков и регистров памяти.
Если что, у писал 2 эмулятора (i4004 и i4040), которые совместимы с железом с точностью до тактов.
Интересно. Я совсем не шарю в схемотехнике, но чтоб такого избежать, просто стараюсь следовать двум правилам: 1) держать дорожки подальше друг от друга, даже если возможности технологии изготовления ПП позволяют расстояние в 0.2мм и 2) вешать развязывающие кондеры рядом с пинами питания на всех IC.
Есть у меня в планах взять что-нибудь из MCS-48, так что посмотрим не постигнет ли меня фейл)
Очевидно, что 1/0 даже и не нужно хранить в памяти. Они используются как immediate значения в коде. Компилятор не будет записывать их куда-либо отдельно в ячейку памяти, а просто будет использовать в качестве операндов инструкций.
В любом случае, такие микро-оптимизации нужно проводить ну очень редко. И в целом я соглашусь, что заменять семантически более подходящие true/false на 1/0 ради выигрыша сотых долей процента (и то в лучшем случае) - не стоит.
Работа с числами с плавающей точкой транслируется в обычные AVX инструкции на современном x86.
Аналогии очень редко применимы, и сравнивать движок JS с машиной не совсем корректно.
Почему же не так? Использование 1/0 в качестве значений для полей объекта быстрее чем true/false просто потому что они хранятся напрямую в словаре свойств объекта, а не как ссылки на базовые true/false объекты. Да, у нас будет некий оверхед на деоптимизационную ловушку для SMI, но в целом 1/0 будет выигрывать у true/false.
Да и в общем, на уровне ассемблера, работать с числами 1/0 компилятор умеет эффективнее чем с указателями и может использовать больше оптимизаций. Так что в большинстве сценариев 1/0 будет быстрее чем true/false.
Занятно, что именно в этом кейсе знание о том, что true-false - ссылочные значения, а не просто числа в памяти, может подсказать ответ. Но странно, что вы сделали противоположный вывод об оптимизации :)
Не совсем. В изначальном комментарии хотел отметить то, что набор практических советов был бы полезнее, чем просто описание небольшого фрагмента движка v8. Если не знать еще множества нюансов (как в примере выше), то использовать информацию о том, как хранятся примитивные типы весьма сложно.
Конечно, всё это очень интересно, но в чём практический выхлоп? Я не говорю про то, что писать быстрый код на JS не следует. А скорее про то, как конкретно именно эта информация может помочь писать быстрый код? Скажем, знание о формах объектов (object shapes) или нюансах GC, можно использовать в реальном коде.
Единственное что приходит в голову, это то, что лучше использовать гомогенные массивы со Smi, чтобы они имели оптимальный тип
PACKED_*_SMI
.Моё предположение, что ограничения по частоте шли не столько от самого процессора, как от переферии. У меня был резервный план - попробовать разогнать i4040, если бы не получилось решить задачу только программно. Однако отмечу, что эмулятор памяти на stm32f4, написанный на C (O3, gcc), уже с трудом справлялся с 740кГц. Скорее всего, я сумел бы написать более эффективный код эмулятора, который поддерживает более высокую частоту, но до этого дело не дошло.
Математика нужна, чтобы просто знать о существовании ряда алгоритмов / формул. Не обязательно даже понимать как они работают. Скажем, попалась тебе задача, и ты уже можешь прикинуть как её решать наиболее оптимально. Для многих прикладных задач существуют лучшие практики их решений, но нужно уметь увидеть то, что конкретная проблема в абстрактной форме ложится на известный алгоритм.
PS: само собой, всё это не нужно чтобы перегонять JSON'ы из одного формата в другой, паралельно реализуя CRUD. Но, к примеру, при разработке распределенных систем "матан" уже встречается не так уж и редко.
Вот небольшой пример с оциллографа - SYNC / CM_ROM сигналы генерировались i4004, ph1/ph2 - современным stm32 (ну как современным, 10+ лет уже ему).
Результат не поменяется - операции с памятью синхронные. Вот 8008 уже имеет READY пин для ожидания когда медленная память сможет выполнить операцию в/в. Но 4004/4040 читают шину данных в следующий такт после передачи адреса. У меня, кстати, есть плата для 4040 с достаточным количеством памяти, но мне было интересно ещё и поработать над железной частью.
Многие вещи упрощены. Как уже писали выше про инструкцию на такт. Или к примеру про локальные переменные на стеке, про то что стек растет вниз, про упрощенные float'ы, и т. д.
Но для новичка я думаю нюансы и не нужны, и как обзорная статья вполне норм должна зайти.