tag:crieit.net,2005:https://crieit.net/tags/CPU/feed 「CPU」の記事 - Crieit Crieitでタグ「CPU」に投稿された最近の記事 2022-06-14T11:43:00+09:00 https://crieit.net/tags/CPU/feed tag:crieit.net,2005:PublicArticle/18199 2022-05-27T07:07:11+09:00 2022-06-14T11:43:00+09:00 https://crieit.net/posts/wzpowmod 乗算器のない8bit CPUで高速にべき乗剰余演算するコード <h1 id="目的"><a href="#%E7%9B%AE%E7%9A%84">目的</a></h1> <p>軽量で非常に良くできた<a target="_blank" rel="nofollow noopener" href="https://wzeta.idletime.tokyo/">8bit CPUのオープンソースWZeta</a>を普及させるためにRSA暗号や楕円暗号などの公開鍵暗号で使われるべき乗剰余演算のアセンブラコードをCC0ライセンス(パブリックドメインと同じ)で公開したことのお知らせ。</p> <p><strong>注意!!! CC0であるのは、べき乗剰余演算のWZetaのアセンブラコードのみ</strong></p> <h1 id="WZetaとは"><a href="#WZeta%E3%81%A8%E3%81%AF">WZetaとは</a></h1> <p>WZetaは<strong>トランジスタ数当たりの性能</strong>、命令セット内パリティ、ハードマクロ命令など8bit CPUにして新技術を多数持ち、常識を破る変則的な命令セットですが、高い効率であることが確認されつつあるCPU。</p> <h1 id="1024bitのべき乗剰余演算(事前定数有版)"><a href="#1024bit%E3%81%AE%E3%81%B9%E3%81%8D%E4%B9%97%E5%89%B0%E4%BD%99%E6%BC%94%E7%AE%97%28%E4%BA%8B%E5%89%8D%E5%AE%9A%E6%95%B0%E6%9C%89%E7%89%88%29">1024bitのべき乗剰余演算(事前定数有版)</a></h1> <pre><code>################################################################### ### WZeta powmod 1024bit 2022/05/27 by Naoki Hirayama ### ### These codes are licensed under CC0.(Public Domain) ### http://creativecommons.org/publicdomain/zero/1.0/deed.ja ### ### Montgomery multiplication method with radix 2, ### which is famous for being used in ICF3(1999). ### ### This code is for Open source 8bit CPU WZeta. ### https://wzeta.idletime.tokyo/ ### ### download WZeta simulator ### https://subnote.icf3.net/wz660/download/ ### ### How to do simulation. ### &gt; wzsim (this file) ### ################################################################### ### --------------------------------------------------------------- ### Subroutine powmod1024 y = g^x mod p ### INOUT g,r(=y) 128,128 !0x100 ### IN x,p 128,128 !0x100 ### r = R^2 mod p ### --------------------------------------------------------------- MEMORY 4 MODEL TINY ### MEMORY 8 ### MODEL HALF .PROG LD A,&powmod_gr.H ST %_b_powmod_gr,A LD A,&powmod_px.H ST %_b_powmod_px,A LD A, ^_b_powmod1024.H LD B, ^_b_powmod1024.L BAL A:B LD A,32 ST %_b_powmod_i,A LD A, &ANS.H LD B,0x80 LD C,0x00 copy_ans: # ans <- powmod_y STACP [&powmod_y:B] STACP [&powmod_y:B] STACP [&powmod_y:B] STACP [&powmod_y:B] DEC %_b_powmod_i JRZ0 ^copy_ans $PRINT &ANS 128 NOP $PRINT &powmod_exp 128 EXIT ### --------------------------------------------------------------- ### [%h:%l] =[%h:%l] * g R-1mod p ### IN %h:%l : pointer ### CONST p,g ### --------------------------------------------------------------- _b_powmod1024_mm: ST %_b_powmod_retA,A ST %_b_powmod_retB,B LD A,&_b_powmod_a.H # a = 0 LD B,&_b_powmod_a.L LD C,128 # repeat 129 LOOPZERO ZERO %_b_powmod_m _b_powmod1024_mm_loop_m: # for m=0 to 127 LD A,8 ST %_b_powmod_n,A LD A, %_b_powmod_m ADD A, %_b_powmod_l LD B,A LD A, %_b_powmod_h LD A,[A:B] ST %_b_powmod_x,A _b_powmod1024_mm_loop_n: # for n=0 to 7 ### loop body start -------------------------- LD A, %_b_powmod_x LD B, 0 AND A,[&powmod_g:B] XOR A,[&_b_powmod_a:B] ST %_b_powmod_u,A SHRC %_b_powmod_x JRC0 ^_b_powmod1024_mm2 # yi = 0 skip a += g LD B,0 # a += g CLC LD C,15 _b_powmod1024_mm1: LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] ADDC [&_b_powmod_a:B],A LOOPINC ^_b_powmod1024_mm1 INCC [&_b_powmod_a:B] _b_powmod1024_mm2: SHRC %_b_powmod_u JRC0 ^_b_powmod1024_mm4 # u=0 skip +p LD B,0 # a += p CLC LD C,15 _b_powmod1024_mm3: LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] ADDC [&_b_powmod_a:B],A LOOPINC ^_b_powmod1024_mm3 INCC [&_b_powmod_a:B] _b_powmod1024_mm4: # a >>= 1 LD A, &_b_powmod_a.H LD B,128 LD C,128 CLC LOOPSHRC ### loop body end -------------------------- DEC %_b_powmod_n JRZ0 ^_b_powmod1024_mm_loop_n INCX %_b_powmod_m # A=m++ XOR A,0x7F JRZ0 ^_b_powmod1024_mm_loop_m ### Final Substruct INC %_b_powmod_n # n=1 _b_powmod1024_mm5: LD A,32 # y=a(before sub) ST %_b_powmod_m,A # 32 = 128 / 4 LD A,%_b_powmod_h LD C,%_b_powmod_l LD B,0 _b_powmod1024_mm6: STACP [&_b_powmod_a:B] STACP [&_b_powmod_a:B] STACP [&_b_powmod_a:B] STACP [&_b_powmod_a:B] DEC %_b_powmod_m JRZ0 ^_b_powmod1024_mm6 LD C,%_b_powmod_n LOOPINC ^_b_powmod1024_mm8 # if C!=0 jump _b_powmod1024_mm7: # return LD A,%_b_powmod_retA LD B,%_b_powmod_retB JMP A:B _b_powmod1024_mm8: LD B,0 # a -= p LD A,0 SUB A,C # CF=1 LD C,31 _b_powmod1024_mm9: LD A,[&powmod_p:B] !SUBC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !SUBC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !SUBC [&_b_powmod_a:B],A LD A,[&powmod_p:B] SUBC [&_b_powmod_a:B],A LOOPINC ^_b_powmod1024_mm9 DECC [&_b_powmod_a:B] JRC0 ^_b_powmod1024_mm7 ZERO %_b_powmod_n JR ^_b_powmod1024_mm5 ### --------------------------------------------------------------- ### --------------------------------------------------------------- ### Subroutine powmod1024 ### INOUT g,r(=y) 128,128 !0x100 ### const IN x,p 128,128 !0x100 ### work _b_powmod_a 129 !0x100 ### r : R2modP ### --------------------------------------------------------------- _b_powmod1024: ST %_b_powmod_RETA,A ST %_b_powmod_RETB,B ### CALL powmod_1024mm LD A, %_b_powmod_gr # y = y(r) * g R-1mod p ST %_b_powmod_h , A LD A, 0x80 ST %_b_powmod_l , A BR ^_b_powmod1024_mm ### COPY y -&gt; g LD A, %_b_powmod_gr LD C,0x7F LD B,0xFF copy_y_g: STAC [A:B] LOOPDEC ^copy_y_g # if c--==0 jump -1 # powmod_y = 1 start LD A, %_b_powmod_gr LD B,0x80 # y LD C, 1 !ST [A:B],C # y[0] = 1 LD C,126 # repeat 127 LOOPZERO ZERO %_b_powmod_i # for i=0 to 127 powmod_loop_i: LD A,8 ST %_b_powmod_j,A # for j=0 to 7 LD A, &powmod_x.L ADD A, %_b_powmod_i LD B,A LD A,[&powmod_x:B] ST %_b_powmod_y,A powmod_loop_j: ### ### loop main ### SHRC %_b_powmod_y JRC0 ^powmod1024_lbl3 # skip yi=0 ### CALL powmod_1024mm (y*g) LD A, &powmod_y.H ST %_b_powmod_h , A LD A, &powmod_y.L ST %_b_powmod_l , A LD B, ^_b_powmod1024_mm.L BAL ^_b_powmod1024_mm:B powmod1024_lbl3: ### CALL powmod_1024mm (g*g) LD A, &powmod_g.H ST %_b_powmod_h , A LD A, &powmod_g.L ST %_b_powmod_l , A LD B, ^_b_powmod1024_mm.L BAL ^_b_powmod1024_mm:B DEC %_b_powmod_j JRZ0 ^powmod_loop_j INCX %_b_powmod_i # A=[i++] XOR A,0x7F JRZ0 ^powmod_loop_i LD A,%_b_powmod_RETA LD B,%_b_powmod_RETB JMP A:B .DATA REG 16 _reg02 ALIAS _b_powmod_gr _reg02 0 ALIAS _b_powmod_px _reg02 1 ALIAS _b_powmod_x _reg02 2 ALIAS _b_powmod_y _reg02 3 ALIAS _b_powmod_i _reg02 4 ALIAS _b_powmod_j _reg02 5 ALIAS _b_powmod_m _reg02 6 ALIAS _b_powmod_n _reg02 7 ALIAS _b_powmod_h _reg02 8 ALIAS _b_powmod_l _reg02 9 ALIAS _b_powmod_u _reg02 10 ALIAS _b_powmod_retA _reg02 11 # child sub ALIAS _b_powmod_retB _reg02 12 # child sub ALIAS _b_powmod_RETA _reg02 13 ALIAS _b_powmod_RETB _reg02 14 MEM 129 _system_work !0x100 ALIAS _b_powmod_a _system_work 0 MEM 256 powmod_gr !0x100 \ 0x3A 0x43 0xCE 0xEB 0xEC 0x52 0x88 0x94 0x4B 0x42 0x09 0xF6 0x91 0x70 0x7B 0x7F 0x25 0x1F 0xB8 0x44 0x32 0x0F 0x05 0x7F 0xF9 0xDD 0xA5 0x94 0x58 0x32 0x70 0x1E 0xCD 0x91 0x16 0xAC 0x21 0x16 0x90 0x79 0xCC 0xC2 0x66 0xC1 0x88 0x85 0x06 0x3B 0xF5 0x66 0xF2 0x31 0x89 0x74 0x2C 0x87 0x1D 0xBF 0x93 0x85 0x80 0x40 0x20 0xD3 0x18 0x47 0x16 0xE1 0xC5 0xB7 0xEB 0x70 0xF6 0xF0 0x2C 0x34 0x1A 0xBA 0xD5 0x9C 0x8C 0xA4 0xEE 0xDD 0x3C 0xD8 0xD9 0x7B 0xC4 0xA6 0x15 0xB3 0xAC 0x26 0x3D 0x45 0x21 0x7B 0x67 0x43 0xA7 0x63 0x16 0x7B 0x83 0x3C 0x1B 0xAE 0x6A 0x8F 0x9E 0x49 0xBE 0x99 0x01 0x92 0x1A 0xDE 0x6A 0xC5 0x7B 0x48 0xBA 0xF9 0x0A 0x29 0x82 0x46 0x3E 0x9C 0xD5 0x81 0xDB 0xC7 0x70 0xFD 0xEB 0x6C 0x52 0x37 0x07 0xF8 0x61 0x3F 0x79 0x31 0x57 0x32 0xC4 0x44 0x51 0x54 0x10 0x14 0x98 0x82 0x6B 0x0D 0xE5 0x50 0xA8 0xC0 0xC2 0x11 0x48 0xF1 0x38 0x4B 0x86 0xAC 0xF0 0xA5 0x34 0x37 0x52 0x67 0x89 0x88 0x93 0x4A 0x08 0x1E 0x92 0x17 0xE5 0x15 0xE5 0x14 0xB9 0x0C 0xCE 0x89 0xC7 0x0F 0x92 0xC5 0x1C 0xA3 0xF6 0x77 0xB8 0x88 0x50 0xF0 0x57 0xC8 0x62 0xED 0x34 0x89 0xE8 0x33 0xD2 0x22 0x6D 0x1B 0x45 0xC7 0xEB 0x84 0x32 0x13 0x18 0x84 0x84 0x69 0x24 0xD5 0x87 0xC0 0x5D 0x82 0xE8 0x55 0x2A 0x1A 0x77 0xEC 0x04 0xA5 0x21 0x86 0x16 0x04 0x25 0x9D 0x6D 0x66 0x11 0x9A 0x0E 0xBD 0xA9 0xB1 0xD1 0x4A ALIAS powmod_g powmod_gr 0x00 ALIAS powmod_y powmod_gr 0x80 # = R2modP MEM 256 powmod_px !0x100 \ 0xA1 0x63 0xD2 0x90 0x0B 0xD0 0x3A 0xAC 0xB4 0x15 0x75 0xEA 0x5E 0x05 0x57 0x86 0x55 0x12 0x36 0xE2 0xF8 0x07 0xCD 0x3E 0xE5 0x65 0x6E 0x70 0xE0 0x57 0xAE 0x5E 0x2D 0x21 0x53 0xE1 0xF0 0xC4 0xE5 0x96 0xB9 0x83 0xB3 0x5C 0x37 0xE2 0x3C 0x54 0xBF 0xF7 0x0F 0x4A 0xD8 0x19 0x2C 0xCA 0x3C 0xCA 0xD9 0x28 0xC3 0x76 0x75 0x5B 0x13 0x93 0xA3 0xC4 0x98 0x4E 0x6B 0x99 0x33 0x79 0xDC 0xCE 0x9C 0xB0 0xE8 0xBA 0x71 0xCD 0x27 0x5E 0xFA 0x8D 0xB0 0x7C 0x08 0xCF 0xF6 0x24 0x1B 0xD4 0xDA 0xCC 0x09 0x27 0x72 0x9C 0x5F 0x8D 0x08 0x6D 0x95 0x33 0x28 0xEE 0xAF 0x5D 0xED 0xB2 0x6E 0xB0 0xC3 0xE4 0xA3 0x70 0x4E 0x6B 0xF2 0xF9 0x6E 0x9C 0x4F 0xAB 0xFB 0xD8 0xC0 0xFA 0x69 0x4E 0x7C 0xBF 0x6D 0x94 0x18 0xE7 0x5C 0xB7 0xE8 0xE2 0xF4 0xCB 0x4B 0x75 0x3B 0x93 0x78 0x55 0xFC 0x0A 0x0D 0x00 0xEE 0xFE 0x16 0x0A 0x1D 0xAF 0x28 0xD0 0x9B 0xF2 0x09 0x4B 0x31 0xDE 0xF5 0x54 0x0E 0xCD 0xFE 0x4E 0x98 0x73 0x31 0x07 0x7E 0x90 0x1E 0xC6 0x98 0xD0 0xD8 0x1F 0xE8 0x0B 0x34 0xB7 0xFF 0x73 0x4A 0x86 0x82 0x48 0x20 0x52 0x9C 0x57 0xD4 0x38 0x5F 0x8F 0x43 0x33 0xB6 0x91 0xC1 0x14 0x5D 0xA6 0xAF 0x7B 0x13 0xA8 0xFB 0x89 0xAC 0xC8 0xFA 0x40 0x1F 0x21 0x14 0x7C 0xE7 0x64 0xCE 0xFF 0x48 0x49 0x7F 0xFD 0x9B 0x1A 0xA5 0x97 0x42 0x4A 0x94 0xB9 0xD6 0x70 0x83 0x38 0xAE 0xB3 0x78 0xBF 0xA6 0x48 0x24 0x4D 0x81 0x8C ALIAS powmod_p powmod_px 0x00 ALIAS powmod_x powmod_px 0x80 MEM 128 ANS &0xF00 MEM 128 powmod_exp \ 0xB4 0xBB 0x5B 0xB6 0x58 0x7A 0x9D 0x7A 0xEB 0x1C 0xE9 0x79 0xBF 0x94 0xF6 0x60 0x57 0x37 0x87 0x60 0x20 0x85 0xB3 0xB6 0xDD 0x9B 0xF4 0xA5 0xD8 0xFA 0x4C 0xC6 0xAD 0x84 0x39 0xCC 0xEC 0xD3 0xDD 0x23 0x86 0x4A 0x2C 0x50 0x93 0xEC 0xD6 0xAD 0x0D 0xD6 0xC4 0xBC 0xA1 0xD7 0x36 0x4F 0x2A 0x80 0x3F 0xC3 0x0C 0x0F 0xCD 0x4F 0x6C 0x6D 0xF1 0x5F 0x3D 0x58 0xAF 0xB5 0x1A 0x5B 0x85 0xF4 0xB8 0x77 0x11 0xD0 0x48 0x94 0xD7 0xC4 0xFF 0xFD 0x21 0xC1 0x41 0xA4 0x34 0xBB 0xC3 0x01 0x3A 0x36 0x4A 0x30 0xC3 0x3E 0x91 0xB2 0x86 0x2E 0x82 0xB0 0x87 0x63 0x81 0xCF 0x9E 0x33 0xC0 0x22 0x73 0x3B 0x05 0x95 0x8D 0xEA 0x80 0xA1 0xEE 0x33 0x47 0xD7 0xF2 0x84 </code></pre> <h1 id="解説(事前定数有版)"><a href="#%E8%A7%A3%E8%AA%AC%28%E4%BA%8B%E5%89%8D%E5%AE%9A%E6%95%B0%E6%9C%89%E7%89%88%29">解説(事前定数有版)</a></h1> <pre><code>y = g ^ x mod p ( r: R^2 mod p ) </code></pre> <p>rはpの値によって決まるモンゴメリ乗算の事前定数。モンゴメリ乗算の基数2は<a target="_blank" rel="nofollow noopener" href="https://openicf3.idletime.tokyo/">ICF3(1999年)</a>でも使われていました。1024bitべき乗剰余演算のサブルーチンの入力パラメータは256バイトのブロック2個。powmod_grとpowmod_pxです。grは前半128バイトがg、後半128バイトがr。 pxは前半128バイトがp(奇数)、後半128バイトがx。サブルーチンが終了するとrの場所に演算結果yが入っています。</p> <h1 id="1024bitのべき乗剰余演算(事前定数無版)"><a href="#1024bit%E3%81%AE%E3%81%B9%E3%81%8D%E4%B9%97%E5%89%B0%E4%BD%99%E6%BC%94%E7%AE%97%28%E4%BA%8B%E5%89%8D%E5%AE%9A%E6%95%B0%E7%84%A1%E7%89%88%29">1024bitのべき乗剰余演算(事前定数無版)</a></h1> <pre><code>################################################################### ### WZeta powmod 1024bit 2022/06/10 by Naoki Hirayama ### ### These codes are licensed under CC0.(Public Domain) ### http://creativecommons.org/publicdomain/zero/1.0/deed.ja ### ### Montgomery multiplication method with radix 2, ### which is famous for being used in ICF3(1999). ### ### This code is for Open source 8bit CPU WZeta. ### https://wzeta.idletime.tokyo/ ### ### download WZeta simulator ### https://subnote.icf3.net/wz660/download/ ### ### How to do simulation. ### &gt; wzsim (this file) ### ################################################################### ### --------------------------------------------------------------- ### Subroutine powmod1024 y = g^x mod p ### INOUT g,y 128,128 !0x100 ### IN x,p 128,128 !0x100 ### --------------------------------------------------------------- MEMORY 4 MODEL TINY ### MEMORY 8 ### MODEL HALF .PROG LD A,&powmod_gy.H ST %_b_powmod_gy,A LD A,&powmod_px.H ST %_b_powmod_px,A LD A, ^_b_powmod1024.H LD B, ^_b_powmod1024.L BAL A:B LD A,32 ST %_b_powmod_i,A LD A, &ANS.H LD B,0x80 LD C,0x00 copy_ans: # ans <- powmod_y STACP [&powmod_y:B] STACP [&powmod_y:B] STACP [&powmod_y:B] STACP [&powmod_y:B] DEC %_b_powmod_i JRZ0 ^copy_ans $PRINT &ANS 128 NOP $PRINT &powmod_exp 128 EXIT ### --------------------------------------------------------------- ### [%h:%l] =[%h:%l] * g R-1mod p ### IN %h:%l : pointer ### CONST p,g ### --------------------------------------------------------------- _b_powmod1024_mm: ST %_b_powmod_retA,A ST %_b_powmod_retB,B LD A,&_b_powmod_a.H # a = 0 LD B,&_b_powmod_a.L LD C,128 # repeat 129 LOOPZERO ZERO %_b_powmod_m _b_powmod1024_mm_loop_m: # for m=0 to 127 LD A,8 ST %_b_powmod_n,A LD A, %_b_powmod_m ADD A, %_b_powmod_l LD B,A LD A, %_b_powmod_h LD A,[A:B] ST %_b_powmod_x,A _b_powmod1024_mm_loop_n: # for n=0 to 7 ### loop body start -------------------------- LD A, %_b_powmod_x LD B, 0 AND A,[&powmod_g:B] XOR A,[&_b_powmod_a:B] ST %_b_powmod_u,A SHRC %_b_powmod_x JRC0 ^_b_powmod1024_mm2 # yi = 0 skip a += g LD B,0 # a += g CLC LD C,15 _b_powmod1024_mm1: LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_g:B] ADDC [&_b_powmod_a:B],A LOOPINC ^_b_powmod1024_mm1 INCC [&_b_powmod_a:B] _b_powmod1024_mm2: SHRC %_b_powmod_u JRC0 ^_b_powmod1024_mm4 # u=0 skip +p LD B,0 # a += p CLC LD C,15 _b_powmod1024_mm3: LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !ADDC [&_b_powmod_a:B],A LD A,[&powmod_p:B] ADDC [&_b_powmod_a:B],A LOOPINC ^_b_powmod1024_mm3 INCC [&_b_powmod_a:B] _b_powmod1024_mm4: # a >>= 1 LD A, &_b_powmod_a.H LD B,128 LD C,128 CLC LOOPSHRC ### loop body end -------------------------- DEC %_b_powmod_n JRZ0 ^_b_powmod1024_mm_loop_n INCX %_b_powmod_m # A=m++ XOR A,0x7F JRZ0 ^_b_powmod1024_mm_loop_m ### Final Substruct INC %_b_powmod_n # n=1 _b_powmod1024_mm5: LD A,32 # y=a(before sub) ST %_b_powmod_m,A # 32 = 128 / 4 LD A,%_b_powmod_h LD C,%_b_powmod_l LD B,0 _b_powmod1024_mm6: STACP [&_b_powmod_a:B] STACP [&_b_powmod_a:B] STACP [&_b_powmod_a:B] STACP [&_b_powmod_a:B] DEC %_b_powmod_m JRZ0 ^_b_powmod1024_mm6 LD C,%_b_powmod_n LOOPINC ^_b_powmod1024_mm8 # if C!=0 jump _b_powmod1024_mm7: # return LD A,%_b_powmod_retA LD B,%_b_powmod_retB JMP A:B _b_powmod1024_mm8: LD B,0 # a -= p LD A,0 SUB A,C # CF=1 LD C,31 _b_powmod1024_mm9: LD A,[&powmod_p:B] !SUBC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !SUBC [&_b_powmod_a:B],A LD A,[&powmod_p:B] !SUBC [&_b_powmod_a:B],A LD A,[&powmod_p:B] SUBC [&_b_powmod_a:B],A LOOPINC ^_b_powmod1024_mm9 DECC [&_b_powmod_a:B] JRC0 ^_b_powmod1024_mm7 ZERO %_b_powmod_n JR ^_b_powmod1024_mm5 ### --------------------------------------------------------------- ### --------------------------------------------------------------- ### Subroutine powmod1024 ### INOUT g,y 128,128 !0x100 ### const IN x,p 128,128 !0x100 ### work _b_powmod_a 129 !0x100 ### --------------------------------------------------------------- _b_powmod1024: ST %_b_powmod_RETA,A ST %_b_powmod_RETB,B ### g = gR mod p LD A,4 ST %_b_powmod_i,A # for i=4 to 1 ZERO %_b_powmod_j # for j=0 to 255 powmod_loop_gi: ### always %_b_powmod_j = 0 powmod_loop_gj: LD A,&powmod_g.H # g<<=1 LD B,0 LD C,0x7F CLC LOOPSHLC GETFLAG [0] JRC1 ^_b_powmod1024_lbl1 # skip copy LD A,&_b_powmod_a.H # copy a <- g LD B,0 LD C,0x7F _b_powmod1024_loop1: STAB [&powmod_g:B] LOOPINC ^_b_powmod1024_loop1 _b_powmod1024_lbl1: LD B,0 LD A,[&powmod_p:B] SUB [&powmod_g:B],A !LD C,126 _b_powmod1024_loop2: LD A,[&powmod_p:B] SUBC [&powmod_g:B],A LOOPINC ^_b_powmod1024_loop2 JRC1 ^_b_powmod1024_lbl2 SHL [0] JRC1 ^_b_powmod1024_lbl2 LD A,&powmod_g.H # copy g <- a LD B,0 LD C,0x7F _b_powmod1024_loop3: STAB [&_b_powmod_a:B] LOOPINC ^_b_powmod1024_loop3 _b_powmod1024_lbl2: DEC %_b_powmod_j JRZ0 ^powmod_loop_gj DEC %_b_powmod_i JRZ0 ^powmod_loop_gi # powmod_y = 1 start LD A, %_b_powmod_gy LD B,0x80 # y LD C, 1 !ST [A:B],C # y[0] = 1 LD C,126 # repeat 127 LOOPZERO ZERO %_b_powmod_i # for i=0 to 127 powmod_loop_i: LD A,8 ST %_b_powmod_j,A # for j=0 to 7 LD A, &powmod_x.L ADD A, %_b_powmod_i LD B,A LD A,[&powmod_x:B] ST %_b_powmod_y,A powmod_loop_j: ### ### loop main ### SHRC %_b_powmod_y JRC0 ^powmod1024_lbl3 # skip yi=0 ### CALL powmod_1024mm (y*g) LD A, &powmod_y.H ST %_b_powmod_h , A LD A, &powmod_y.L ST %_b_powmod_l , A LD B, ^_b_powmod1024_mm.L BAL ^_b_powmod1024_mm:B powmod1024_lbl3: ### CALL powmod_1024mm (g*g) LD A, &powmod_g.H ST %_b_powmod_h , A LD A, &powmod_g.L ST %_b_powmod_l , A LD B, ^_b_powmod1024_mm.L BAL ^_b_powmod1024_mm:B DEC %_b_powmod_j JRZ0 ^powmod_loop_j INCX %_b_powmod_i # A=[i++] XOR A,0x7F JRZ0 ^powmod_loop_i LD A,%_b_powmod_RETA LD B,%_b_powmod_RETB JMP A:B .DATA REG 16 _reg02 ALIAS _b_powmod_gy _reg02 0 ALIAS _b_powmod_px _reg02 1 ALIAS _b_powmod_x _reg02 2 ALIAS _b_powmod_y _reg02 3 ALIAS _b_powmod_i _reg02 4 ALIAS _b_powmod_j _reg02 5 ALIAS _b_powmod_m _reg02 6 ALIAS _b_powmod_n _reg02 7 ALIAS _b_powmod_h _reg02 8 ALIAS _b_powmod_l _reg02 9 ALIAS _b_powmod_u _reg02 10 ALIAS _b_powmod_retA _reg02 11 # child sub ALIAS _b_powmod_retB _reg02 12 # child sub ALIAS _b_powmod_RETA _reg02 13 ALIAS _b_powmod_RETB _reg02 14 MEM 129 _system_work !0x100 ALIAS _b_powmod_a _system_work 0 MEM 256 powmod_gy &0xE00 \ 0x3A 0x43 0xCE 0xEB 0xEC 0x52 0x88 0x94 0x4B 0x42 0x09 0xF6 0x91 0x70 0x7B 0x7F 0x25 0x1F 0xB8 0x44 0x32 0x0F 0x05 0x7F 0xF9 0xDD 0xA5 0x94 0x58 0x32 0x70 0x1E 0xCD 0x91 0x16 0xAC 0x21 0x16 0x90 0x79 0xCC 0xC2 0x66 0xC1 0x88 0x85 0x06 0x3B 0xF5 0x66 0xF2 0x31 0x89 0x74 0x2C 0x87 0x1D 0xBF 0x93 0x85 0x80 0x40 0x20 0xD3 0x18 0x47 0x16 0xE1 0xC5 0xB7 0xEB 0x70 0xF6 0xF0 0x2C 0x34 0x1A 0xBA 0xD5 0x9C 0x8C 0xA4 0xEE 0xDD 0x3C 0xD8 0xD9 0x7B 0xC4 0xA6 0x15 0xB3 0xAC 0x26 0x3D 0x45 0x21 0x7B 0x67 0x43 0xA7 0x63 0x16 0x7B 0x83 0x3C 0x1B 0xAE 0x6A 0x8F 0x9E 0x49 0xBE 0x99 0x01 0x92 0x1A 0xDE 0x6A 0xC5 0x7B 0x48 0xBA 0xF9 0x0A 0x29 0x82 0x46 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ALIAS powmod_g powmod_gy 0x00 ALIAS powmod_y powmod_gy 0x80 MEM 256 powmod_px &0xD00 \ 0xA1 0x63 0xD2 0x90 0x0B 0xD0 0x3A 0xAC 0xB4 0x15 0x75 0xEA 0x5E 0x05 0x57 0x86 0x55 0x12 0x36 0xE2 0xF8 0x07 0xCD 0x3E 0xE5 0x65 0x6E 0x70 0xE0 0x57 0xAE 0x5E 0x2D 0x21 0x53 0xE1 0xF0 0xC4 0xE5 0x96 0xB9 0x83 0xB3 0x5C 0x37 0xE2 0x3C 0x54 0xBF 0xF7 0x0F 0x4A 0xD8 0x19 0x2C 0xCA 0x3C 0xCA 0xD9 0x28 0xC3 0x76 0x75 0x5B 0x13 0x93 0xA3 0xC4 0x98 0x4E 0x6B 0x99 0x33 0x79 0xDC 0xCE 0x9C 0xB0 0xE8 0xBA 0x71 0xCD 0x27 0x5E 0xFA 0x8D 0xB0 0x7C 0x08 0xCF 0xF6 0x24 0x1B 0xD4 0xDA 0xCC 0x09 0x27 0x72 0x9C 0x5F 0x8D 0x08 0x6D 0x95 0x33 0x28 0xEE 0xAF 0x5D 0xED 0xB2 0x6E 0xB0 0xC3 0xE4 0xA3 0x70 0x4E 0x6B 0xF2 0xF9 0x6E 0x9C 0x4F 0xAB 0xFB 0xD8 0xC0 0xFA 0x69 0x4E 0x7C 0xBF 0x6D 0x94 0x18 0xE7 0x5C 0xB7 0xE8 0xE2 0xF4 0xCB 0x4B 0x75 0x3B 0x93 0x78 0x55 0xFC 0x0A 0x0D 0x00 0xEE 0xFE 0x16 0x0A 0x1D 0xAF 0x28 0xD0 0x9B 0xF2 0x09 0x4B 0x31 0xDE 0xF5 0x54 0x0E 0xCD 0xFE 0x4E 0x98 0x73 0x31 0x07 0x7E 0x90 0x1E 0xC6 0x98 0xD0 0xD8 0x1F 0xE8 0x0B 0x34 0xB7 0xFF 0x73 0x4A 0x86 0x82 0x48 0x20 0x52 0x9C 0x57 0xD4 0x38 0x5F 0x8F 0x43 0x33 0xB6 0x91 0xC1 0x14 0x5D 0xA6 0xAF 0x7B 0x13 0xA8 0xFB 0x89 0xAC 0xC8 0xFA 0x40 0x1F 0x21 0x14 0x7C 0xE7 0x64 0xCE 0xFF 0x48 0x49 0x7F 0xFD 0x9B 0x1A 0xA5 0x97 0x42 0x4A 0x94 0xB9 0xD6 0x70 0x83 0x38 0xAE 0xB3 0x78 0xBF 0xA6 0x48 0x24 0x4D 0x81 0x8C ALIAS powmod_p powmod_px 0x00 ALIAS powmod_x powmod_px 0x80 MEM 128 ANS &0xF00 MEM 128 powmod_exp \ 0xB4 0xBB 0x5B 0xB6 0x58 0x7A 0x9D 0x7A 0xEB 0x1C 0xE9 0x79 0xBF 0x94 0xF6 0x60 0x57 0x37 0x87 0x60 0x20 0x85 0xB3 0xB6 0xDD 0x9B 0xF4 0xA5 0xD8 0xFA 0x4C 0xC6 0xAD 0x84 0x39 0xCC 0xEC 0xD3 0xDD 0x23 0x86 0x4A 0x2C 0x50 0x93 0xEC 0xD6 0xAD 0x0D 0xD6 0xC4 0xBC 0xA1 0xD7 0x36 0x4F 0x2A 0x80 0x3F 0xC3 0x0C 0x0F 0xCD 0x4F 0x6C 0x6D 0xF1 0x5F 0x3D 0x58 0xAF 0xB5 0x1A 0x5B 0x85 0xF4 0xB8 0x77 0x11 0xD0 0x48 0x94 0xD7 0xC4 0xFF 0xFD 0x21 0xC1 0x41 0xA4 0x34 0xBB 0xC3 0x01 0x3A 0x36 0x4A 0x30 0xC3 0x3E 0x91 0xB2 0x86 0x2E 0x82 0xB0 0x87 0x63 0x81 0xCF 0x9E 0x33 0xC0 0x22 0x73 0x3B 0x05 0x95 0x8D 0xEA 0x80 0xA1 0xEE 0x33 0x47 0xD7 0xF2 0x84 </code></pre> <h1 id="解説(事前定数無版)"><a href="#%E8%A7%A3%E8%AA%AC%28%E4%BA%8B%E5%89%8D%E5%AE%9A%E6%95%B0%E7%84%A1%E7%89%88%29">解説(事前定数無版)</a></h1> <pre><code>y = g ^ x mod p </code></pre> <p>モンゴメリ乗算の基数2は<a target="_blank" rel="nofollow noopener" href="https://openicf3.idletime.tokyo/">ICF3(1999年)</a>でも使われていました。1024bitべき乗剰余演算のサブルーチンの入力パラメータは256バイトのブロック2個。powmod_gyとpowmod_pxです。gyは前半128バイトがg、後半128バイトは演算結果。 pxは前半128バイトがp(奇数)、後半128バイトがx。</p> <h1 id="実行環境"><a href="#%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83">実行環境</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://subnote.icf3.net/wz660/download.html">WZetaシミュレータ</a>で実際に演算させてみることが可能です。</p> <pre><code>> wzsim (アセンブラのファイル) </code></pre> <p><strong>注意 シミュレータにはC言語実装のシミュレータとverilogのバイナリがあります。verilogでは1024bitのべき乗剰余演算に1週間以上かかることもあるので、ご注意ください。</strong></p> <h1 id="実行結果"><a href="#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C">実行結果</a></h1> <p>実行後、演算が終了すると演算結果に続いて期待値が表示されます。期待値はコードの最後にあるpowmod_expの値が、そのまま表示されます。</p> <h1 id="性能について"><a href="#%E6%80%A7%E8%83%BD%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">性能について</a></h1> <p>乗算命令が無いため8bitの加算器1個で演算しています。絶対時間では非常に遅いため軽量な楕円暗号か、数時間の演算時間が許容されるIoTシステムなどでの利用に向いています。BIOSを通してアプリを作成すればアプリを改変することなく超高速な<a target="_blank" rel="nofollow noopener" href="https://snakecube.idletime.tokyo/">暗号プロセッサSnakeCube</a>に置き換えられることを考えているため、性能が必要になったところで、暗号プロセッサSnakeCubeに置き換えることが可能になる予想です。シミュレータの実行終了後、命令数が表示されます。WZetaのSDogコアでは1命令4サイクルなので命令数を4倍して周波数を計算すると1024bitのべき乗剰余演算1回の時間が求まります。値に依存しますが、上記、サンプルコードでは666530315命令。CPUの周波数に8MHzを想定した場合、1サイクル125[ns]なので<br /> 666530315 × 4 × 125 ÷ 10^9 ≒ 333秒 ( 512bitのべき乗剰余演算だと約42秒 )</p> <h1 id="脆弱性対策"><a href="#%E8%84%86%E5%BC%B1%E6%80%A7%E5%AF%BE%E7%AD%96">脆弱性対策</a></h1> <p>今回のコードは脆弱性対策の無い単純に最も高速なプログラムになっています。また最上位ビットを高速モードとして使っています。サイドチャネル攻撃を対策をするには値に依存しないようにダミーの計算時間を入れます。WZetaの命令セットはオペコードに依存せずメモリアクセスをするという低消費電力でない特性がありますが、これが電力解析などのサイドチャネル攻撃への耐性を高めることにもなっています。トランジスタ数が少ないのでオペコードに依存しない動作で0、1の切り替えが多くなったとしても、全体としての消費電力は少ないという予想です。</p> spinlock tag:crieit.net,2005:PublicArticle/17191 2021-05-19T14:20:49+09:00 2021-05-19T14:21:14+09:00 https://crieit.net/posts/7f7e03b7271977ac7674f9f425a886b3 サーバハードウェア(パーツ)ざっくりまとめ <h1 id="サーバハードウェアのパーツ"><a href="#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%8F%E3%83%BC%E3%83%89%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E3%83%91%E3%83%BC%E3%83%84">サーバハードウェアのパーツ</a></h1> <p>コンピュータアーキテクチャで7個くらいあったけど、ここでは<br /> 1.CPU<br /> 2.メモリ<br /> 3.ディスク<br /> の3個についてまとめる</p> <h1 id="CPU"><a href="#CPU">CPU</a></h1> <p>主に演算を担当しているパーツ<br /> 処理性能を左右する要素が3つある</p> <h2 id="1.クロック周波数と世代"><a href="#1.%E3%82%AF%E3%83%AD%E3%83%83%E3%82%AF%E5%91%A8%E6%B3%A2%E6%95%B0%E3%81%A8%E4%B8%96%E4%BB%A3">1.クロック周波数と世代</a></h2> <p>クロック周波数が高ければ高いほど処理速度が上がる<br /> また、<strong>同じ周波数でも世代が新しい物の方が性能は上</strong></p> <h2 id="2.コア数"><a href="#2.%E3%82%B3%E3%82%A2%E6%95%B0">2.コア数</a></h2> <p>CPUの核になる部分。<br /> 基本数が多ければ多いほど並列処理の性能が上がる</p> <h2 id="3.キャッシュメモリ"><a href="#3.%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%83%A1%E3%83%A2%E3%83%AA">3.キャッシュメモリ</a></h2> <p>アクセスしたいデータの一部をCPUの内部に保存できる場所<br /> ここに保存されてるデータにアクセスするとき早くなる。<br /> 大きいほうがいい。サーバのはPCよりでかい。</p> <h1 id="メモリ(主記憶装置)"><a href="#%E3%83%A1%E3%83%A2%E3%83%AA%EF%BC%88%E4%B8%BB%E8%A8%98%E6%86%B6%E8%A3%85%E7%BD%AE%EF%BC%89">メモリ(主記憶装置)</a></h1> <p>キャッシュメモリに入りきらないデータを入れる場所<br /> ディスクより処理が早くキャッシュメモリより低速<br /> メモリは<strong>容量が大きいほうがいい</strong><br /> データのエラーを検出、訂正ができる</p> <h3 id="ECC(Error Correction Code)"><a href="#ECC%28Error+Correction+Code%29">ECC(Error Correction Code)</a></h3> <p>機能搭載が一般的</p> <h1 id="ディスク"><a href="#%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF">ディスク</a></h1> <p>OS、アプリケーションプログラム、データを格納する装置<br /> 電源を切ってもデータは消えないが処理速度は遅い<br /> <strong>2種類ある</strong></p> <p>①ハードディスク<br /> 磁気でデータを記録するディスク<br /> ハードディスクの中でまた二つの種類がある<br /> ①-1SATAハードディスク<br /> PC用。一日<strong>8時間程度の稼働</strong>を想定している。<br /> 安くて大容量だけど<strong>遅い</strong><br /> ①-2SASハードディスク<br /> サーバ用。365日24時間稼働を想定<br /> SSDより安くSATAより高速</p> <p>②SSD<br /> 半導体でデータを記録するディスク<br /> ②-1SSD(Solid State Drive)<br /> SATA、SAS、<strong>NVMe</strong>の接続規格に対応したものがある<br /> ハードディスクより<strong>かなり高価</strong>だけど<strong>圧倒的に速い</strong></p> tobara tag:crieit.net,2005:PublicArticle/16851 2021-04-16T04:38:28+09:00 2023-12-06T18:30:01+09:00 https://crieit.net/posts/relay-logic-circuit-simulator-1bit-cpu リレー式論理回路シミュレータを自作して1bit CPUまで動かした <ul> <li>「1bit CPU」というのは、書籍『CPUの創りかた』に載っている「オリジナルCPU 試作3号機(エレキ式)」のことです。</li> <li>※ ブログに書いていた記事のクロス投稿です。元の公開日は 2020-05-03 です。</li> </ul> <h1 id="概要"><a href="#%E6%A6%82%E8%A6%81">概要</a></h1> <p>リポジトリ:<br /> <a target="_blank" rel="nofollow noopener" href="https://github.com/sonota88/kairo-gokko">https://github.com/sonota88/kairo-gokko</a></p> <p>デモ(ブラウザで動かせます):<br /> <a target="_blank" rel="nofollow noopener" href="https://sonota88.github.io/kairo-gokko/pages/39/index.html">https://sonota88.github.io/kairo-gokko/pages/39/index.html</a></p> <ul> <li>音量を小さめにしていますが、音が出ます</li> <li>表示サイズや負荷の関係でPCブラウザ推奨です <ul> <li>とりあえず富豪的に作っていて、まだ最適化などやってません</li> </ul></li> <li>最初は発振するので、スイッチを適当に操作して発振を止める必要があります。操作については<a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/entry/2020/04/12/094629">こちら</a>も参照してください。</li> </ul> <hr /> <p>製作過程のメモ(どういうステップを踏んで何を実装していったか、具体的な話はこっちにまとめています):<br /> <a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/entry/2020/04/21/065800">https://memo88.hatenablog.com/entry/2020/04/21/065800</a></p> <hr /> <p>動かしている様子です。</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/5a779825-a252-aad1-2aab-7d51fd708363.gif" alt="x00_1bit_cpu.gif" /></p> <p>左下のスイッチがクロックで、右下のスイッチで命令( <code>MOV A, A</code> と <code>NOT A</code> )を切り替えています。</p> <hr /> <p>回路図を描いて動かすまでの流れ:</p> <ul> <li>回路図を LibreOffice Draw で描いて <code>.fodg</code> 形式で保存</li> <li>fodg ファイルを読んで前処理し、中間データ(JSON)に変換</li> <li>シミュレータのプログラムと中間データを使ってブラウザで実行</li> </ul> <p>LibreOffice Draw で描いた回路図はこんな感じ。</p> <p><a href="https://crieit.now.sh/upload_images/1649cf3b27696c4991dcb814567a0522607893c592e6a.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/1649cf3b27696c4991dcb814567a0522607893c592e6a.png?mw=700" alt="image" /></a></p> <p>直線と矩形、矩形内のテキストだけです。部品はグリッドに合わせて配置します。ナナメの配線は禁止。</p> <hr /> <p>使っている部品:</p> <ul> <li>導線<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/efabd580-0a0f-8416-6f0d-40726d049b25.png" alt="image.png" /></li> <li>電池のプラス極・マイナス極<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/6b688ff5-4cba-7f71-97b9-6389c156dfb9.png" alt="image.png" /></li> <li>ランプ<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/f5f8fb2e-f463-4c52-ca30-3a1524ac5de1.png" alt="image.png" /></li> <li>スイッチ。マウスでクリックすると ON/OFF が切り替わります。<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/31b10750-be58-028c-f8d7-d7b1171b9232.png" alt="image.png" /></li> <li>リレー(2種類)<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/bc167c9e-ce38-fa7b-8801-bce4c74a5f95.png" alt="image.png" /></li> </ul> <p>ランプ、リレーには極性なし(プラス極・マイナス極を入れ替えても動作は変わらない)</p> <hr /> <p>小さい回路の例をいくつか:</p> <p>NOT(を3つ繋げたもの)<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/0d1eca62-ac93-db69-6edd-c3231e72d81d.gif" alt="x01_not.gif" /></p> <p>NAND<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/068b2a43-015f-7c83-b368-fd8a2967ca1f.gif" alt="x02_nand.gif" /></p> <p>XOR<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/9f42f922-272f-800c-2978-47eea147aaba.gif" alt="x03_xor.gif" /></p> <p>RSフリップフロップ<br /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/34bb8ab3-60ad-679d-2fbf-950164903d1e.gif" alt="x04_rsff.gif" /></p> <hr /> <p>ほぼ Ruby 製。ブラウザで動かす部分は <a target="_blank" rel="nofollow noopener" href="https://github.com/yhara/dxopal">DXOpal</a> を使っています。</p> <p><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234055/6902942b-3509-c3f6-46aa-2d96e0380459.png" alt="image.png" /></p> <p>(一応残してあるが)不要になっている部分、補助ツール的なスクリプト、コメントなどを除くと主な部分は 2000行弱(2021-04-11 時点)。途中いろいろありましたができあがってみると意外と小さい。</p> <pre><code>$ wc -l *.rb 283 child_circuit.rb 456 circuit.rb 114 drawer_dxopal.rb 137 libo_draw.rb 237 main.rb 26 preprocess.rb 307 unit.rb 346 view.rb 1906 合計 </code></pre> <h1 id="製作期間"><a href="#%E8%A3%BD%E4%BD%9C%E6%9C%9F%E9%96%93">製作期間</a></h1> <p>2019-12-31 〜 2020-02-02<br /> (プロトタイプを作り始めてから 1bit CPU が動くまで)</p> <p>始める前からいろいろ調べたりはしていて、書き始めたのが 12/31 だったか 12/30 だったか。</p> <p>回路図エディタの部分を <a target="_blank" rel="nofollow noopener" href="https://qiita.com/sonota88/items/4c280ac13b7f7709abeb">LibreOffice Draw に丸投げ</a>することにより、製作期間を短縮しシミュレータ部分に集中することができました。</p> <h1 id="どのくらいの電気の知識で始めたか"><a href="#%E3%81%A9%E3%81%AE%E3%81%8F%E3%82%89%E3%81%84%E3%81%AE%E9%9B%BB%E6%B0%97%E3%81%AE%E7%9F%A5%E8%AD%98%E3%81%A7%E5%A7%8B%E3%82%81%E3%81%9F%E3%81%8B">どのくらいの電気の知識で始めたか</a></h1> <ul> <li>小学校、中学校の理科レベル <ul> <li>電池、エナメル線、豆電球、電磁石、直列・並列つなぎ</li> </ul></li> <li>大学の頃にちょっとだけ電子工作やろうとするも鉱石ラジオ作った程度で終わった</li> <li>『CPUの創りかた』のうっすらした記憶</li> <li>リレーは名前は聞いたことあったけどどういうものか知らなかった</li> <li>トランジスタの前は真空管を使っていたらしい</li> <li>GND って何?</li> </ul> <p>……という程度。</p> <h1 id="コンセプト・方針"><a href="#%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88%E3%83%BB%E6%96%B9%E9%87%9D">コンセプト・方針</a></h1> <ul> <li>ガチャガチャ動く機械仕掛けのおもちゃ</li> <li>ピタゴラ装置みたいなの</li> <li>電圧や抵抗は考慮しない <ul> <li>難しそうなので</li> <li>電気が流れているか、流れていないかだけ考える</li> </ul></li> <li>小学校の理科の工作の延長程度のもの</li> <li>なるべく寄り道せずに曳光弾を通す <ul> <li>遅すぎて辛い、ということがなければ最適化は後回し</li> <li>そもそも作れるのか、(論理)回路を動かすには最低限何が必要なのかなど、よく分かっていなかった</li> </ul></li> </ul> <h1 id="なぜ作ったか / 作り始めるまでの経緯"><a href="#%E3%81%AA%E3%81%9C%E4%BD%9C%E3%81%A3%E3%81%9F%E3%81%8B+%2F+%E4%BD%9C%E3%82%8A%E5%A7%8B%E3%82%81%E3%82%8B%E3%81%BE%E3%81%A7%E3%81%AE%E7%B5%8C%E7%B7%AF">なぜ作ったか / 作り始めるまでの経緯</a></h1> <p>並行してボンヤリと考えていたのですっきりまとめることができませんが、思い出して雑に書き出してみました。</p> <p>列挙の順序も適当です。</p> <h2 id="そもそもは『CPUの創りかた』"><a href="#%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E3%81%AF%E3%80%8ECPU%E3%81%AE%E5%89%B5%E3%82%8A%E3%81%8B%E3%81%9F%E3%80%8F">そもそもは『CPUの創りかた』</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://book.mynavi.jp/ec/products/detail/id=22065">CPUの創りかた | マイナビブックス</a></p> <ul> <li>最初に読んだのは 4年くらい前</li> <li>かなり基本的なところから手取り足取り説明されていてとっても良い本だが、 単に読むだけだと後半で分からなくなる</li> <li>さすがに何も知らない私みたいなド素人が さらっと読んだだけで理解できるほど甘くはない</li> <li>(自分のような初心者は)作りながら読まないと分からないのでは <ul> <li>回路図を読むところがネックになる</li> <li>回路図というものは抽象化された図なわけで、 そこから具体的な回路や動作がどうなるかよく分からない</li> </ul></li> <li>しかし作るのは面倒 <ul> <li>部品の調達</li> <li>また部屋が散らかる……</li> <li>知識・経験がなさすぎてゴールが遠い</li> </ul></li> <li>物理CPU作るのは老後の楽しみにしよう……</li> <li>とはいえ、先にしくみだけでも理解したい</li> <li>しくみを理解するには、やはり自分で作って電子回路についての経験を積む必要があるんだろうな…… <ul> <li>→ 「しかし作るのは面倒」に戻る</li> <li>ブートストラップ問題</li> </ul></li> <li>しくみを理解するだけなら、枝葉の部分を捨ててもっと簡素化してハードルを下げられないか</li> </ul> <p>こういうのって、実際に手を動かして作って壊して、回路図とにらめっこしたり計算をやりなおして試行錯誤を繰り返すうちにだんだん勘が養われていくものだと思いますが、そういう経験がない状態なのでなかなか大変です。</p> <h2 id="論理回路シミュレータ"><a href="#%E8%AB%96%E7%90%86%E5%9B%9E%E8%B7%AF%E3%82%B7%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF">論理回路シミュレータ</a></h2> <ul> <li>そもそも論理回路シミュレータというものをよく知らなかった</li> <li>シミュレータで CPU(TD4など)を作っている人たちがいると知る</li> <li>物理CPU作る前にこれで試すのは良さそう <ul> <li>手間・時間をかけずに好きなだけスクラップ&ビルドできる</li> <li>部屋も散らからない</li> </ul></li> </ul> <h2 id="nand2tetlis"><a href="#nand2tetlis">nand2tetlis</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://www.oreilly.co.jp/books/9784873117126/">O'Reilly Japan - コンピュータシステムの理論と実装</a></p> <ul> <li>通称(?) nand2tetlis</li> <li>物理的な電子回路でなぜ論理回路が動くのか、という部分がよく分からないまま HDL に進んでしまうのがちょっと不満</li> <li>そこの部分のブラックボックス感を解消したいのに</li> </ul> <h2 id="そもそも論理回路が動くしくみがよく分かってない"><a href="#%E3%81%9D%E3%82%82%E3%81%9D%E3%82%82%E8%AB%96%E7%90%86%E5%9B%9E%E8%B7%AF%E3%81%8C%E5%8B%95%E3%81%8F%E3%81%97%E3%81%8F%E3%81%BF%E3%81%8C%E3%82%88%E3%81%8F%E5%88%86%E3%81%8B%E3%81%A3%E3%81%A6%E3%81%AA%E3%81%84">そもそも論理回路が動くしくみがよく分かってない</a></h2> <ul> <li>入力側から電流が流れてきて、それが出力側に伝わるというのは分かる</li> <li>NOTゲートってどうなってるの。謎。 <ul> <li>入力が L で出力が H になる場合、その H の電力はどこから来てるの</li> <li>省略されると分からない</li> </ul></li> <li>フリップフロップ <ul> <li>タイミングが絡んでくるし、入力がループするので、 脳内でエミュレートできない</li> <li>(自分で作って)動かしてみないとどうも実感が湧かない</li> </ul></li> <li>論理回路図というものは抽象化された図なわけで、 どうすればそれを物理的な回路で実現できるかが分からない</li> </ul> <p>今だからこうやって言語化できていますが、もっとボンヤリとモヤモヤしてました。「なんとなく……分かった気がする……たぶん……とりあえずそういうものだと飲み込んで先に進んでもいいが……(モヤモヤ)」みたいな。</p> <h2 id="リレー"><a href="#%E3%83%AA%E3%83%AC%E3%83%BC">リレー</a></h2> <ul> <li>トランジスタについてもよく分かっていなかったので、 トランジスタ → 真空管 → リレー と遡って調べたりしていた</li> <li>リレーについて知ることで 「要するに何をやっているのか」「何のための部品なのか」が分かった</li> <li>要するに「電気を使ってスイッチを切り替える装置」 <ul> <li><a target="_blank" rel="nofollow noopener" href="https://en.wikipedia.org/wiki/Relay">英語版 Wikipedia</a> の説明が簡潔で良いです。 "A relay is an electrically operated switch."</li> <li>「それを早く教えてよ!」という気分に</li> </ul></li> <li>リレー、めっちゃ良い。分かりやすい。小学生でも理解できる。電磁石まで知ってればあともう一歩。そのくせインパクトがでかい。 <ul> <li>「小学校の理科でついでにリレーまで教えてくれてればよかったのに!」 という気分に <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></li> <li>「小学校の理科の知識に、あとはリレーだけ付け加えれば CPU まで作れる」 というのは、なんかいい。よくないですか?</li> </ul></li> <li>トランジスタについても、「N型 と P型があって正孔が……」という 半導体自体の説明よりも、 先に役割や目的について着目した方が(自分には)分かりやすかったと思います</li> </ul> <p>たしか、ここがクリアされたことで「あ、これなら自分でも作れるかも?」みたいな気分になった気がします。</p> <h2 id="Minecraft や Oxygen Not Included の論理回路"><a href="#Minecraft+%E3%82%84+Oxygen+Not+Included+%E3%81%AE%E8%AB%96%E7%90%86%E5%9B%9E%E8%B7%AF">Minecraft や Oxygen Not Included の論理回路</a></h2> <ul> <li>楽しい</li> <li>あの要素だけなら、自分でもなんとか作って遊べるのではないか? <ul> <li>そう思わせてくれるところがとても良い。教育的。</li> </ul></li> <li>グリッド配置にしたのはこれらの影響</li> <li>他にも、マリオメーカーや Cities: Skylines などで作ってみた系の記事や動画を見て 「その部分だけ抜き出したもの」程度なら自分でも作れないか、 と妄想したり <ul> <li>(2010)<a target="_blank" rel="nofollow noopener" href="https://nlab.itmedia.co.jp/games/articles/1010/01/news094.html">スゴすぎ! 「Minecraft」で本物の16ビットコンピュータを再現 - ねとらぼ</a></li> <li>(2015)<a target="_blank" rel="nofollow noopener" href="https://www.nicovideo.jp/watch/sm27235148">【論理演算】マリオメーカーに「3+3=6」を計算させてみた - ニコニコ動画</a></li> <li>(2019)<a target="_blank" rel="nofollow noopener" href="https://automaton-media.com/articles/newsjp/20190718-97734/">『Cities: Skylines』でうんちを利用した計算機が制作される。汚水が流れて4ビットの回路を動かす | AUTOMATON</a></li> </ul></li> </ul> <h2 id="水流モデル(失敗)"><a href="#%E6%B0%B4%E6%B5%81%E3%83%A2%E3%83%87%E3%83%AB%EF%BC%88%E5%A4%B1%E6%95%97%EF%BC%89">水流モデル(失敗)</a></h2> <ul> <li>電気について詳しくないので<a target="_blank" rel="nofollow noopener" href="https://ja.wikipedia.org/wiki/%E6%B0%B4%E6%B5%81%E3%83%A2%E3%83%87%E3%83%AB">水流モデル</a>の方が分かりやすいかな、と思ってセルオートマトンで作ろうとした</li> <li>逆に複雑で難しかったので中止</li> </ul> <h1 id="どうやって作るか"><a href="#%E3%81%A9%E3%81%86%E3%82%84%E3%81%A3%E3%81%A6%E4%BD%9C%E3%82%8B%E3%81%8B">どうやって作るか</a></h1> <ul> <li>ググっても「論理回路シミュレータの作りかた」なんて解説は出てこない <ul> <li>自分のイメージに一番近かったのがこれ: <a target="_blank" rel="nofollow noopener" href="http://bach.ai/a-puzzle-game-that-makes-us-build-a-complete-computer/">A puzzle game that makes us build a complete computer - Joscha Bach</a></li> </ul></li> <li>OSS なシミュレータのソースを読む手もあるが…… <ul> <li><a target="_blank" rel="nofollow noopener" href="http://www.cburch.com/logisim/">Logisim</a> とか <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></li> <li>そんなに本格的なものでなくてよい</li> <li>おもちゃみたいなのでよい</li> <li>実用目的ではない。いわゆる「教育目的」なもの。<br /> 枝葉を排して理解しやすさを優先したもの。</li> <li>自分が作りたかったのは普通の論理回路シミュレータではなく、 電池と導線と……で論理回路が動かせる、抽象化されていないシミュレータ</li> </ul></li> <li>結局手探りで</li> <li>詳しくは<a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/entry/2020/04/21/065800">製作過程のメモ</a>の方に書きました</li> </ul> <h1 id="感想"><a href="#%E6%84%9F%E6%83%B3">感想</a></h1> <ul> <li>おもしろかった!!</li> <li>物理回路と論理回路との接続の部分が分かってよかった</li> <li>1bit CPU を自分で実際に作れてよかった <ul> <li>生まれて初めて(シミュレータ上だけど)CPU を自作した!</li> <li>めでたい!</li> </ul></li> <li>NOTゲートえらい <ul> <li>NOTゲートが作れるようになるのでリレーは偉大な発明</li> <li>で、リレーで論理回路を作るアイデアはどこから出てきたんだ、誰が始めたんだ…… と調べていくとクロード・シャノンにたどり着きます。 コンピュータの黎明期の話というとチューリングやノイマンが有名ですが、 シャノンも非常に重要な仕事をしていたんですね (これも今回いろいろ調べていて知りました)。 <ul> <li><a target="_blank" rel="nofollow noopener" href="https://qiita.com/sonota88/items/a5d6d3539e0fb8040f74#comment-3fce67595ab213760f79">中嶋章についてのscivolaさんのコメント</a> も参照</li> </ul></li> <li><a target="_blank" rel="nofollow noopener" href="https://sgforum.impress.co.jp/article/774">連載:インターネット・サイエンスの歴史人物館(2)クロード・シャノン | 情報通信(ICT) | スマートグリッドフォーラム<br /> </a></li> <li><a target="_blank" rel="nofollow noopener" href="https://xtech.nikkei.com/it/free/NSW/ITBASIC/20040403/2/">プログラミングの10大基礎知識(3) | 日経クロステック(xTECH)</a></li> </ul></li> <li>電気の知識がちょっと増えてよかった <ul> <li>ふだんやらないことをやると知らないことだらけで楽しい</li> </ul></li> <li>むちゃくちゃ難易度高いということもなく、動くと楽しいのでプログラミングのお題としてもおもしろいと思います。おすすめ。</li> </ul> <h1 id="TODO"><a href="#TODO">TODO</a></h1> <p>気が向いたらやりたい</p> <ul> <li>最適化・リファクタリング <ul> <li>現状ではだいぶ富豪的なので</li> </ul></li> <li>タイミングチャート付ける <ul> <li>そんなに難しくなさそう</li> <li>(2020-07-26) <a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/entry/2020/07/26/140308">付けました</a></li> </ul></li> <li>1bit CPU から先 <ul> <li>これ以上規模が大きくなると大変そうだし、 論理回路と物理回路の接続の理解についてはだいぶ気が済んだので、 続きを作るとしたら既存の論理回路シミュレータを使えばよさそう</li> </ul></li> <li>オブザーバーパターンや Actor モデルを使って書いてみる?</li> </ul> <h1 id="関連"><a href="#%E9%96%A2%E9%80%A3">関連</a></h1> <p>今のところ直接関連するというわけではないですが、もっと上のレイヤーの話ということで。1bit CPU と下記の VM の間のギャップも埋めていければなあと考えてはいます。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/entry/2019/05/04/232236">RubyでオレオレVMとアセンブラとコード生成器を2週間で作ってライフゲームを動かした話</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/entry/2020/05/04/155425">Rubyで素朴な自作言語のコンパイラを作った</a></li> </ul> <h1 id="作った後に読んだもの"><a href="#%E4%BD%9C%E3%81%A3%E3%81%9F%E5%BE%8C%E3%81%AB%E8%AA%AD%E3%82%93%E3%81%A0%E3%82%82%E3%81%AE">作った後に読んだもの</a></h1> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.tokyo-shoseki.co.jp/books/81189/">【東京書籍】 一般書籍 文芸 コンピュータ、どうやってつくったんですか?</a> <ul> <li>2020-12 に読んだ。リレーで説明されてて良い。</li> </ul></li> <li><a target="_blank" rel="nofollow noopener" href="https://book.mynavi.jp/ec/products/detail/id=116654">作ろう!CPU | マイナビブックス</a></li> </ul> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>指導要領の都合とかでいろいろあるんだと思います <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:2" role="doc-endnote"> <p>有名っぽいので Logisim を例に出しましたが、Logisim は開発が終わっているようなので他のものを探すのが良さそうです <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> sonota486 tag:crieit.net,2005:PublicArticle/15772 2020-03-19T20:19:01+09:00 2021-02-09T20:50:42+09:00 https://crieit.net/posts/CPU-RISC-V-vs-ICF3-Z オープンソースのCPUの除算性能 RISC-V vs ICF3-Z <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p>2020年1月15日に<a target="_blank" rel="nofollow noopener" href="https://icf3z.idletime.tokyo/">8bit CPU ICF3-Z</a>を制限の緩いオープンソースのライセンスで公開しました。</p> <p>CPUのようなハードウェアもオープンソースな時代になってきました。CPUのオープンソースで最も有名なのはRISC-Vです。RISC-Vを見てみるとオープンソースによるメリットを見つけることができます。RISC-Vは、とても広い範囲をカバーする32bit(64bit)のCPUですが低性能な領域でも万能というわけではないように思います。</p> <p>例えば通信系のハードウェアでは8bit単位で処理するものもあり32bitが無駄になる場合もあります。無駄になるだけなら問題はありませんが消費電力で不利です。</p> <p>一方、8bit CPUは除算命令がなかったり、除算命令があっても8bit÷8bitで、使える範囲が狭いということがありました。8bit CPUのオープンソースも既に複数、存在していますが、高性能な除算を持ったものは、あまりないように思います。ICF3-Zはオープンソースで、少ないトランジスタ数であるにもかかわらず高速な除算が可能です。</p> <h2 id="除算性能の比較"><a href="#%E9%99%A4%E7%AE%97%E6%80%A7%E8%83%BD%E3%81%AE%E6%AF%94%E8%BC%83">除算性能の比較</a></h2> <p><strong>実際に比較しないと、わからない人が多いと思っています。</strong> ICF3-ZのZeviosを小型のRISC-VコアであるlowRISCのibexと比較してみました。 ICF3-ZのZeviosは8bit CPUですが、lowRISCのibexは<strong>除算器を持った32bit CPU</strong>です。</p> <p>lowRISCの<a target="_blank" rel="nofollow noopener" href="https://www.lowrisc.org/blog/2019/06/an-update-on-ibex-our-microcontroller-class-cpu-core/">Webページ</a>にXilinxのローエンドのFPGA(7シリーズ)に実装した場合の周波数が50MHz、面積2500LUTと書かれてありました。 除算のサイクル数は<a target="_blank" rel="nofollow noopener" href="https://ibex-core.readthedocs.io/en/latest/instruction_decode_execute.html#multiplier-divider-block-mult-div">別のページ</a>に37サイクルと記述されています。</p> <p>Zeviosは同じくXilinxのローエンドのFPGA(Artix-7)に実装した場合、周波数は150MHzになります。つまりibexの3倍の周波数で動作します。ibexが1命令を実行するのにZeviosは3命令を実行できる。</p> <div class="table-responsive"><table> <thead> <tr> <th>除算</th> <th>ibexRISC-V[サイクル]</th> <th>ZeviosICF3-Z[サイクル]</th> <th>ibexを1とした倍率</th> <th>周波数を考慮した倍率</th> </tr> </thead> <tbody> <tr> <td>16bit÷8bit</td> <td>37</td> <td>20</td> <td>1.85</td> <td>5.55</td> </tr> <tr> <td>24bit÷8bit条件付き</td> <td>37</td> <td>21</td> <td>1.76</td> <td>5.29</td> </tr> <tr> <td>32bit÷8bit</td> <td>37</td> <td>55</td> <td>0.67</td> <td>2.02</td> </tr> <tr> <td>32bit÷16bit</td> <td>37</td> <td>約350</td> <td>0.11</td> <td>0.32</td> </tr> </tbody> </table></div> <p>0除算などのチェックや演算レジスタへのロード、ストアの補正として3~6サイクル追加しています。<br /> ZeviosはXilinxのFPGA XC7A35TICSG324-1Lに実装した場合です。</p> <h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2> <p>ibexは2500LUTの面積ですが、Zeviosは400LUTの面積です。 外部I/OなどZeviosに不足しているものがあるかもしれませんが<strong>5分の一の面積で5倍以上の性能が出る</strong>ことは、考えるべき点ではないでしょうか。16bit÷8bitは32bit CPUであるRISC-Vに不利ということはありますが、制御など32bitの精度が必ずしも必要ない場合もあるように思います。</p> <p>ICF3-Zは海外のパクリな構造ではなく僕の考えた独自アーキテクチャです。疑似パイプラインによって高周波数で動作することも、この圧倒的な面積当たりの性能(25倍)に貢献しています。</p> <p>このオープンソースな8bit CPU ICF3-Zが、期待を含めれば2020年代に大きく産業に貢献していくかもしれません。</p> <h2 id="参考リンク"><a href="#%E5%8F%82%E8%80%83%E3%83%AA%E3%83%B3%E3%82%AF">参考リンク</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/izuna/items/49ad4eef53c65c591d61">8bit CPU ICF3-ZのZeviosの除算性能のメモ</a></p> <p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/izuna/items/38a04fbedf531f193a7d">8bit CPU ATmega328の除算性能を測定してみた</a></p> <p><a target="_blank" rel="nofollow noopener" href="https://icf.hatenablog.com/entry/2019/04/16/181417">仮想マシンの加速支援機構つきの新型8bit CPU</a></p> spinlock tag:crieit.net,2005:PublicArticle/15684 2020-01-16T06:22:14+09:00 2020-01-16T06:22:14+09:00 https://crieit.net/posts/8bit-CPU-ICF3-Z-Zevios 8bit CPU ICF3-ZのZeviosの除算性能のメモ <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p>8bit CPU ICF3-Zのオリジナルのコア、<a target="_blank" rel="nofollow noopener" href="https://icf3z.idletime.tokyo/download.html">Zevios</a>の除算性能について解説します。Zeviosは2020年1月15日に緩いオープンソースライセンスであるApache License 2.0で公開されました。FPGAに実装できるverilogファイルがあるので、いろいろ性能を測定することができます。</p> <h2 id="Zeviosの除算器について"><a href="#Zevios%E3%81%AE%E9%99%A4%E7%AE%97%E5%99%A8%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">Zeviosの除算器について</a></h2> <p>正しくは除算器というものはなくて8bitの加算器を効率的に動作させることで1サイクルに1bitの商を演算するアーキテクチャです。除算器の性能としては低いのですが、マイコン向けのCPUでは除算器がないものも多く、小さい面積なのに高速に除算ができるものになっています。(除算器としての面積がほとんどない) その除算向けのアーキテクチャを使って8bitより大きい除算をソフトウェアで実装できます。一般の8bit CPUによる実装よりも高速に演算できます。</p> <h2 id="16bit÷8bitの除算"><a href="#16bit%C3%B78bit%E3%81%AE%E9%99%A4%E7%AE%97">16bit÷8bitの除算</a></h2> <p>ICF3-Zでは加算器を使って効率的に演算できるようになっています。17サイクルで演算ができます。</p> <h2 id="24bit÷8bitの除算"><a href="#24bit%C3%B78bit%E3%81%AE%E9%99%A4%E7%AE%97">24bit÷8bitの除算</a></h2> <p>ICF3-Zでは加算器を使って効率的に演算できるようになっています。17サイクルで演算ができます。<br /> ただし被除数の最上位8bitが除数8bitよりも小さい場合に限ります。</p> <h2 id="32bit÷8bitの除算"><a href="#32bit%C3%B78bit%E3%81%AE%E9%99%A4%E7%AE%97">32bit÷8bitの除算</a></h2> <p>16bit÷8bitの除算方法を応用したサンプルコードによる性能は50サイクルです。サンプルコードはgithubで公開されています。<br /> sim2フォルダのpmem.asmzが32bit÷8bitのコードです。</p> <h2 id="32bit÷16bitの除算"><a href="#32bit%C3%B716bit%E3%81%AE%E9%99%A4%E7%AE%97">32bit÷16bitの除算</a></h2> <p>ICF3-Zのアーキテクチャを駆使したサンプルコードによる性能は約350サイクルです。サンプルコードはgithubで公開されています。<br /> sim1フォルダのpmem.asmzが32bit÷16bitのコードです。<br /> ソフトウェアの実装によって性能は違ってくると思われます。もっと高速な方法もあるかもしれません。<br /> 除数が8bit × 8bitの因数に分解できるものなら32bit ÷ 8bitを2回演算したほうが高速です。</p> <p>32bit÷15bitを230サイクルで演算するコードも作ったのですが、まだ十分に検証できていないため、今回は見送りました。</p> <h2 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h2> <p>ICF3-Z Zeviosは、とても少ないトランジスタ数(面積)で実装できるのに高速です。16bit÷8bit、24bit÷8bitの除算が有効につかえるアプリでは低消費電力が期待できるように思われます。</p> spinlock tag:crieit.net,2005:PublicArticle/15676 2020-01-12T04:51:56+09:00 2020-06-03T01:49:25+09:00 https://crieit.net/posts/8bit-CPU-ATmega328 8bit CPU ATmega328の除算性能を測定してみた <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p>ATmega328は Microchipの8bit CPU AVRの1種です。AVRは除算命令がなくArduinoで除算をするコードを書いた場合、どのくらいの性能になるのか測定しました。測定条件でソフトウェア処理が最適化されていないのでAVRのアセンブラを使って最適化をすれば、もっと高速になるはずですが、これはソフト開発環境Arduinoのソフトウエア除算性能の測定です。</p> <h2 id="測定条件"><a href="#%E6%B8%AC%E5%AE%9A%E6%9D%A1%E4%BB%B6">測定条件</a></h2> <p>CPU : ATmega328 クロック 16MHz<br /> ボード: Arduino<br /> ソフト開発環境 : Arduino 1.8.10<br /> 性能を測定する除算 : 16bit ÷ 8bit / 24bit ÷ 8bit</p> <h2 id="測定コード(16bit÷8bit)"><a href="#%E6%B8%AC%E5%AE%9A%E3%82%B3%E3%83%BC%E3%83%89%2816bit%C3%B78bit%29">測定コード(16bit÷8bit)</a></h2> <p>除算を1万回実行して、加算のみの場合との差分を除算1万回の実行時間とします。</p> <pre><code>void setup() { Serial.begin(9600); randomSeed(analogRead(0)); } void loop() { unsigned long s, e, t; unsigned int i; unsigned short x,z; unsigned char y; t = millis(); /* dummy */ s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0xffff); y = random(2,0xff); z += x + y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" time1="); Serial.print(t); Serial.print("\n"); s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0xffff); y = random(2,0xff); z += x / y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" z="); Serial.print(z); Serial.print(" time2="); Serial.print(t); Serial.print("\n\n"); } </code></pre> <h2 id="測定コード(24bit÷8bit)"><a href="#%E6%B8%AC%E5%AE%9A%E3%82%B3%E3%83%BC%E3%83%89%2824bit%C3%B78bit%29">測定コード(24bit÷8bit)</a></h2> <p>除算を1万回実行して、加算のみの場合との差分を除算1万回の実行時間とします。</p> <pre><code>void setup() { Serial.begin(9600); randomSeed(analogRead(0)); } void loop() { unsigned long s, e, t; unsigned int i; unsigned long x,z; unsigned char y; t = millis(); /* dummy */ s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0x7effff); y = random(0x7f,0xff); z += x + y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" time1="); Serial.print(t); Serial.print("\n"); s = millis(); for(i=0 ; i<10000 ; i++) { x = random(0,0x7effff); y = random(0x7f,0xff); z += x / y; } e = millis(); t = e - s; Serial.print("x="); Serial.print(x); Serial.print(" y="); Serial.print(y); Serial.print(" z="); Serial.print(z); Serial.print(" time2="); Serial.print(t); Serial.print("\n\n"); } </code></pre> <h2 id="結果(16bit÷8bit)"><a href="#%E7%B5%90%E6%9E%9C%2816bit%C3%B78bit%29">結果(16bit÷8bit)</a></h2> <p>除算1万回の実行時間は約128 [mS] 16MHzで動作しているのでサイクル数は2048000 cyc<br /> 除算1回のサイクル数は204.8 cyc<br /> 比較用の加算2サイクルの補正を追加すると<br /> <strong>16bit÷8bit 除算1回のサイクル数は207 cyc</strong></p> <h2 id="結果(24bit÷8bit)"><a href="#%E7%B5%90%E6%9E%9C%2824bit%C3%B78bit%29">結果(24bit÷8bit)</a></h2> <p>除算1万回の実行時間は約373 [mS] 16MHzで動作しているのでサイクル数は5968000 cyc<br /> 除算1回のサイクル数は596.8 cyc<br /> 比較用の加算2サイクルの補正を追加すると<br /> <strong>24bit÷8bit 除算1回のサイクル数は599 cyc</strong><br /> 32bit÷16bitの性能と、ほとんど同じなので、24bit÷8bit用に除算ルーチンを作り直せば性能は向上するのではないだろうか。</p> spinlock tag:crieit.net,2005:PublicArticle/15672 2020-01-09T13:37:32+09:00 2020-01-09T13:37:32+09:00 https://crieit.net/posts/8bit-CPU 仮想マシンの加速支援機構つきの新型8bit CPU <h2 id="概要"><a href="#%E6%A6%82%E8%A6%81">概要</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://icf3z.idletime.tokyo/">新型の8bit CPU(ICF3-Z)</a>を設計してFPGAに実装。仮想マシンの加速支援機構を使った、簡単なスタックマシンで、サンプルプログラムがXilinx FPGA Artix-7(-1)の実機上で動作した。たった約400LUTの小さいCPUで。Intel 8051マイコンのFREEな実装に<a target="_blank" rel="nofollow noopener" href="https://github.com/jaruiz/light52">light52</a>があります。軽量なマイコンですがCPU部だけで約800LUTあるようです。light52は1命令、6サイクルですが、このICF3-Zは1命令、1サイクルが基本で、時に1サイクルに複数命令の実行ができます。周波数比較もICF3-Zが、おおよそ2倍のようで、<strong>圧倒的に勝った</strong>のかも。他にあまり比較できるものがなかったという話もありますが。</p> <h2 id="仮想マシンの加速支援機構とは"><a href="#%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%81%AE%E5%8A%A0%E9%80%9F%E6%94%AF%E6%8F%B4%E6%A9%9F%E6%A7%8B%E3%81%A8%E3%81%AF">仮想マシンの加速支援機構とは</a></h2> <p>新型8bit CPU(ICF3-Z)なのですが命令コードが32bitで、一般的な8bit CPUと比べてメモリ効率が悪い。そこで16bitの圧縮命令の機能を追加した。この機能が仮想マシンの加速支援機構なのです。<br /> 圧縮命令のために作られたもので、加速支援機構として、最終的に成立するのかは、わからないですが、需要があって無理がなければ、加速支援機構として考えていく方向です。</p> <h2 id="加速支援機構が何の役に立つのか?"><a href="#%E5%8A%A0%E9%80%9F%E6%94%AF%E6%8F%B4%E6%A9%9F%E6%A7%8B%E3%81%8C%E4%BD%95%E3%81%AE%E5%BD%B9%E3%81%AB%E7%AB%8B%E3%81%A4%E3%81%AE%E3%81%8B%EF%BC%9F">加速支援機構が何の役に立つのか?</a></h2> <p>超低スペックなCPUでは、ソフトウエアで仮想マシンを実装しても性能的な問題で用途が狭められることがあります。この加速支援機構があれば実用の範囲が広がります。</p> <p><strong>2019年11月23日 追記</strong><br /> 仮想マシンの命令列を大容量の安価なプログラムメモリに置けるので、容量の少ない高価なデータメモリを圧迫しないということも利点です。</p> <h2 id="なぜ低スペックなCPUで仮想マシンなのか?"><a href="#%E3%81%AA%E3%81%9C%E4%BD%8E%E3%82%B9%E3%83%9A%E3%83%83%E3%82%AF%E3%81%AACPU%E3%81%A7%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%81%AA%E3%81%AE%E3%81%8B%3F">なぜ低スペックなCPUで仮想マシンなのか?</a></h2> <p>仮想マシンをJavaのようなスタックマシンにしたり、レジスタ1個のマシンにしたりできます。<br /> CPUのアーキテクチャの違いを吸収して、いろいろな言語のコンパイラの開発を容易にします。<br /> 非C言語が利用できるようになることで、より多くの人がIoTデバイスなどを開発できるようになります。</p> <h2 id="試作プログラム"><a href="#%E8%A9%A6%E4%BD%9C%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0">試作プログラム</a></h2> <p>プログラムの上部で簡単なスタックマシンの命令を実装して、仮想マシンの命令列をFPGAの実機で動作させたものです。独自のアセンブラなので多少、わかりにくかもしれません。自作したアセンブラでバイナリを生成して、FPGAのプログラムメモリに、置きます。<br /> 即値の5をPUSH、メモリの0番の値をPUSH、メモリの1番の値をPUSH、乗算、加算、LEDに結果を出力。<br /> メモリ0番には、最初のところで2を書き込んでいます。メモリ1番には3。つまり3*2+5 = 11がLEDに出力されます。(確認しました)</p> <pre><code>######################################################## # vm (Virtual Machie) # # C Register : SP(Stack Pointer) # D Register : PRINT (LED x 8) # MEM[0-255] : Memory # # PUSHI: SP=SP-1 , MEM[SP]=nn (5cyc) # PUSHR: SP=SP-1 , MEM[SP]=MEM[nn] (5cyc) # POP : MEM[nn]=MEM[SP] , SP=SP+1 (4cyc) # ADD : MEM[SP+1]=MEM[SP]+MEM[SP+1] , SP=SP+1 (7cyc) # MUL : MEM[SP+1]=MEM[SP]*MEM[SP+1] , SP=SP+1 (16cyc) # PRINT: PRINT MEM[SP] ######################################################## # Initial MEM[0]=0x02 , MEM[1]=0x03 ######################################################## ADDL=N;N=0x02;A=ANS STORE;Z=0 ADDL=N;N=0x03;A=ANS B(START) STORE;Z=1;C=ANS;D=ANS ######################################################## %NOP: JRETURN %PUSHI: ADDR=C;ADDL=N;N=0xFF;C=ANS RETURN;COPR;ADDL=N;A=ANS ADDR=C;R(ADDR);STORE %PUSHR: ADDR=C;ADDL=N;N=0xFF;C=ANS RETURN;R(N);COPR MOV;ADDR=C;R(ADDR);STORE %POP: RETURN;R(ADDR);ADDR=C;ONE;C=ANS MOV;COPR;R(N);STORE %ADD: R(ADDR);ADDR=C;ONE;C=ANS B=REG;R(ADDR);ADDR=C B=REG;ADDR=B;A=ANS RETURN;ADDL=A;ADDR=B;A=ANS R(ADDR);ADDR=C;STORE %MUL: R(ADDR);ADDR=C;ONE;C=ANS;D=ANS C=REG;R(ADDR);ADDR=C C=REG;ADDR=C;A=ANS B=ANS;I=X;X=7 MUL;ADDL=A;ADDR=B;B=RSH;C=RSH;WAIT RETURN;ADDR=C;A=ANS R(ADDR);ADDR=D;STORE;C=ANS %PRINT: RETURN;R(ADDR);ADDR=C D=REG START: _%PUSHI,0x05,%PUSHR,0x00 _%PUSHR,0x01,%MUL,0x00 _%ADD,0x00,%PRINT,0x00 EXIT(0);@D END: B(END) NOP </code></pre> <h2 id="ちなみに"><a href="#%E3%81%A1%E3%81%AA%E3%81%BF%E3%81%AB">ちなみに</a></h2> <p>割込みの実装もついていて約400LUTです。2つの割込みを受けられます。</p> <h2 id="2019年12月29日更新"><a href="#2019%E5%B9%B412%E6%9C%8829%E6%97%A5%E6%9B%B4%E6%96%B0">2019年12月29日更新</a></h2> <p>XilinxのFPGA(XC7A35TICSG324-1L)に搭載した<a target="_blank" rel="nofollow noopener" href="http://akizukidenshi.com/catalog/g/gM-14484/">Arty</a>に実装して面積を確認しています。 論理合成のオプションで結果が違うので、面積重視、性能重視の結果です。</p> <div class="table-responsive"><table> <thead> <tr> <th align="left">合成方針</th> <th align="center">LUT数</th> <th align="center">FF数</th> <th align="center">BRAM数</th> <th align="center">LUT-RAM</th> <th align="center">周波数</th> </tr> </thead> <tbody> <tr> <td align="left">面積重視</td> <td align="center">390</td> <td align="center">197</td> <td align="center">1.5</td> <td align="center">10</td> <td align="center">150MHz</td> </tr> <tr> <td align="left">面積重視</td> <td align="center">406</td> <td align="center">197</td> <td align="center">1.5</td> <td align="center">10</td> <td align="center">160MHz</td> </tr> <tr> <td align="left">性能重視</td> <td align="center">481</td> <td align="center">197</td> <td align="center">1.5</td> <td align="center">10</td> <td align="center">175MHz</td> </tr> </tbody> </table></div> <p>BRAM 1.5の内訳はプログラムメモリ 4KBとデータメモリ 2KB</p> <p>データメモリの先頭32バイトがレジスタ、先頭256バイトがスクラッチパッドメモリ。この合成結果はデータのアドレス線を8bitにしたものです。11bitにすればBRAMを消費することなく2KBのデータメモリをすべて使えます。データのアドレス線を16bitまで設定可能ですがBRAMを消費します。圧縮命令(仮想マシン)を利用する場合はプログラムメモリの先頭の領域を消費します。圧縮命令の命令数によって消費する領域が変化します。</p> <p>割込みを使ったデバッグ機能の検証をしました。 プログラムのコード中に、ブレークポイントを設定して、そこに、たどり着いた回数を計算して、設定した値(パスカウント)のとき、ブレークさせるみたいな機能が実現できます。 具体的には毎サイクル割込みを入れて、アドレスを確認して、設定されたアドレスなら、指定された回数に到達したかをチェック。 指定された回数の場合は、LEDを点灯させるというプログラムを作成して、FPGAの実機でテストしました。ちゃんと動いているようです。 ただプログラムコード中の一部の命令ではパスカウントを正しく計算できません。遅延分岐で遅延スロットをキャンセルする命令などです。 分岐命令の直後の命令にブレークポイントを設定した場合は、パスカウントは正しくありませんという仕様にしようかと考えています。 割込み処理中でキャンセル信号をチェックしてもいいのですが、 デバッグ機能のためにキャンセル信号をチェックする論理を追加するのは面積最小を追求するプロセッサでは、あまり良くないと考えてのことです。 (面倒とかではなくて)</p> <p>約400 LUTの面積の小さいCPUで、追加のデバッグモジュールなしにパスカウントを 使ったブレークポイントを設定できるのは、良くできるほうなんだろうと思うが、 他のCPUの面積とかわからないから、なんとも。</p> spinlock