Чт янв 12, 2017 07:08:47
Чт янв 12, 2017 20:16:25
Чт янв 12, 2017 20:34:15
Чт янв 12, 2017 20:41:12
*_Подходящий эпитет.DX168B писал(а):.. "размышления на унитазе"* ..
.. И инструкция имеет шансы выполниться за такт**. Данный подход ...
Чт янв 12, 2017 20:59:26
+----------=> $L:Lock-mask
| +----------=> $K:Keep code
| | +---------=> $Z:PREFIX #Z
| | | +-------=> $J:
| | | | +-----=> $Y:
| | | | | +---=> $I:
| | | | | | +-=> $X:
| | | | | | |
/|\/|\/|\|/|\|/|\
LLLKKKZZZJYYYIXXX_
XXX00000000000C HLT :IS_BOOT ? IS_WAIT ? CR(0, ACC( ) ) : FH(8 ) : (CR(CR(0 ) & 0xF0 ) , FH(0xB ) , FL(0x5 ) ) // Halting
XXX00011111110C NOP :$IB==$IB // No operation
0000000XXX0XXX_ PREFIX R#X/P#X :0 // Prefix for R#X!/P#X!
X1000011101XXXE PUSH+ U#X :HEAP(U#X( ) ) // Push pointer into stack
X1000011111XXXE POP+ U#X :U#X(HEAP( ) ) // Pop pointer from stack
XXXXXX11111110C NOP #Z :#Z // Hollow operation through #Z ticks
XXX10010101XXXA ALU#X IB :$1=ALU#X(DROP(FH( ) ) ,$IB ) ,ACC($1 ) ,FL($1.hi( ) ) // ALU#X! with retained and immediate
XXXXXX10101XXXA ALU#X Z#Z,IB :$1=ALU#X(Z#Z( ) ,$IB ) ,Z#Z($1 ) ,FL($1.hi( ) ) // ALU#X! with Z#Z! and byte
XXX1000XXX1XXXA ALU#X Z#Y :$1=ALU#X(DROP(#Y ) ,REG(#Y ) ) ,REG(#Y,$1 ) ,FL($1.hi( ) ) // ALU#X! with Z#Y! and retained
XXXXXX0XXX1XXXA ALU#X Z#Z,R#Y :$1=ALU#X(Z#Z( ) ,R#Y( ) ) ,Z#Z($1 ) ,FL($1.hi( ) ) // ALU#X! with Z#Z! and R#Y!
000XXX0XXX0XXXC HLT #Z :IS_BOOT && IS_WAIT ? FH( ) ==(#Z+8 ) ? ACC(PORT(ACC( ) ) ) : FH( ) >=8 ? PORT(R#Z( ) ,ACC( ) ) : CR(#Z,ACC( ) ) : FH(#Z+8 ) // Hold #Z index number
X1000011001XXXD INC+ Q#X :Q#X(Q#X( ) +1 ) // Increment Q#X!
X1000011011XXXD DEC+ Q#X :Q#X(Q#X( ) -1 ) // Decrement Q#X!
XXX00011001111A CMC :FL(FL( ) ^ 2 ) // Complement carry flag
XXXXXX11001110D ADC BX,T#Z :$1=BX( ) +T#Z( ) +(_CF?1:0 ) ,$2=($1>>15 ) &2,FL((FL( ) & 0xD ) |$2 ) , BX($1 ) // Addition register pair with carry
X10XXX11001XXXD ADD Q#X,T#Z :$1=Q#X( ) +T#Z( ) +(_CF?0:0 ) ,$2=($1>>15 ) &2,FL((FL( ) & 0xD ) |$2 ) , Q#X($1 ) // Addition register pair
XXXXXX11011110D SBB BX,T#Z :$1=BX( ) -T#Z( ) -(_CF?1:0 ) ,$2=($1>>15 ) &2,FL((FL( ) & 0xD ) |$2 ) , BX($1 ) // Subtraction register pair with borrow
X10XXX11011XXXD SUB Q#X,T#Z :$1=Q#X( ) -T#Z( ) -(_CF?0:0 ) ,$2=($1>>15 ) &2,FL((FL( ) & 0xD ) |$2 ) , Q#X($1 ) // Subtraction register pair
XXX00011001010A XCHG :$1=ACC( ) ; for($2=0,$0=0;$0<8;++$0,$1>>=1 ) $2=($2<<1 ) +($1&1 ) ; ACC($2 ) >0 // Exchange retained bits by mirror
XXXXXX11001010A XCHG P#Z :$1=DST( ) ,DST(P#Z( ) ) ,P#Z($1 ) // Exchange P#Z! with retained pair
XXXXXX11001111A XCHG R#Z :$1=ACC( ) ,ACC(R#Z( ) ) ,R#Z($1 ) // Exchange R#Z! with retained register
XXX100110X1XXXA ALU#W :$1=ACC(ALU#W(ACC( ) ) ) ,FL($1.hi( ) ) // ALU#W! with retained
XXXXXX110X1XXXA ALU#W Z#Z :$1=Z#Z(ALU#W(Z#Z( ) ) ) ,FL($1.hi( ) ) // ALU#W! with Z#Z!
X111000XXX0000A MUL R#Y :0 //
X1110000000XXXF XCHG R#X :$1=ACC( ) ,ACC(R#X( ) ) ,R#X($1 ) // Exchange R#Z! with retained register
X111000XXX0100F XCHG P#Y :$1=DST( ) ,DST(P#Y( ) ) ,P#Y($1 ) // Exchange P#Z! with retained pair
X111000XXX0XXXF MOV P#X,T#Y :P#X(T#Y( ) ) // Move T#Y! vector to P#X!
01110000000XXXD_PUSH+ T#X+[T#Y] :HEAP(T#X( ) +DW(T#Y( ) ) ) // Correct effective address in stack
0111000XXX0XXXD_PUSH+ T#X+T#Y :HEAP(T#X( ) +T#Y( ) ) // Push effective address into stack
1111000XXX0000D_PUSH+ [T#X]-T#Y :HEAP(HEAP( ) -T#Y( ) ) // Correct effective address in stack
1111000XXX0XXXD_PUSH+ T#X-T#Y :HEAP(T#X( ) -T#Y( ) ) // Push effective address into stack
XXXXXX00000000C HLT R#Z :IS_WAIT ? FH( ) == #Z ? ACC(CTX(ACC( ) ) ) : $IR ? CTX(ACC( ) ,R#Z( ) ) : R#Z(CR(FH( ) ) ) : FH(#Z ) // Hold R#Z!/P#Z! as retained
XXX0000XXX0XXXF MOV R#X,R#Y :IS_WAIT && true ? #Y == 0 ? ($1=PORT(R#X( ) ) ,trace.eady?R#X($1 ) :0 ) : PORT(R#X( ) ,R#Y( ) ) : R#X(R#Y( ) ) // Move R#Y! data into R#X!
X11XXX0XXX0XXXD_ALU#Z P#X,T#Y :0 //
XXX00010110000B JCND#X $+IB :CND#X?IP(IP( ) +$IV ) :0 // Relative branching if CND#X!
XXX00010100XXXF MOV R#X,IB :R#X($IB ) // Move immediate data into R#X!
XXX00010110001E BIAS $+IB :HEAP($IP+$IV ) // Push instruction based relative address
XXX00010110XXXB CCND#X $+IB :CND#X?HEAP(IP( ) ) +IP(IP( ) +$IV ) :0 // Relative call if CND#X!
XXX00011000XXXA INC+ R#X :$1=ADD(R#X( ) ,1 ) ,R#X($1 ) ,FL($1.hi( ) ) // Increment R#X!
XXX00011010XXXA DEC+ R#X :$1=SUB(R#X( ) ,1 ) ,R#X($1 ) ,FL($1.hi( ) ) // Decrement R#X!
X00XXX1111XXXXB INT #T :HEAP($IP ) +IP(JP(#T<10?0:1 ) ) >0 // Programm interruption indexed by #T
XXX10011101110F XCHG [SP] :$1=DST( ) ,DST(DW($2=SP( ) ) ) , DW($2, $1 ) // Exchange retained pair with stack heap
XXXXXX11101110F XCHG P#Z,[SP] :$1=P#Z( ) ,P#Z(DW(SP( ) ) ) , DW(SP( ) , $1 ) // Exchange pair P#Z with stack heap
001XXX0XXX0XXXF XCHG P#Z,P#Y :$1=P#Z( ) ,P#Z(P#Y( ) ) ,P#Y($1 ) // Exchange P#Z! and P#Y!
010XXX0XXX0XXXF XCHG R#Z,R#Y :$1=R#Z( ) ,R#Z(R#Y( ) ) ,R#Y($1 ) // Exchange R#Z! and R#Y!
011XXX0XXX0XXXD LEA P#Z,T#X+T#Y :P#Z(T#X( ) +T#Y( ) ) // Load T#X!+T#Y! effective address into P#Z
111XXX0XXX0XXXD LEA P#Z,T#X-T#Y :P#Z(T#X( ) -T#Y( ) ) // Load T#X!-T#Y! effective address into P#Z
XXXXXX10100000E POP+ [P#Z+IB] :DW(P#Z( ) +$IV,HEAP( ) ) // Pop data into memory indexed by P#Z
XXXXXX10100XXXF MOV R#X,[P#Z+IB] :trace.is_port=IP_BP; trace.is_context=IP_SP; R#X(DB(P#Z( ) +$IV ) ) // Move memory data by P#Z pointer into R#X
XXXXXX10110000E PUSH+ [P#Z+IB] :HEAP(DW(P#Z( ) +$IV ) ) // Push data from memory indexed by P#Z
XXXXXX10110XXXF MOV [P#Z+IB],R#X :trace.is_port=IP_BP; trace.is_context=IP_SP; DB(P#Z( ) +$IV,R#X( ) ) // Move R#X register data into memory by P#Z
XXX10011101111E PUSH :HEAP(DST( ) ) // Push retained pair
XXXXXX11101111E PUSH+ S#Z :HEAP(S#Z( ) ) // Push service S#Z register pair to stack
XXX10011111111E POP :DST(HEAP( ) ) // Pop retained pair
XXXXXX11111111E POP+ S#Z :S#Z(HEAP( ) ) // Pop service S#Z register pair from stack
XXXXXX11101010E PUSH+ R#Z :DUP(#Z ) // Dup R#Z register history
XXXXXX11101011C SKIP [R#Z] :FH(R#Z( ) |8 ) ,FL((FL( ) & 0x02 ) | 0x05 ) // Exclude next operations by R#Z bits
XXXXXX11101100C SKIP R#Z :FH(#Z ) , FL((FL( ) & 0x02 ) | 0x05 ) // Exclude next operations by R#Z counter
XXXXXX11101101C SKIP #Z :FH(#Z | 8 ) , FL((FL( ) & 0x02 ) | 0x05 ) // Exclude next operations by #Z times
XXXXXX11111010E POP+ R#Z :DROP(#Z ) // Drop R#Z register history
XXXXXX11111011C LOOP [R#Z] :FH(R#Z( ) |8 ) ,FL((FL( ) & 0x02 ) | 0x09 ) // Forcing next operation by R#Z bits
XXXXXX11111100C LOOP R#Z :FH(#Z ) , FL((FL( ) & 0x02 ) | 0x09 ) // Forcing next operation by R#Z counter
XXXXXX11111101C LOOP #Z :FH(#Z | 8 ) , FL((FL( ) & 0x02 ) | 0x09 ) // Forcing next operation by #Z times
XXXXXX100XXXXXE PUSH+ #VIB :HEAP(0x#V00 + $IB ) // Push immediate data into stack
0XX10010111XXXX --- IB :return 0 // Reserved extended code
XXX10010111010E LEA +IB :DST(DST( ) +$IB ) // Load retained effective address
X1010010111XXXF MOV [U#X],IB :DB(U#X( ) ,$IB ) // Load immediate data into memory by U#X
XXXXXX10111000B JMP $+#UIB :$IW==-2?(FL((FL( ) & 0x02 ) | 0x0D ) ,trace.expression=0 ) :IP(IP( ) +$IW ) // Unonditional relative branching
XXXXXX10111001B CALL $+#UIB :$IW==-2?0:HEAP(IP(IP( ) +$IW ) ) // Unconditional relative call
XXXXXX10111XXXB JCND#X $+#UIB :CND#X?IP(IP( ) +$IW ) :0 // Branching if CND#X!
XXXXXXXXXXXXXXX --- :return 0 // Reserved code
Чт янв 12, 2017 21:01:55
petrenko писал(а):И , как это ни скучно, но "всё уже придумано до нас и без нас" - вполне N-ное число лет уже вовсю клепают "однотактовое ядро" для некоторых архитектур.
Чт янв 12, 2017 21:28:29
petrenko писал(а):И , как это ни скучно, но "всё уже придумано до нас и без нас" - вполне N-ное число лет уже вовсю клепают "однотактовое ядро" для некоторых архитектур.
*_Соверешенно верно ! Именно для самообучения - наилучшим образом ! Ну и ещё можно для досуговых целей тож .DX168B писал(а):И ,как ни странно, такие мысли бывают полезными для саморазвития*.
И все таки мне интересно было бы поболтать о процессоростроительстве ..
Чт янв 12, 2017 21:43:03
Я думаю, для самообучения в первую очередь было бы полезно разобраться в уже имеющихся процессорах, попытаться понять или поднять историю вопроса, почему в том или ином моменте было выбрано именно такое решение, а не какое-то другое, и к каким неудачным последствиям это решение привело в последующем.petrenko писал(а):Именно для самообучения - наилучшим образом !
Ну, например, разница между Z80 и семейством микроконтроллеров AVR, что мне доводилось программировать, бросается в глаза сразу: в первом шина для данных и команд одна, во втором — их две, по одной на каждую. В Z80 и AVR внешние устройства адресуются через специально адресное пространство — порты ввода-вывода, а в STM32 микроконтроллерах адресное пространство для устройств, оперативной памяти и ПЗУ едино. Я ещё далеко дилетант в подобных вопросах, хоть и занимаюсь периодически программированием на ассемблере, но мне кажется, что есть и другие походы к вопросу.Paguo-86PK писал(а):А насчёт архитектуры... Если я не очень ошибаюсь, именно архитектурой ВМ80 описывалось, что все арифметико-логические действия производятся с аккумулятором; что имеется поддержка до 256 УВВ; что максимально адресуемое пространство - 64кб; что поддерживается прямая и косвенная адресация
Чт янв 12, 2017 21:49:18
*_Ну это вовсе не резкая, а весьма даже мягкая критикаPaguo-86PK писал(а):.. достаточно резкую* критику..
..
.. разве я не достаточно уделил внимания этим деталям** ? ..
Воистину так !думаю, что концептуальная красота кодировки команд, .. - это самое последнее, о чём надо задумываться
Чт янв 12, 2017 21:49:52
В IBM-подобных системах обнулением памяти занимается биос на этапе проверки работоспособности памяти. При включении память забита мусором. Единственный способ "сбросить" динамическое ОЗУ — записать туда конкретное значение. Этим значением может быть команда NOP или любая другая по вашему желанию.Paguo-86PK писал(а):Так, например, меня возмутило, что в i8086 коду 00 соответствует операция ADD, что сбивает с толку, если память обнулена.
Чт янв 12, 2017 21:57:11
petrenko писал(а):Кроме того на nedopc.org/forum уже обсуждался принцип непосредственного изполнения объектов - когда у данных есть тег, описывающий тип и возможные процедуры/операции над таковыми данными.
Управляющему ядру остаётся лишь направить таковые данные в соответствующее обрабатывающее устройство - как частный случай - арифметические&логические данные направить в а.л.у.
Чт янв 12, 2017 21:59:50
Чт янв 12, 2017 22:22:24
Расстановку команд логичнее производить на этапе разводки ядра процессора, таким образом, чтобы эта разводка и схемотехника были наиболее просты. Снижает цену процессора. Компилятору будет всё равно, какая кодировка у какой команды.Paguo-86PK писал(а):Операции АЛУ также занимают интуитивно понятные позиции: A(Add)/B(suB)/C(Conjunction-AND)/D(Disjunction-OR)/E(Exclusive OR).
Чт янв 12, 2017 22:41:01
Вот тут то я категорически не согласен.B@R5uk писал(а):Расстановку команд логичнее производить на этапе разводки ядра процессора, таким образом, чтобы эта разводка и схемотехника были наиболее просты. Снижает цену процессора. Компилятору будет всё равно, какая кодировка у какой команды.Paguo-86PK писал(а):Операции АЛУ также занимают интуитивно понятные позиции: A(Add)/B(suB)/C(Conjunction-AND)/D(Disjunction-OR)/E(Exclusive OR).
Чт янв 12, 2017 23:36:59
Пт янв 13, 2017 00:26:17
Вoт это вопрос по существуLastHopeMan писал(а):ТС, а ваш процессор - это виртуально-программный продукт, или же реальное железное воплощение на транзисторах\ТТЛ логике?
Пт янв 13, 2017 01:12:07
Пт янв 13, 2017 13:11:31
Когда в детстве читал отцовские справочники с описанием устройств ЭВМ, иногда мечтал быть инженером и участвовать в разработках машин, подобных Cray и CYBER…LastHopeMan писал(а):Пускать устройства за дешифратором - это здравая идея, как идея. Я именно так планирую устраивать свою самоделку. Но если присмотреться, то типовая схема интеловских ПК как раз и являлась этим воплощением. Общая шина, процессор командует устройствами на ней. А вы похоже хотите, чтобы внутри процессора тоже сложилась подобная система, если я правильно понял. Это хорошая мысль, если процессор является сборным с "модулями", которые можно было бы подключать. Но в наше время УЖЕ не практично. Линии длиннее, размеры больше. Поэтому перспектив у данного подхода нет - вся высокочастотность в укорочении линий внутри процессора. Что же касается опкодов и анекдота про сумматор, то на самом деле все именно так. Когда я приступил к написанию хоть какой-то схемы для подобной вещицы, то в первый же день стало очевидно: ради простоты конструкции я готов пожертвовать 90% функциональности и быстродействия. Будь у меня завод под рукой - все равно бы сделал также. Дешифратор - это чертовски слабое место на мой взгляд, при сложной его архитектуре (команды вперемешку различного назначения) дешифрация некоторых команд может занимать ощутимое время, либо ощутимое количество транзисторов. Это все чертовски не окупается. Пока это все виртуально, то можно оптимизировать и структурировать. Как только переходим к практике - увы...
Пт янв 13, 2017 18:27:08
Пт янв 13, 2017 19:03:47
Вaш процессор напоминает мой, который многие критикуют. Суть которого в том, что АЛУ в нём отсутствует, но он просто работает как маршрутизатор потоков данных между всеми внешними устройствами, как умный ПДП. Подключив к нему внешние FPU/ALU - получаем полноценное процессорное устройство.DX168B писал(а):Можно добавить еще мультиплексоры на регистр SR, указатель стека и прочее.
Замысел во второй картинке заключается в том, что операнды узел забирает сам, покрутив счетчик PC.
Таим образом можно создавать инструкции с большим числом операндов. В качестве первого операнда можно указать количество рабочих операндов, чтобы узел, загрузив его, мог сориентироваться, сколько операндов можно забрать из памяти до появления следующей инструкции. А транслятор ассемблера можно реализовать так, чтобы транслятор сам вставлял количество операндов.