SSブログ
English Version

Z80での高速な乗算処理(その3)2バイト乗算への適用検討 [Z80]

 「Z80での高速な乗算処理」の記事の「応用編」で1バイトの乗算処理を使った2バイト乗算処理への拡張では今回提案しているマイナス二乗法の効果は確認できませんでした。1バイトの乗算処理では2.4倍程度速くなったマイナス二乗法の2バイト乗算処理への適用について再度考えてみました。

  1. 以前の簡易2バイト対応
     上記の記事で書いたマイナス二乗法の簡易的な2バイト乗算への適用は下記の式に示すように2バイト変数をバイトに分離して計算しました。


        (28*x1 + x0)*(28*y1 + y0) 
      = 216*x1*y1 + 28*(x0*y1 + x1*y0) + x0*y0 
     

     マイナス二乗法では1回の掛け算で二乗テーブルを3回引くので、上記の2バイト乗算では1バイトの乗算を4回実装する必要があることから、二乗テーブルを合計で12回引くことになります。


  2. マイナス二乗法の2バイト乗算への適用検討

    [二乗計算の高速化
     マイナス二乗法は下記の計算式で乗算値を求める方式です。


         (x - y)2 = x2 - 2*x*y + y2 
      ⇒ x*y = ( x2 + y2 - (x - y)2 ) / 2 
     

     従って2バイトの乗算に適用するためには2バイトの二乗を高速に計算する必要があります。2バイトの二乗をテーブルから丸ごと引く為にはメモリが大量に必要になるので、従来通り1バイトの二乗テーブルを使うことにしたいと思います。
     2バイトのデータを上位バイトと下位バイトに分けて考えると、二乗計算は下記のようになります。


        X = 28*x1 + x0 
      X2 = (28*x1 + x0)2 
           = 216*x12 + 29*x1*x0 + x02 
     

     ここで上記のマイナス二乗法の計算式より、x1*x0=(x12+x02-(x1-x0)2)/2 なので


        (28*X1 + x0)2 
     = 216*x12 + x02 + 29x1*x0 
     = 216*x12 + x02 + 28*(x12 + x02 - (x1 - x0)2
     = (216 + 28)*x12 + (28 + 1)*x02 - 28*(x1 - x0)2 
     

    となり、1バイト用の二乗テーブルを3回引くことで2バイトの二乗を求めることができるということになります。

    ★追記 2023/04/30 {
     下記の様に (28 + 1) を共通項にすることで若干最適化しました。


     = (216 + 28)*x12 + (28 + 1)*x02 - 28*(x1 - x0)2 
     = (28 + 1)*(28*x12 + x02) - 28*(x1 - x0)2 
     
    }


    [乗算の計算方法]
     符号付の乗算を考えると MSB は符号情報であることから、乗数と被乗数の絶対値を求めてから符号無し乗算処理を実施後に再度、符号付整数にするという処理になります。
     従って実際に乗算する値は絶対値であり、2バイト乗算の場合は符号無しの15ビット整数を掛け合わせることになります。
     そのため冒頭で書いた「Z80での高速な乗算処理」の記事の出だしで書いている


     (X + Y)2 - (X - Y)2 = 4*X*Y 
     ⇒ X*Y = ((X + Y)2 - (X - Y)2) / 4 
     
     

    を使用しても (X + Y) が16ビットになるので桁あふれせずに前述の二乗テーブル引きにより、2バイトの二乗の値を求めることができます。

     計算のコストの目安として仮に二乗テーブルを引く回数とすると、上記の方法による2バイトの乗算処理でテーブルを引く回数は6回(=2x3回)となり、前項で書いた以前の簡易適用の場合(12回)の半分で済むことになります(但し、二乗を求めた後に複数の加算処理等が必要になる)。
     どうでしょう。中々見込みがありそうになってきたと思いませんか?


  3. コード化
     机上の方式検討だけでは評価できないので、簡易的にコード化して評価してみたいと思います。但し、今回考案した処理内容の評価が主要な目的なのでコード自体の最適化はあまり行っていません。

    [標準的な乗算処理]
     比較のために標準的な筆算方式による符号無し2バイトの乗算処理を作ってみました。
     ネットを探せば見つかりそうではありますが処理的にも単純なので自前でコードを起こしました。レジスタのみで処理が完結しているのでそれなりに高速な乗算処理になったのではないかと思います(引数とリターン値へのレジスタ割り振りを下記の乗算処理と合わせるために先頭と末尾で調整しています)。

    筆算方式による標準的な2バイト乗算処理(Z80アセンブラ)
    ; normal unsigned 16 bits mul ; DE <- val1 ; HL <- val2 ; HLBC -> val1 * val2 ; ; BCHL vs DE 02A1 3E 10 MUL16: LD A,16 02A3 44 LD B,H 02A4 4D LD C,L 02A5 21 0000 LD HL,0 02A8 29 MUL16L: ADD HL,HL 02A9 CB 11 RL C 02AB CB 10 RL B 02AD 30 04 JR NC,MUL16N 02AF 19 ADD HL,DE 02B0 30 01 JR NC,MUL16N 02B2 03 INC BC 02B3 3D MUL16N: DEC A 02B4 C2 02A8 JP NZ,MUL16L 02B7 59 LD E,C 02B8 50 LD D,B 02B9 EB EX DE,HL 02BA 4B LD C,E 02BB 42 LD B,D 02BC C9 RET


    [以前の簡易乗算処理]
     冒頭で書いた以前行った2バイトを上位バイトと下位バイトに分割した簡易的な乗算処理も再度コードを起こしてみました。高速化のためにローカルな変数領域は使用せずにレジスタとスタックのみで処理するようにしています。

    バイト分割による乗算処理(Z80アセンブラ)
    ; ; (256*x1 + x0)*(256*y1 + y0) ; = 2^16x1y1 + 2^8(x0*y1 + x1*y0) + x0*y0 ; ; | . | . | . | . | ; <--- x1y1 ---> ; <--- x0y1 ---> ; <--- x1y0 ---> ; <--- x0y0 ---> ; unsigned 15 bits mul ; DE <- val1(X) ; HL <- val2(Y) ; HLBC -> val1 * val2 0359 E5 FMul16: PUSH HL ; (SP):Y 035A D5 PUSH DE ; (SP):Y,X 035B 55 LD D,L ; DE: y0:x0 035C 6B LD L,E ; HL: y1:x0 035D E5 PUSH HL ; (SP):Y,X,y1:x0 035E CD 038B CALL FMul8 ; HL<-x0*y0 0361 E3 EX (SP),HL ; (SP):Y,X,x0*y0, HL:y1:x0 0362 EB EX DE,HL ; DE:y1:x0 0363 CD 038B CALL FMul8 ; HL:x0*y1 0366 D1 POP DE ; (SP):Y,X DE:x0*y0 0367 C1 POP BC ; (SP):Y BC:x1:x0 0368 E3 EX (SP),HL ; (SP):x0*y1, HL:y1:y0 0369 D5 PUSH DE ; (SP):x0*y1,x0*y0 036A 50 LD D,B 036B 5D LD E,L ; DE:x1:y0 036C 68 LD L,B ; HL:y1:x1 036D E5 PUSH HL ; (SP):x0*y1,x0*y0,y1:x1 036E CD 038B CALL FMul8 ; HL:x1*y0 0371 E3 EX (SP),HL ; (SP):x0*y1,x0*y0,x1*y0, HL:y1:x1 0372 EB EX DE,HL ; DE:y1:x1 0373 CD 038B CALL FMul8 ; HL:x1*y1 0376 D1 POP DE ; (SP):x0*y1,x0*y0 DE:x1*y0 0377 7C LD A,H 0378 65 LD H,L 0379 2E 00 LD L,0 037B 19 ADD HL,DE 037C CE 00 ADC A,0 037E C1 POP BC ; (SP):x0*y1 BC:x0*y0 037F D1 POP DE ; (SP):none DE:x0*y1 0380 19 ADD HL,DE 0381 16 00 LD D,0 0383 58 LD E,B 0384 8A ADC A,D ; D:0 0385 19 ADD HL,DE 0386 8A ADC A,D ; D:0 0387 45 LD B,L 0388 6C LD L,H 0389 67 LD H,A 038A C9 RET ; unsigned 8 bits fast multi(my method) ; x*y = (x^2 + y^2 - (x-y)^2)/2 ; E <- data0 ; D <- data1 ; HL -> data0 * data1 038B 6A FMul8: LD L,D ; 4 038C 7B LD A,E ; 4 038D A5 AND L ; 4 038E 1F RRA ; 4 038F 26 06 LD H,HIGH(MULTB2) ; 7 0391 54 LD D,H ; 4 0392 1A LD A,(DE) ; 7 0393 8E ADC A,(HL) ; 7 0394 4F LD C,A ; 4 0395 14 INC D ; 4 0396 24 INC H ; 4 0397 1A LD A,(DE) ; 7 0398 8E ADC A,(HL) ; 7 0399 57 LD D,A ; 4 039A 7B LD A,E ; 4 039B 95 SUB L ; 4 039C 30 02 JR NC,FFMu10 ; 12/7 039E ED 44 NEG ; 8 03A0 6F FFMU10: LD L,A ; 4 03A1 5E LD E,(HL) ; 7 03A2 25 DEC H ; 4 03A3 79 LD A,C ; 4 03A4 96 SUB (HL) ; 7 03A5 6F LD L,A ; 4 03A6 7A LD A,D ; 4 03A7 9B SBC A,E ; 4 03A8 67 LD H,A ; 4 03A9 C9 RET ; 10 ; (8bit ^ 2) / 2 table 0600 00 00 02 04 MULTB2: DB 000H,000H,002H,004H,008H,00CH,012H,018H ; low byte 0604 08 0C 12 18 0608 20 28 32 3C DB 020H,028H,032H,03CH,048H,054H,062H,070H 060C 48 54 62 70 0610 80 90 A2 B4 DB 080H,090H,0A2H,0B4H,0C8H,0DCH,0F2H,008H 0614 C8 DC F2 08 0618 20 38 52 6C DB 020H,038H,052H,06CH,088H,0A4H,0C2H,0E0H 061C 88 A4 C2 E0 0620 00 20 42 64 DB 000H,020H,042H,064H,088H,0ACH,0D2H,0F8H 0624 88 AC D2 F8 0628 20 48 72 9C DB 020H,048H,072H,09CH,0C8H,0F4H,022H,050H 062C C8 F4 22 50 0630 80 B0 E2 14 DB 080H,0B0H,0E2H,014H,048H,07CH,0B2H,0E8H 0634 48 7C B2 E8 0638 20 58 92 CC DB 020H,058H,092H,0CCH,008H,044H,082H,0C0H 063C 08 44 82 C0 0640 00 40 82 C4 DB 000H,040H,082H,0C4H,008H,04CH,092H,0D8H 0644 08 4C 92 D8 0648 20 68 B2 FC DB 020H,068H,0B2H,0FCH,048H,094H,0E2H,030H 064C 48 94 E2 30 0650 80 D0 22 74 DB 080H,0D0H,022H,074H,0C8H,01CH,072H,0C8H 0654 C8 1C 72 C8 0658 20 78 D2 2C DB 020H,078H,0D2H,02CH,088H,0E4H,042H,0A0H 065C 88 E4 42 A0 0660 00 60 C2 24 DB 000H,060H,0C2H,024H,088H,0ECH,052H,0B8H 0664 88 EC 52 B8 0668 20 88 F2 5C DB 020H,088H,0F2H,05CH,0C8H,034H,0A2H,010H 066C C8 34 A2 10 0670 80 F0 62 D4 DB 080H,0F0H,062H,0D4H,048H,0BCH,032H,0A8H 0674 48 BC 32 A8 0678 20 98 12 8C DB 020H,098H,012H,08CH,008H,084H,002H,080H 067C 08 84 02 80 0680 00 80 02 84 DB 000H,080H,002H,084H,008H,08CH,012H,098H 0684 08 8C 12 98 0688 20 A8 32 BC DB 020H,0A8H,032H,0BCH,048H,0D4H,062H,0F0H 068C 48 D4 62 F0 0690 80 10 A2 34 DB 080H,010H,0A2H,034H,0C8H,05CH,0F2H,088H 0694 C8 5C F2 88 0698 20 B8 52 EC DB 020H,0B8H,052H,0ECH,088H,024H,0C2H,060H 069C 88 24 C2 60 06A0 00 A0 42 E4 DB 000H,0A0H,042H,0E4H,088H,02CH,0D2H,078H 06A4 88 2C D2 78 06A8 20 C8 72 1C DB 020H,0C8H,072H,01CH,0C8H,074H,022H,0D0H 06AC C8 74 22 D0 06B0 80 30 E2 94 DB 080H,030H,0E2H,094H,048H,0FCH,0B2H,068H 06B4 48 FC B2 68 06B8 20 D8 92 4C DB 020H,0D8H,092H,04CH,008H,0C4H,082H,040H 06BC 08 C4 82 40 06C0 00 C0 82 44 DB 000H,0C0H,082H,044H,008H,0CCH,092H,058H 06C4 08 CC 92 58 06C8 20 E8 B2 7C DB 020H,0E8H,0B2H,07CH,048H,014H,0E2H,0B0H 06CC 48 14 E2 B0 06D0 80 50 22 F4 DB 080H,050H,022H,0F4H,0C8H,09CH,072H,048H 06D4 C8 9C 72 48 06D8 20 F8 D2 AC DB 020H,0F8H,0D2H,0ACH,088H,064H,042H,020H 06DC 88 64 42 20 06E0 00 E0 C2 A4 DB 000H,0E0H,0C2H,0A4H,088H,06CH,052H,038H 06E4 88 6C 52 38 06E8 20 08 F2 DC DB 020H,008H,0F2H,0DCH,0C8H,0B4H,0A2H,090H 06EC C8 B4 A2 90 06F0 80 70 62 54 DB 080H,070H,062H,054H,048H,03CH,032H,028H 06F4 48 3C 32 28 06F8 20 18 12 0C DB 020H,018H,012H,00CH,008H,004H,002H,000H 06FC 08 04 02 00 0700 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H ; high byte 0704 00 00 00 00 0708 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H 070C 00 00 00 00 0710 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,001H 0714 00 00 00 01 0718 01 01 01 01 DB 001H,001H,001H,001H,001H,001H,001H,001H 071C 01 01 01 01 0720 02 02 02 02 DB 002H,002H,002H,002H,002H,002H,002H,002H 0724 02 02 02 02 0728 03 03 03 03 DB 003H,003H,003H,003H,003H,003H,004H,004H 072C 03 03 04 04 0730 04 04 04 05 DB 004H,004H,004H,005H,005H,005H,005H,005H 0734 05 05 05 05 0738 06 06 06 06 DB 006H,006H,006H,006H,007H,007H,007H,007H 073C 07 07 07 07 0740 08 08 08 08 DB 008H,008H,008H,008H,009H,009H,009H,009H 0744 09 09 09 09 0748 0A 0A 0A 0A DB 00AH,00AH,00AH,00AH,00BH,00BH,00BH,00CH 074C 0B 0B 0B 0C 0750 0C 0C 0D 0D DB 00CH,00CH,00DH,00DH,00DH,00EH,00EH,00EH 0754 0D 0E 0E 0E 0758 0F 0F 0F 10 DB 00FH,00FH,00FH,010H,010H,010H,011H,011H 075C 10 10 11 11 0760 12 12 12 13 DB 012H,012H,012H,013H,013H,013H,014H,014H 0764 13 13 14 14 0768 15 15 15 16 DB 015H,015H,015H,016H,016H,017H,017H,018H 076C 16 17 17 18 0770 18 18 19 19 DB 018H,018H,019H,019H,01AH,01AH,01BH,01BH 0774 1A 1A 1B 1B 0778 1C 1C 1D 1D DB 01CH,01CH,01DH,01DH,01EH,01EH,01FH,01FH 077C 1E 1E 1F 1F 0780 20 20 21 21 DB 020H,020H,021H,021H,022H,022H,023H,023H 0784 22 22 23 23 0788 24 24 25 25 DB 024H,024H,025H,025H,026H,026H,027H,027H 078C 26 26 27 27 0790 28 29 29 2A DB 028H,029H,029H,02AH,02AH,02BH,02BH,02CH 0794 2A 2B 2B 2C 0798 2D 2D 2E 2E DB 02DH,02DH,02EH,02EH,02FH,030H,030H,031H 079C 2F 30 30 31 07A0 32 32 33 33 DB 032H,032H,033H,033H,034H,035H,035H,036H 07A4 34 35 35 36 07A8 37 37 38 39 DB 037H,037H,038H,039H,039H,03AH,03BH,03BH 07AC 39 3A 3B 3B 07B0 3C 3D 3D 3E DB 03CH,03DH,03DH,03EH,03FH,03FH,040H,041H 07B4 3F 3F 40 41 07B8 42 42 43 44 DB 042H,042H,043H,044H,045H,045H,046H,047H 07BC 45 45 46 47 07C0 48 48 49 4A DB 048H,048H,049H,04AH,04BH,04BH,04CH,04DH 07C4 4B 4B 4C 4D 07C8 4E 4E 4F 50 DB 04EH,04EH,04FH,050H,051H,052H,052H,053H 07CC 51 52 52 53 07D0 54 55 56 56 DB 054H,055H,056H,056H,057H,058H,059H,05AH 07D4 57 58 59 5A 07D8 5B 5B 5C 5D DB 05BH,05BH,05CH,05DH,05EH,05FH,060H,061H 07DC 5E 5F 60 61 07E0 62 62 63 64 DB 062H,062H,063H,064H,065H,066H,067H,068H 07E4 65 66 67 68 07E8 69 6A 6A 6B DB 069H,06AH,06AH,06BH,06CH,06DH,06EH,06FH 07EC 6C 6D 6E 6F 07F0 70 71 72 73 DB 070H,071H,072H,073H,074H,075H,076H,077H 07F4 74 75 76 77 07F8 78 79 7A 7B DB 078H,079H,07AH,07BH,07CH,07DH,07EH,07FH 07FC 7C 7D 7E 7F


    [今回提案の乗算処理]
     上述の今回考えた乗算処理をコード化したものが下記になります。今回の方式は乗算値を求める際には乗数と被乗数のプラスとマイナスの二乗を用いるプラマイ二乗法を採用していますが、各項の二乗を求める際にマイナス二乗の式を用いていることから従来通りマイナス二乗法と呼称することにします。
     尚、下記の乗算処理と上記の2つの乗算処理は乗数及び被乗数が0x0000~0x7fffの範囲内で計算結果が同じであることを確認しています。

    今回提案の乗算処理(Z80アセンブラ)
    ; unsigned 15 bits mul ; DE <- val1 ; HL <- val2 ; HLBC -> val1 * val2 ; ; X*Y = ((X + Y)^2 - (X - Y)^2) / 4 ; 02BD D5 FMUL15: PUSH DE 02BE E5 PUSH HL 02BF 19 ADD HL,DE 02C0 EB EX DE,HL 02C1 CD 02F0 CALL Square2B ; DEBC<-DE^2 02C4 E1 POP HL 02C5 EB EX DE,HL 02C6 E3 EX (SP),HL 02C7 C5 PUSH BC 02C8 AF XOR A 02C9 ED 52 SBC HL,DE 02CB 30 05 JR NC,FMU150 02CD 95 SUB L ; A:0 02CE 6F LD L,A 02CF 9F SBC A,A 02D0 94 SUB H 02D1 67 LD H,A 02D2 EB FMU150: EX DE,HL 02D3 CD 02F0 CALL Square2B 02D6 E1 POP HL 02D7 B7 OR A 02D8 ED 42 SBC HL,BC 02DA 44 LD B,H 02DB 4D LD C,L 02DC E1 POP HL 02DD ED 52 SBC HL,DE 02DF CB 3C SRL H 02E1 CB 1D RR L 02E3 CB 18 RR B 02E5 CB 19 RR C 02E7 CB 3C SRL H 02E9 CB 1D RR L 02EB CB 18 RR B 02ED CB 19 RR C 02EF C9 RET ; square unsigned 16bit ; DE <- input value ; DEBC -> value^2 ; ; ; X = 2^8*x1 + x0 ; X^2 = 2^16+x1^2 + 2^9*x1*x0 + x0^2 ; = 2^16*x1^2 + x0^2 + 2^8*(x1^2 + x0^2 - (x1 - x0)^2) ; = (2^16 + 2^8)*x1^2 + (2^8 + 1)*x0^2 - 2^8*(x1-x0)^2 ; = (2^8 + 1)*(2^8*x1^2 + x0^2) - 2^8*(x1-x0)^2 ; ; 3H-3L:2H-2L:1H-1L:0H-0L ; ; x1^2 <+++++++++> ; x1^2 <+++++++++> ; dif^2 <---------> ; x0^2 <+++++++++> ; x0^2 <+++++++++> 02F0 Square2B: 02F0 26 04 LD H,HIGH(MULTBL) 02F2 6B LD L,E 02F3 7E LD A,(HL) 02F4 08 EX AF,AF' 02F5 24 INC H 02F6 4E LD C,(HL) ; CA:x0^2 02F7 6A LD L,D 02F8 7A LD A,D 02F9 93 SUB E 02FA 30 02 JR NC,SquV20 02FC ED 44 NEG 02FE 56 SquV20: LD D,(HL) 02FF 25 DEC H 0300 5E LD E,(HL) ; DE:x1^2 0301 6F LD L,A ; abs(x1-x0) 0302 AF XOR A 0303 47 LD B,A 0304 EB EX DE,HL 0305 09 ADD HL,BC 0306 08 EX AF,AF' 0307 4F LD C,A 0308 08 EX AF,AF' 0309 45 LD B,L 030A 8C ADC A,H ; AHL=A3:A2:A1 030B 09 ADD HL,BC 030C CE 00 ADC A,0 030E EB EX DE,HL 030F 4E LD C,(HL) 0310 24 INC H 0311 46 LD B,(HL) ; BC:dif^2 0312 EB EX DE,HL 0313 ED 42 SBC HL,BC ; CY:0 0315 DE 00 SBC A,0 0317 57 LD D,A 0318 5C LD E,H 0319 45 LD B,L 031A 08 EX AF,AF' 031B 4F LD C,A 031C C9 RET ORG ($ + 255) AND 0FF00H ; 8bit ^ 2 table 0400 00 01 04 09 MULTBL: DB 000H,001H,004H,009H,010H,019H,024H,031H ; low byte 0404 10 19 24 31 0408 40 51 64 79 DB 040H,051H,064H,079H,090H,0A9H,0C4H,0E1H 040C 90 A9 C4 E1 0410 00 21 44 69 DB 000H,021H,044H,069H,090H,0B9H,0E4H,011H 0414 90 B9 E4 11 0418 40 71 A4 D9 DB 040H,071H,0A4H,0D9H,010H,049H,084H,0C1H 041C 10 49 84 C1 0420 00 41 84 C9 DB 000H,041H,084H,0C9H,010H,059H,0A4H,0F1H 0424 10 59 A4 F1 0428 40 91 E4 39 DB 040H,091H,0E4H,039H,090H,0E9H,044H,0A1H 042C 90 E9 44 A1 0430 00 61 C4 29 DB 000H,061H,0C4H,029H,090H,0F9H,064H,0D1H 0434 90 F9 64 D1 0438 40 B1 24 99 DB 040H,0B1H,024H,099H,010H,089H,004H,081H 043C 10 89 04 81 0440 00 81 04 89 DB 000H,081H,004H,089H,010H,099H,024H,0B1H 0444 10 99 24 B1 0448 40 D1 64 F9 DB 040H,0D1H,064H,0F9H,090H,029H,0C4H,061H 044C 90 29 C4 61 0450 00 A1 44 E9 DB 000H,0A1H,044H,0E9H,090H,039H,0E4H,091H 0454 90 39 E4 91 0458 40 F1 A4 59 DB 040H,0F1H,0A4H,059H,010H,0C9H,084H,041H 045C 10 C9 84 41 0460 00 C1 84 49 DB 000H,0C1H,084H,049H,010H,0D9H,0A4H,071H 0464 10 D9 A4 71 0468 40 11 E4 B9 DB 040H,011H,0E4H,0B9H,090H,069H,044H,021H 046C 90 69 44 21 0470 00 E1 C4 A9 DB 000H,0E1H,0C4H,0A9H,090H,079H,064H,051H 0474 90 79 64 51 0478 40 31 24 19 DB 040H,031H,024H,019H,010H,009H,004H,001H 047C 10 09 04 01 0480 00 01 04 09 DB 000H,001H,004H,009H,010H,019H,024H,031H 0484 10 19 24 31 0488 40 51 64 79 DB 040H,051H,064H,079H,090H,0A9H,0C4H,0E1H 048C 90 A9 C4 E1 0490 00 21 44 69 DB 000H,021H,044H,069H,090H,0B9H,0E4H,011H 0494 90 B9 E4 11 0498 40 71 A4 D9 DB 040H,071H,0A4H,0D9H,010H,049H,084H,0C1H 049C 10 49 84 C1 04A0 00 41 84 C9 DB 000H,041H,084H,0C9H,010H,059H,0A4H,0F1H 04A4 10 59 A4 F1 04A8 40 91 E4 39 DB 040H,091H,0E4H,039H,090H,0E9H,044H,0A1H 04AC 90 E9 44 A1 04B0 00 61 C4 29 DB 000H,061H,0C4H,029H,090H,0F9H,064H,0D1H 04B4 90 F9 64 D1 04B8 40 B1 24 99 DB 040H,0B1H,024H,099H,010H,089H,004H,081H 04BC 10 89 04 81 04C0 00 81 04 89 DB 000H,081H,004H,089H,010H,099H,024H,0B1H 04C4 10 99 24 B1 04C8 40 D1 64 F9 DB 040H,0D1H,064H,0F9H,090H,029H,0C4H,061H 04CC 90 29 C4 61 04D0 00 A1 44 E9 DB 000H,0A1H,044H,0E9H,090H,039H,0E4H,091H 04D4 90 39 E4 91 04D8 40 F1 A4 59 DB 040H,0F1H,0A4H,059H,010H,0C9H,084H,041H 04DC 10 C9 84 41 04E0 00 C1 84 49 DB 000H,0C1H,084H,049H,010H,0D9H,0A4H,071H 04E4 10 D9 A4 71 04E8 40 11 E4 B9 DB 040H,011H,0E4H,0B9H,090H,069H,044H,021H 04EC 90 69 44 21 04F0 00 E1 C4 A9 DB 000H,0E1H,0C4H,0A9H,090H,079H,064H,051H 04F4 90 79 64 51 04F8 40 31 24 19 DB 040H,031H,024H,019H,010H,009H,004H,001H 04FC 10 09 04 01 0500 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H ; high byte 0504 00 00 00 00 0508 00 00 00 00 DB 000H,000H,000H,000H,000H,000H,000H,000H 050C 00 00 00 00 0510 01 01 01 01 DB 001H,001H,001H,001H,001H,001H,001H,002H 0514 01 01 01 02 0518 02 02 02 02 DB 002H,002H,002H,002H,003H,003H,003H,003H 051C 03 03 03 03 0520 04 04 04 04 DB 004H,004H,004H,004H,005H,005H,005H,005H 0524 05 05 05 05 0528 06 06 06 07 DB 006H,006H,006H,007H,007H,007H,008H,008H 052C 07 07 08 08 0530 09 09 09 0A DB 009H,009H,009H,00AH,00AH,00AH,00BH,00BH 0534 0A 0A 0B 0B 0538 0C 0C 0D 0D DB 00CH,00CH,00DH,00DH,00EH,00EH,00FH,00FH 053C 0E 0E 0F 0F 0540 10 10 11 11 DB 010H,010H,011H,011H,012H,012H,013H,013H 0544 12 12 13 13 0548 14 14 15 15 DB 014H,014H,015H,015H,016H,017H,017H,018H 054C 16 17 17 18 0550 19 19 1A 1A DB 019H,019H,01AH,01AH,01BH,01CH,01CH,01DH 0554 1B 1C 1C 1D 0558 1E 1E 1F 20 DB 01EH,01EH,01FH,020H,021H,021H,022H,023H 055C 21 21 22 23 0560 24 24 25 26 DB 024H,024H,025H,026H,027H,027H,028H,029H 0564 27 27 28 29 0568 2A 2B 2B 2C DB 02AH,02BH,02BH,02CH,02DH,02EH,02FH,030H 056C 2D 2E 2F 30 0570 31 31 32 33 DB 031H,031H,032H,033H,034H,035H,036H,037H 0574 34 35 36 37 0578 38 39 3A 3B DB 038H,039H,03AH,03BH,03CH,03DH,03EH,03FH 057C 3C 3D 3E 3F 0580 40 41 42 43 DB 040H,041H,042H,043H,044H,045H,046H,047H 0584 44 45 46 47 0588 48 49 4A 4B DB 048H,049H,04AH,04BH,04CH,04DH,04EH,04FH 058C 4C 4D 4E 4F 0590 51 52 53 54 DB 051H,052H,053H,054H,055H,056H,057H,059H 0594 55 56 57 59 0598 5A 5B 5C 5D DB 05AH,05BH,05CH,05DH,05FH,060H,061H,062H 059C 5F 60 61 62 05A0 64 65 66 67 DB 064H,065H,066H,067H,069H,06AH,06BH,06CH 05A4 69 6A 6B 6C 05A8 6E 6F 70 72 DB 06EH,06FH,070H,072H,073H,074H,076H,077H 05AC 73 74 76 77 05B0 79 7A 7B 7D DB 079H,07AH,07BH,07DH,07EH,07FH,081H,082H 05B4 7E 7F 81 82 05B8 84 85 87 88 DB 084H,085H,087H,088H,08AH,08BH,08DH,08EH 05BC 8A 8B 8D 8E 05C0 90 91 93 94 DB 090H,091H,093H,094H,096H,097H,099H,09AH 05C4 96 97 99 9A 05C8 9C 9D 9F A0 DB 09CH,09DH,09FH,0A0H,0A2H,0A4H,0A5H,0A7H 05CC A2 A4 A5 A7 05D0 A9 AA AC AD DB 0A9H,0AAH,0ACH,0ADH,0AFH,0B1H,0B2H,0B4H 05D4 AF B1 B2 B4 05D8 B6 B7 B9 BB DB 0B6H,0B7H,0B9H,0BBH,0BDH,0BEH,0C0H,0C2H 05DC BD BE C0 C2 05E0 C4 C5 C7 C9 DB 0C4H,0C5H,0C7H,0C9H,0CBH,0CCH,0CEH,0D0H 05E4 CB CC CE D0 05E8 D2 D4 D5 D7 DB 0D2H,0D4H,0D5H,0D7H,0D9H,0DBH,0DDH,0DFH 05EC D9 DB DD DF 05F0 E1 E2 E4 E6 DB 0E1H,0E2H,0E4H,0E6H,0E8H,0EAH,0ECH,0EEH 05F4 E8 EA EC EE 05F8 F0 F2 F4 F6 DB 0F0H,0F2H,0F4H,0F6H,0F8H,0FAH,0FCH,0FEH 05FC F8 FA FC FE
    ★変更 2023/04/30 上記の共通項化することで約 15% スピードアップしました。



  4. 評価結果
     評価方法としては上記の3つの乗算処理に対して乗数及び被乗数を 0x0000 ~ 0x7fff の範囲で 0 から16 づつ増やしていった二重ループ処理の合計時間を計ってみました。従って乗算処理のみならず、乗数と被乗数の加算及び範囲チェック等のロジックも処理に含まれてしまいますが、実際のアプリでの使用状況により近づくのではないかと思います。

    No.methodtime[s]ratio
    1Normal method231.61.00
    2Minus square method
    (previous 1byte square)
    216.31.07
    3Minus square method
    (new 2bytes square)
    175.01.32
    ※2023/04/30 new method's ratio is up to 1.32 from 1.14

     色々書いてきた割にはあまり高速化していませんね^^;;;
     2バイト以上のバイト長の乗算計算は他の画期的なブレークスルーが無いと2倍以上の高速化は難しそうです。

     上記の処理時間測定時の画面のハードコピーも貼っておきます。Z80 が 20MHz で動作している自作ボードで CP/M 環境を使って ZSID でブレークを掛けて測定しました。時間測定自体は TeraTerm のマクロで自動的に計測しています。

    実行時間比較画面


★追記 2024/03/08
 「HD64180Compact(その6)16bit乗算処理」の記事に HD64180 の 8bit 乗算命令を使って作成した 16bit 乗算処理の演算速度について記載しました。



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

超小型Z80マイコン(その13)クロック20MHz化 [Z80]

 前回の記事でプリント基板化してほぼ Z80 のチップサイズと同程度のサイズの基板にできたことを書きましたが、今回は Z80 のクロックを12MHz から 20MHz に変更した場合の動作を確認しましたので結果を記録しておきたいと思います。

 但し、今回の3チップ構成での Z80 のチップサイズのプリント基板は弄らずに開発用に汎用基板で手配線した基板に 74HCU04 と 20MHz のクリスタルを追加して動作を確認して見ました。元々あった 12MHz のクロックは USB 機能を実現するために必要なので変更できないのです。
 一発では動作しませんでしたが、Z80 側のソフトウェアをタイミング調整することで 12MHz と 20MHz の両方で CP/M が動作するようになりました(上記以外のハードの変更は発生しませんでした)。

 下の写真は改造後の開発用基板です。Z80 のクロックはジャンパーピンで 12MHz と 20MHz のどちらか一方に切り替えられるようにしました。

開発用基板


 下図はもともとの 12MHz の状態で ASCIIART を実行した結果になります。

ASCIIART実行結果(12MHz)


 20MHz 動作では1分を切ることができました。上の 12MHz の時間からクロック反比例での予測時間は 57.4s(= 95.6 x 12 / 20)なのでほぼ計算値通りということになります。

ASCIIART実行結果(20MHz)



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

電動こて先クリーナーの製作(その4)ケース完成 [PIC]

 半田ごてのこて先クリーナーを自作中で前回の記事で PIC 搭載の制御回路のプリント基板ができたことを書きましたが、いよいよケースが完成しましたので記録しておきます。

 CAD(DesignSpark Mechanical)を使って設計したCAD画面が下図になります。
 判り辛いですが背面の扉を開くと回転ブラシの後方に設置した半田屑受け皿の取り出しや電池交換ができるようにしました。扉の固定は機構設計が楽なマグネット方式にしてみました。

こて先クリーナーCAD画面(前面)
こて先クリーナーCAD画面(前面透過)
こて先クリーナーCAD画面(前面内部)
こて先クリーナーCAD画面(後面内部)


 完成後に撮影した記念写真も貼っておきます。
 下の写真は正面から撮ったものでこて先を入れる部分は耐熱性を高めるために厚手(60um)のアルミホイルで包んでいます。アルミホイルをもう少し丁寧に貼れば金属部品の様に見せることが可能かもしれませんw
 右側のスイッチを押すことで待機状態になりスイッチの下の LED が点滅します。こて先を入れると自動的にブラシが回転し、3秒後に停止します。何もしなければ3分後に電源が切れます。待機時には電源(単三電池2本)の電圧もチェックしていて 2.3V 以下や 2.0V 以下になると LED の点灯パターンが変化して知らせるようになっています。1.8V 以下の場合は LED を速いテンポで点滅後、過放電防止のために電源を切るようにしました。

こて先クリーナー(左前面)


 右前面から見ると下の写真のようになります。モーターや制御基板を左側に実装した関係でこて先挿入口が中心よりも右側にあります。

こて先クリーナー(右前面)


 背面は下の写真のようになっています。前述のようにメンテナンス用の扉を設け、今回はマグネットで固定しました。

こて先クリーナー(背面)


 背面の扉を開けると下の写真のようになり、半田屑受け皿の掃除や電池交換をできるようになっています。

こて先クリーナー(背面2)


 Twitter に投稿した動画付きメッセージも貼っておきます。


★追記 2023/05/02 {
 こて先のクリーン前後の写真を撮ったので貼っておきます。
 写真では判り辛いですがクリーン後はピッカピカで気持ちが良いですね。百均の小型たわしをブラシにしているのでこて先を摩耗せずに汚れだけが取り除かれて程よい感じです。

クリーン前 クリーン後
}


★追記 2023/05/05 {
 説明動画をYouTubeにアップしましたので貼っておきます。

}


[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

ミニテーブルソーの購入 [購入]

 プリント基板の製造が3ドル程度(5枚の製造費2ドル+送料1ドル)でできるようになった昨今では自宅で基板を作ることがほとんどなくなったのですが 10MHz 以上※1の回路はブレッドボードでは不安定になることがあるので「超小型Z80マイコン(その10)確認用基板作成」の記事で書いたように稀に汎用基板で自作する場合があります。
 更に頻度は少なくなりますが下記の Twitter メッセージの様にちょっとした実験を行いたい時等に出来合いの汎用基板のサイズが大きすぎてガラエポ基板を切断したい場合があります。

※1)ネット情報ではブレッドボードでは上限周波数は100KHz、電流500mA程度との情報もあるが、10MHzまで行けるとの情報もある。個人的な経験から言うと本体とジャンパー線が新品であれば20MHzクロックのマイコン回路も動いたが、使い古していくにつれて不安定になってくる。



 従来ガラエポ基板の切断は下の写真のようにプロクソンのミニルーターにダイヤモンドディスクの丸鋸刃を付けて行っていました。
 しかし、直線に切断するのが難しく、かつ体に悪そうなガラエポの粉塵が舞い上がるので塗装用のマスクをかけて作業していました。

ダイヤモンドブレードを装着したプロクソンルーター


 上記の様なガラエポ基板のカット作業の環境を改善したいと考えていたところ、Twitter のタイムラインでプロクソンのテーブルソーの情報を見つけ、Amazon で探してみたところ1万2千円程で、基板カット用のダイヤモンドブレードは5千円弱でした。使用頻度から考えても合計で2万弱はきついので、性能は低くてもいいのでもっと安いものが無いか AliExpress で探したところ、ダイヤモンドブレードを含めて4枚のブレードが付属して送料込みで8千2百円のものがあったので(ブレードの高さ調整機能無しの物であればもっと安いものもあった))購入してみました。
 掃除機用のアダプタも付属しているので、基板切断時に掃除機を取り付ければ、ガラエポの粉塵も殆ど舞い上がらないものと思います。

購入したミニテーブルソー


 付属品のACアダプタはスライドスイッチの操作により、12V~24Vまで7通りの電圧に設定可能なので回転速度調整もできます。
 まだ基板切断は行っていませんがこれでガラエポ基板の切断作業環境がかなり良くなったのではないかと期待しています。

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

電動こて先クリーナーの製作(その3)プリント基板完成 [PIC]

 前回の記事で PIC を使った制御回路とプリント基板のパターン設計等について書きました。プリント基板ができましたのでブログに書いて置きたいと思います。

 下の写真が完成したプリント基板のトップ面です。PIC(PIC12F683)は表面実装タイプではなくスルホールタイプを実装しています。昇圧用 IC(HT7750A)も手持ちで表面実装タイプもありましたが、PIC に合わせてリード品を実装するようにしました。

制御基板(トップ面)


 下の写真がボトム面です。実装した PIC はスルホールタイプなのでソケットから取り外して書き込みができますが、プリント基板に付けたままでも書き込みできるように PICKIT に接続するための端子用の穴を設けています。

制御基板(ボトム面)


 回路が単純なこともあり部品実装後、直ぐに動作しました。

 残りはケース設計ですが、ほぼ完成しています(下図)。下図は中身が見えるように外枠のケース本体を非表示にした状態です。
 半田ごてのコテ先を入れる部分は耐熱性能を上げるためにアルミ箔で包んでケースの外枠に取付ける予定です。この部分は缶コーヒーのアルミ缶の口の部分の使用や百均で売っている金属製のケースを利用する等、色々考えたのですが、形状の自由度を重視して3Dプリント部品をアルミ箔で包んで使用することにしました。
 同様にブラシの後方にあるコテ先から分離された半田を受ける部分もアルミ箔で覆う予定です。

半田ごて先クリーナーの内部構造(CAD画面)


★追記 2023/04/05 {
 外枠のケース本体の図を追記しました。背面は扉になっていてブラシの後方にある半田屑の受け皿の取り出しや電池交換ができるようになっています。

半田ごて先クリーナーの外観(CAD画面)
}

 最後に、ケースの外枠が無い状態ではありますが、動作確認した際の動画を貼り付けた Twitter メッセージを貼っておきます。



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー