Тут, в ветке обсуждения 8-ми битных ядер, я упомянул о баге в LatticeMico8 и получил предложение рассказать о нем (баге) подробнее. Дальше речь только о Verilog реализации, как там в VHDL - не знаю. Сразу скажу, что если не использовать прерывания, то ядро работает прекрасно. Система команд полноценная, два такта на команду, в плотно забитом (90%) FPGA работает на 50 МГц. Теперь о грустном, в чем проявляется проблема. Если сигнал прерывания приходит во время выполнения "простой" команды, т.е. без передачи управления (не меняется PC), то все нормально: сохранение адрес возврата в стеке, переход по вектору и возврат. Но если мы попадаем на команду перехода, то происходит следующее. В первом такте сохраняется адреса возврата в стеке, а во втором внутренний автомат принимает решение - раз сейчас переход, то прерывание не выполняем. Похоже, по начальной мысли автора, должна была быть только задержка прерывания на время команды перехода, но из-за ошибки в реализации происходит наращивание стека без его освобождения. В свое время я попытался поправить это, но с наскоку не получилось, в одном месте поправил, в другом сломал. Там в коде не злоупотребляют комментариями, хорошо хоть обфускатор не использовали, а потом и времени не было. Вот исходный текст примера программы, которая была использована при описании бага для техподдержки Lattice:
# interrupt vector ........b..........int_handler # start ........movi.....r0,5 ........seti main_loop: ........subi.....r0,1 ........bnz......main_loop ........clri stop: ........b..........stop # end int_handler: ........iret
На входе прерываний постоянный запрос. Успевает пройти нормальное прерывание между командами "seti" (разрешение прерываний) и "subi" (декремент). Затем, пока крутится цикл, прерывания не проходят вообще, но наращивается стек, а в конце "clri" запрещает прерывания. К багрепорту прилагался проект в Modelsim, и даже скриншот происходящего. Ошибка была признана, но не исправлена до сих пор.
|