С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Я видел эти 5 тактов по результатам Ваших исследований ранее, поэтому этот момент на модели тщательно проверял и обдумывал где там может лишний такт набежать. В самой схеме таймера - никак, это изолированный тактовый домен CLC/4, может где-то снаружи в схеме сопряжения с шиной, но ей все равно, другие значения тоже на такт "дрожали" бы. В итоге я надеюсь мы Ваш тест прогоним полностью на получившейся реплике и увидим, будет расхождение с реальным ВМ1 или нет.
Update: кстати работу счетчика легко проверить и без программы на реальном ВМ1. Запускаем ВМ1, он запускает таймер, забираем у ВМ1 шину через DMR, запускаем цикл чтения из регистра таймера внешним агентом, цикл не заканчиваем и на nAD0 осциллографом наблюдаем поведение младшего разряда счетчика таймера. Будет у меня рабочий стенд ВМ1 + FPGA - проверю.
Последний раз редактировалось Vslav; 20.12.2014 в 16:04.
Матрица приоритетного шифратора прерываний основное время отключена от питания, все линии разряжены. При исполнении команды, в фазе проверки наличия запроса на прерывание от основной ПЛМ формируется строб, по этому стробу матрица шифратора "просыпается", фиксирует входные запросы, прогоняет их через себя, фиксирует результаты в выходном латче, возвращает ответный строб готовности и снова отключается. "Зеленые" технологии. Основная ПЛМ тоже с каким-то хитрым отключением о питания, пока не разобрался.
Входные запросы прерываний ACLO, IRQ1, IRQ2, IRQ3, VIRQ фиксируются на входе шифратора с использованием не нормального триггера, а динамической логики, через емкость затвора транзистора. Фиксация происходит по ниспадающему фронту CLC, поэтому, если "не повезет" и в этот момент будет изменятся уровень входных линий, то транзистор может оказаться в промежуточном состоянии, получим пороговые и переходные процессы на шифраторе и непредсказуемый результат на выходе. В связи с этим рекомендуется все внешние входы IRQ1-3, VIRQ синхронизировать на внешней микросхеме по фронту CLC. В БК все засинхронизировано, на MC1201.01 - не все, по IRQ1 (HALT), IRQ3 и ACLO могут быть проблемы. События редкие, вероятность очень невысокая, но тем не менее.
Update: ответный строб формируется сразу оказывается. Картинка со схемой:
RESET - сброс процессорного модуля
REQ - запрос на работу шифратора
ACK - ответный строб
ENA - высокий - постоянная трансляция во входном латче запросов на прерывание, матрица выключена, низкий - латч фиксирует входы, матрица частично разрешается
STB - высокий - матрица полностью разрешена, выходной латч разрешен, низкий - латч фиксирует выходы
Последний раз редактировалось Vslav; 21.12.2014 в 10:33.
Разобрал генератор векторов прерываний, долго искал что такое 270 вектор, оказывается в книжке "МикроЭВМ, Том 2" опечатка, и IRQ3 прерывается по 270 вектору (а написано 274). Ниже фрагмент всех векторов, которые вообще есть у процессора в таблице и по которым он может "ходить".
Дальше буду разбирать генератор констант.
Прерывание по нарастающему фронту nACLO никак не влияет на обработку. Если два отдельных детектора ниспадающего среза (и он используется) и нарастающего фронта. Влияние запроса от детектора фронт возможно только в краткий момент в первом цикле после сброса, тогда поведение непредсказуемо (вероятно зависание шифратора).Код:always begin case(vsel) 4'b0000: vmux = 16'o160006; // double error 4'b0001: vmux = 16'o000020; // IOT instruction 4'b0010: vmux = 16'o000010; // reserved opcode 4'b0011: vmux = 16'o000014; // T-bit trap 4'b0100: vmux = 16'o000004; // invalid opcode 4'b0101: // case (pa[1:0]) // initial start 2'b00: vmux = 16'o177716; // register base 2'b01: vmux = 16'o177736; // depends on 2'b10: vmux = 16'o177756; // processor number 2'b10: vmux = 16'o177776; // endcase // 4'b0110: vmux = 16'o000030; // EMT instruction 4'b0111: vmux = 16'o160012; // int ack timeout 4'b1000: vmux = 16'o000270; // IRQ3 falling edge 4'b1001: vmux = 16'o000024; // ACLO falling edge 4'b1010: vmux = 16'o000100; // IRQ2 falling edge 4'b1011: vmux = 16'o160002; // IRQ1 low level/HALT 4'b1100: vmux = 16'o000034; // TRAP instruction 4'b1101: vmux = vreg; // vector register 4'b1110: vmux = svec; // start @177704* 4'b1111: vmux = 16'o000000; // unused vector default: vmux = 16'o000000; // endcase end
Последний раз редактировалось Vslav; 22.12.2014 в 02:19.
Тогда отметить цепь к которой он подключен, ПКМ->Properties->Net и там ввести нужное имя. Но порт отображает имя всей цеи, если подключите к ней еще порты - то будет то же самое имя. Более того, все фрагменты цепей с одинаковым именем считаются электрически единой цепью.
Если такая функциональность не нужна, то лучше нарисовать компонент с прямоугольником и одним пином без имени и менять у всего компонента аттрибут Value, я так на схемах с ВП1/ВМ1 делаю для внешних пинов, потому что цепи с такими именами могут быть внутри схемы, обзывать коротенький фрагмент от пина до буфера осмысленным полезным именем жалко.
Порт имеет только аттрибут Net Name и все.
Для Ваших целей можно
- использовать только имя порта/цепи
- поставить компонент и использовать его аттрибут value
- просто написать дополнительный текст (не будет привязан, отдельный объект)
Я для обозначения пина ставил компонент вместо порта и использовал Value. На схемах ВП1 этот компонент заменял всю ячейку ввода-вывода, на ВМ1/ВМ80 представлял только пин.
Красиво разложился приоритетный шифратор прерываний, это вот там маленькая матричка в правом нижнем углу на нашей фотографии кристалла.
На его работу существенно влияет бит 2 регистра режима (177700), я этот бит назвал ncpu, вот так работает шифратор штатно, при ncpu=0:
Строчки я расписал от наивысшего приоритета к низшему:Код://______________________________________________________________________________ // // ncpu = 0, simplified matrix to demostrate priority encoding // // iato & qbto; // & ~iato & qbto & dble; // psw[11] & ~iato & qbto & ~dble ; // psw[10] & ~iato & qbto & ~dble; // ~psw[11] & ~psw[10] & ~iato & qbto & ~dble; // // ~qbto & uerr; // ~psw[10] & psw[4] & ~qbto & ~uerr; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & aclo; // ~psw[11] & ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & irq[1]; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & ~psw[7] & ~irq[1] & irq[2]; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & ~psw[7] & ~irq[1] & ~irq[2] & irq[3]; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & ~psw[7] & ~irq[1] & ~irq[2] & ~irq[3] & ~virq; //
- тайм-аут по извлечению вектора прерывания (немаскируемое)
- двойное зависание (немаскируемое)
- зависание шины, (psw[11] и psw[10] как-то управляют реакцией на прерывание)
- недопустимый код инструкции (немаскируемое)
- T-бит (psw[4]) (маскируется psw[10])
- понижение питания nACLO (маскируется psw[10])
- irq[1] (маскируется psw[10] или psw[11])
- irq[2] (маскируется psw[10] или psw[7])
- irq[3] (маскируется psw[10] или psw[7])
- virq (маскируется psw[10] или psw[7]) (низкий уровень активный)
С детектором фронта ACLO тоже понятно, это перезапуск процессора после снятия DCLO. То есть ACLO должен сниматься строго после DCLO, иначе никакого старта не будет.
А вот при ncpu = 1 модифицируется поведение T-бита, он перестает работать как бит ловушки, вместо этого он как-то начинает влиять на внешние прерывания, пока ясности нет. (Позже выяснилось что это бит режима wait)
Вот полная матрица, может у кого мысли будут:
Такое в Сети нашел:Код://______________________________________________________________________________ // // Interrupt matrix rewritten (for clarity and readability) // module vm1_pli ( input [19:0] rq, output [10:0] sp ); wire [20:0] p; wire [10:0] pl; wire [3:1] irq; wire [11:0] psw; wire virq; wire plir, uerr; wire ncpu, dble; wire acok, aclo; // ACLO detector requests wire iato, qbto; // qbus timeouts and odd address assign psw[10] = rq[0]; assign plir = rq[1]; assign psw[11] = rq[2]; assign uerr = rq[3]; assign psw[7] = rq[4]; assign virq = rq[8]; // low active level assign qbto = rq[9]; assign dble = rq[10]; assign aclo = rq[11]; assign ncpu = rq[12]; // low active level assign acok = rq[13]; assign irq[1] = rq[14]; assign psw[4] = rq[15]; assign irq[2] = rq[16]; assign iato = rq[17]; assign irq[3] = rq[18]; function cmp ( input [19:0] i, input [19:0] c, input [19:0] m ); cmp = &(~(i ^ c) | m); endfunction //______________________________________________________________________________ // // ncpu = 0, simplified matrix to demostrate priority encoding // // iato & qbto; // & ~iato & qbto & dble; // psw[11] & ~iato & qbto & ~dble ; // & psw[10] & ~iato & qbto & ~dble; // ~psw[11] & ~psw[10] & ~iato & qbto & ~dble; // // ~qbto & uerr; // ~psw[10] & psw[4] & ~qbto & ~uerr; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & aclo; // ~psw[11] & ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & irq[1]; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & ~psw[7] & ~irq[1] & irq[2]; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & ~psw[7] & ~irq[1] & ~irq[2] & irq[3]; // ~psw[10] & ~psw[4] & ~qbto & ~uerr & ~aclo & ~psw[7] & ~irq[1] & ~irq[2] & ~irq[3] & ~virq; // assign p[0] = plir & ~qbto & ~aclo & ~uerr & ncpu & ~irq[1] & ~irq[2] & ~irq[3] & virq; assign p[10] = plir & ~psw[10] & ~qbto & ~aclo & ~uerr & ncpu & ~irq[1]; assign p[3] = plir & ~psw[11] & ~psw[10] & psw[4] & ~qbto & ~aclo & ~uerr & ncpu & irq[1]; assign p[2] = plir & ~psw[11] & ~psw[10] & ~psw[4] & ~qbto & ~aclo & ~uerr & irq[1]; assign p[1] = plir & ~psw[10] & ~qbto & ~aclo & ~uerr & ncpu & ~psw[7] & ~irq[1] & irq[2]; assign p[7] = plir & ~psw[10] & ~psw[4] & ~qbto & ~aclo & ~uerr & ~psw[7] & ~irq[1] & irq[2]; assign p[6] = plir & ~psw[10] & psw[4] & ~qbto & ~aclo & ~uerr & ncpu & ~psw[7] & ~irq[1] & ~irq[2] & irq[3]; assign p[9] = plir & ~psw[10] & ~psw[4] & ~qbto & ~aclo & ~uerr & ~psw[7] & ~irq[1] & ~irq[2] & irq[3]; assign p[4] = plir & ~psw[10] & psw[4] & ~qbto & ~aclo & ~uerr & ncpu & ~psw[7] & ~irq[1] & ~irq[2] & ~irq[3] & ~virq; assign p[5] = plir & ~psw[10] & ~psw[4] & ~qbto & ~aclo & ~uerr & ~psw[7] & ~irq[1] & ~irq[2] & ~irq[3] & ~virq; assign p[11] = plir & ~psw[10] & ~psw[4] & ~qbto & aclo & ~uerr; assign p[12] = plir & ~psw[10] & psw[4] & ~qbto & ~uerr & ~ncpu ; assign p[13] = plir & ~psw[10] & psw[4] & ~qbto & aclo & ~uerr & ncpu ; assign p[20] = plir & ~psw[11] & ~psw[10] & ~iato & qbto & ~dble; assign p[14] = plir & psw[11] & ~iato & qbto & ~dble ; assign p[18] = plir & psw[10] & ~iato & qbto & ~dble; assign p[19] = plir & ~iato & qbto & dble; assign p[16] = plir & iato & qbto; assign p[15] = plir & uerr & ~qbto; assign p[8] = ~plir & ~acok; assign p[17] = ~plir & acok; assign sp = ~pl; assign pl[0] = p[20] | p[19] | p[15] | p[9] | p[7] | p[6] | p[1]; // 20, 19, 17, 16, 15, 13, assign pl[1] = p[20] | p[19] | p[17] | p[13] | p[11] | p[9] | p[6]; // 12, 11, 9, 7, 6, 5, 4, 1 assign pl[2] = p[20] | p[17] | p[16] | p[5] | p[4]; assign pl[3] = p[20] | p[19] | p[17] | p[16] | p[15] | p[12]; assign pl[4] = p[8]; assign pl[5] = p[20] | p[17] | p[15] | p[13] | p[12] | p[11] | p[9] | p[7] | p[6] | p[5] | p[4] | p[1]; assign pl[6] = p[20] | p[19] | p[18] | p[16] | p[15] | p[14] | p[12] | p[10] | p[9] | p[7] | p[5]; assign pl[7] = p[19] | p[18] | p[17] | p[16] | p[14] | p[3] | p[2]; assign pl[8] = p[20] | p[19] | p[18] | p[17] | p[16] | p[15] | p[14] | p[13] | p[11] | p[9] | p[6]; assign pl[9] = p[14] | p[13] | p[12] | p[11] | p[10] | p[9] | p[8] | p[7] | p[5] | p[3] | p[2] | p[0]; assign pl[10] = p[20] | p[19] | p[18] | p[17] | p[16] | p[15] | p[14] | p[13] | p[12] | p[11] | p[5] | p[4]; endmodule
Добавлю от себя что в битах 4 и 3 читается номер процессора (00 для главного, 01/10/11 для ведомого). Да, этот ncpu очень даже на wait похож. Может устанавливаться по сигналу из ядра, надо будет проследить его связь с исполнением инструкции wait. Значит бит T после wait не генерирует исключение, прерывания, если они были замаскированы T-битом, в состоянии wait разрешаются, все логично.177700
Чтение всегда 177740
Запись
биты 0,1 - "1" в любой разряд - останов процессора
бит 2 - запись "1" приостанавливает процессор в ожидании любого прерывания (аналогично команде wait)
Последний раз редактировалось Vslav; 23.12.2014 в 01:04.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)