SlideShare a Scribd company logo
1 of 16
Download to read offline
いにしえ的ななにか、カニか?
RISC-V
picoRV32, e203 改造
オレオレ命令追加した
2023/DEC/02
たけおか@AXE
@takeoka
…
今は無き Tang Primer
廃番。EG4S20 , Tang Primer FPGA
あらかじめ RISC-Vが焼かれている
Humming bird E203 core
Verilogで書かれている
秋月で¥2,580円 だった
結構いいものだった…
Tang Nano9K
Gowin GW1NR-9 FPGAチップ
LUT4:8640個
https://akizukidenshi.com/catalog/g/gM-17448/
https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-
9K/Nano-9K.html
Humming bird E203 core

2段パイプライン

RV32IMAC 命令セット

密結合メモリ

ITCM (Instruction Tightly
Coupled Memory)

DTCM (Data Tightly
Coupled Memory)

オープンソース Githubにある

Apacheライセンス
下記より引用解説:
https://content.riscv.org/wp-content/uploads/2018/07/Shanghai-
1110_HummingBirdE200forShanghaiDay_v1.pdf
Hummingbird Ultra-Low-Power 32bits RISC-V Processor Core
picorv32

picorv32 , nano 9k用
https://github.com/sipeed/TangNano-9K-example/tree/main/picotiny

pico rv32
https://github.com/YosysHQ/picorv32

picosoc
https://github.com/YosysHQ/picorv32/blob/master/picosoc/README.md

大変、単純なCPUコア

コンパクト

改造しやすい

クロック周波数は上げにくい
picorv32,e203に命令追加した
“B”拡張命令が無かった。

Parity: ワード中の”1”の個数の偶/奇を得る

Population Count:ワード中の”1”の数を数える
Alpha(CTPOP)にはある

Count Leading Zeros(CLZ)
x86(lzcnt,bsf), ARM(clz), Power(cntlzd,cntlzw),
Sparc2011(lzcnt),Mips32(clz),Alpha(CTLZ),
VAX(Find First Set(ffs)),68020(bfffo)にはある

Count Trailing Zero(CTZ)
x86(tzcnt),PowerISA3(cnttzw,cnttzd),Alpha(CTTZ)にある

bit reverse: ワードのビット順を逆転

Halt Exchange: ワードを半分に切って、その上下を入れ替え

Quarter Exchange:ハーフ・ワード内でその半分(1/4)を入れ替え
parity
ワード中の 各ビットの XORを取る
1のビットが奇数個:1
1のビットが偶数個:0
シリアル通信で使うかも…
Verilog記述
(^ reg_op1)
前置きの^ :リダクション XOR。各ビットのXORを取る
前置きの| :リダクション OR。各ビットのORを取る。0判定
前置きの& :リダクション AND。各ビットのANDを取る。0xFF判定
遅いclz Count Leading Zeros
ワード中で、MSB(最左)から0が何個 続くかを数える。
一番上(左)の1の位置がわかる。
この実装だと、32個の比較の後、
結果が得られる。
遅い
↓
クロック周波数の足を引っ張る
Verilog記述→
/* clz 24bit for pmmp0, Slow*/
assign nsh_pmmp[5:0] =
pmmp0[23] ? 6'd0
:( pmmp0[22] ? 6'd1
:( pmmp0[21] ? 6'd2
:( pmmp0[20] ? 6'd3
:( pmmp0[19] ? 6'd4
:( pmmp0[18] ? 6'd5
:( pmmp0[17] ? 6'd6
:( pmmp0[16] ? 6'd7
:( pmmp0[15] ? 6'd8
:( pmmp0[14] ? 6'd9
:( pmmp0[13] ? 6'd10
:( pmmp0[12] ? 6'd11
:( pmmp0[11] ? 6'd12
:( pmmp0[10] ? 6'd13
:( pmmp0[9] ? 6'd14
:( pmmp0[8] ? 6'd15
:( pmmp0[7] ? 6'd16
:( pmmp0[6] ? 6'd17
:( pmmp0[5] ? 6'd18
:( pmmp0[4] ? 6'd19
:( pmmp0[3] ? 6'd20
:( pmmp0[2] ? 6'd21
:( pmmp0[1] ? 6'd22
:( pmmp0[0] ? 6'd23
: 6'd24
)))))))))))))))))))))));
「ハッカーのたのしみ」本を読むべし
エエこと書いてある!
Hacker's Delight (原書は2nd Editionになっている)
出版社: エスアイビーアクセス (2004/09)
ISBN-10: 4434046683
clz,clz,population は、この本で勉強
速い clz Count Leading Zeros
ワード中で、MSB(最左)から0が何個 続くかを数える。
一番上(左)の1の位置がわかる。
●判断(?)5段、 !( |(clzx0[X:Y]))演算4段 の9段の演算になる
Verilog記述
//// clz
wire [31:0] clzx0,clzx1,clzx2,clzx3,clzx4,clzx5,n1,n2,n3,n4,n5,xx1,xx2,xx3,xx4;
assign clzx0[31:0] = reg_op1;
assign xx1 = !( |(clzx0[31:16])); // & 32'hFFFF0000
assign clzx1[31:0] = xx1 ?
clzx0[31-16:0] << 16
: clzx0[31:0] ;
assign n1 = (xx1 ? 32'd16 : 32'd0);
assign xx2 = !(|(clzx1[31:24]));
assign clzx2[31:0] = xx2 ?
clzx1[31-8:0] << 8
: clzx1[31:0] ;
assign n2 = n1 + (xx2 ? 32'd8 : 32'd0);
assign xx3 = !(|(clzx2[31:28]));
assign clzx3[31:0] = xx3 ?
clzx2[31-4:0] << 4
: clzx2[31:0] ;
assign n3 = n2 + (xx3 ? 32'd4 : 32'd0);
assign xx4 = !(|(clzx3[31:30]));
assign clzx4[31:0] = xx4 ?
clzx3[31-2:0] << 2
: clzx3[31:0] ;
assign n4 = n3 + (xx4 ? 32'd2 : 32'd0);
assign n5 = n4 + !clzx4[31]; //add
inverse of MSB
wire [31:0] clz_res = !(|(reg_op1))?
最下位(?) 細粒度 並列
assign xx1 = !( |(clzx0[31:16]));
assign clzx1[31:0] = xx1 ?
clzx0[31-16:0] << 16
: clzx0[31:0] ;
assign n1 = (xx1 ? 32'd16 : 32'd0);
●clzx1 と n1 は、同時に計算される
●
n1 が参照されるのは、clzx1 …
より 少し後だが
●assign clzx1[31:0] = xx1 ?
clzx0[15:0] << 16
は、配線の接続となって、シフト演算されない(ことを願う)
{ clzx0[15:0], 16'd0 }
…
とか書いた方がいいか
ビット選択と線(ワイヤ)
ワード中で、MSB(最左)から0が何個 続くかを数える。
一番上(左)の1の位置がわかる。
Verilog記述
assign xx1 = !( |(clzx0[31:16]));
↓あまり良くないことが起きるかも…(通常なら、最適化されて↑になるはず)
assign xx1 = !( clzx0[31:0] & 32'hFFFF0000)
1
1
1
1
ctz Count Trailing Zero
ワード中で、LSB(最右)から0が何個 続くかを数える。
一番下(右)の1の位置がわかる。
clzと同様
Verilog記述
/// ctz
wire [31:0] ctzx0;wire [15:0] ctzx1; wire [7:0] ctzx2; wire [3:0] ctzx3; wire [1:0] ctzx4;
wire [5:0] m1, m2, m3, m4, m5; wire yy1,yy2,yy3,yy4;
assign ctzx0[31:0] = reg_op1;
assign yy1 = !( |(ctzx0[15:0])); // & 32'h0000FFFF
assign ctzx1[15:0] = yy1 ?
(ctzx0[31:16])
: ctzx0[15:0] ;
assign m1 = (yy1 ? 32'd16 : 32'd0);
assign yy2 = !(|(ctzx1[7:0])); // & 32'h000000FF
assign ctzx2[7:0] = yy2 ?
(ctzx1[15:8])
: ctzx1[7:0] ;
assign m2 = m1 + (yy2 ? 32'd8 : 32'd0);
assign yy3 = !(|(ctzx2[3:0])); // & 32'h000000F
assign ctzx3[3:0] = yy3 ?
(ctzx2[7:4])
: ctzx2[3:0] ;
assign m3 = m2 + (yy3 ? 32'd4 : 32'd0);
assign yy4 = !(|(ctzx3[1:0])); // & 32'h0000003
assign ctzx4[1:0] = yy4 ?
(ctzx3[3:2])
: ctzx3[1:0] ;
assign m4 = m3 + (yy4 ? 32'd2 : 32'd0);
assign m5 = m4 + !ctzx4[0]; //add inverse of LSB
wire [31:0] ctz_res = !(|(reg_op1)) ? 32'd32 : m5;
population
ワード中の 1のビットの 数を数える
Verilog記述
//// population
wire [31:0] popx0, popx1, popx2, popx3, popx4, pop_res;
assign popx0 = reg_op1;
assign popx1 = (popx0 & 32'h55555555) + ((popx0 >> 1)& 32'h55555555);
assign popx2 = (popx1 & 32'h33333333) + ((popx1 >> 2)& 32'h33333333);
assign popx3 = (popx2 & 32'h0f0f0f0f) + ((popx2 >> 4)& 32'h0f0f0f0f);
assign popx4 = (popx3 & 32'h00ff00ff) + ((popx3 >> 8)& 32'h00ff00ff);
assign pop_r = (popx4 & 32'h0000ffff) + ((popx4 >>16)& 32'h0000ffff);
bit reverse
ワード中のビットの順序を逆にする
Verilog記述
//// bit reverse
alu_brev <= {reg_op1[0],reg_op1[1],reg_op1[2],reg_op1[3],
reg_op1[4],reg_op1[5],reg_op1[6],reg_op1[7],
reg_op1[8],reg_op1[9],reg_op1[10],reg_op1[11],
reg_op1[12],reg_op1[13],reg_op1[14],reg_op1[15],
reg_op1[16],reg_op1[17],reg_op1[18],reg_op1[19],
reg_op1[20],reg_op1[21],reg_op1[22],reg_op1[23],
reg_op1[24],reg_op1[25],reg_op1[26],reg_op1[27],
reg_op1[28],reg_op1[29],reg_op1[30],reg_op1[31]
};
Half Exchange,Quarter Exchange
●Halt Exchange: ワードを半分に切って、その上下を入れ替え
元 3,2 , 1,0
3,2 ⇔ 1,0
結果1,0 , 3,2
●Quarter Exchange:ハーフ・ワード内でその半分(1/4)を入れ替え
元 3,2 , 1,0
3⇔2 , 1⇔0
結果 2,3 , 0,1
Verilog記述
//// Half Exchange
alu_hexg <= {reg_op1[15:0],reg_op1[31:16]};
//// Quarter Exchange
alu_qexg <=
{reg_op1[23:16],reg_op1[31:24],reg_op1[7:0],reg_op1[15:8]};
//// word Ex (おまけ)
alu_wexg <=
{reg_op1[7:0],reg_op1[15:8],reg_op1[23:16],reg_op1[31:24]};
ワード中のバイトを逆順にするには、
H-Exg と Q-Exg を行う
以上

More Related Content

Similar to いにしえ的ななにか、カニか? RISC-V picoRV32, e203 改造 オレオレ命令追加した

x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTtakesako
 
PBL1-v1-008j.pptx
PBL1-v1-008j.pptxPBL1-v1-008j.pptx
PBL1-v1-008j.pptxNAIST
 
PBL1-v1-010j.pptx
PBL1-v1-010j.pptxPBL1-v1-010j.pptx
PBL1-v1-010j.pptxNAIST
 
OutLookAR for EKF_SLAM_Model
OutLookAR for EKF_SLAM_ModelOutLookAR for EKF_SLAM_Model
OutLookAR for EKF_SLAM_ModelToshiki Imagaw
 
第10回 計算機構成
第10回 計算機構成第10回 計算機構成
第10回 計算機構成眞樹 冨澤
 
自作RISC-VチップでLチカをやってみた
自作RISC-VチップでLチカをやってみた自作RISC-VチップでLチカをやってみた
自作RISC-VチップでLチカをやってみたJunichi Akita
 
C++でHello worldを書いてみた
C++でHello worldを書いてみたC++でHello worldを書いてみた
C++でHello worldを書いてみたfirewood
 
PBL1-v1-009j.pptx
PBL1-v1-009j.pptxPBL1-v1-009j.pptx
PBL1-v1-009j.pptxNAIST
 
[DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装
[DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装 [DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装
[DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装 Deep Learning JP
 
Rでシステムバイオロジー
RでシステムバイオロジーRでシステムバイオロジー
Rでシステムバイオロジー弘毅 露崎
 
Rによるデータサイエンス:12章「時系列」
Rによるデータサイエンス:12章「時系列」Rによるデータサイエンス:12章「時系列」
Rによるデータサイエンス:12章「時系列」Nagi Teramo
 
世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤
世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤
世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤capsmalt
 
Hello, Guava ! samples
Hello, Guava ! samplesHello, Guava ! samples
Hello, Guava ! samples輝 子安
 
ネイティブコードを語る
ネイティブコードを語るネイティブコードを語る
ネイティブコードを語るKenji Imasaki
 
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部NVIDIA Japan
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングKiwamu Okabe
 
メンテできないコードをメンテする技術
メンテできないコードをメンテする技術メンテできないコードをメンテする技術
メンテできないコードをメンテする技術Tomoya Ishida
 

Similar to いにしえ的ななにか、カニか? RISC-V picoRV32, e203 改造 オレオレ命令追加した (20)

x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNT
 
PBL1-v1-008j.pptx
PBL1-v1-008j.pptxPBL1-v1-008j.pptx
PBL1-v1-008j.pptx
 
PBL1-v1-010j.pptx
PBL1-v1-010j.pptxPBL1-v1-010j.pptx
PBL1-v1-010j.pptx
 
OutLookAR for EKF_SLAM_Model
OutLookAR for EKF_SLAM_ModelOutLookAR for EKF_SLAM_Model
OutLookAR for EKF_SLAM_Model
 
第10回 計算機構成
第10回 計算機構成第10回 計算機構成
第10回 計算機構成
 
LLVM最適化のこつ
LLVM最適化のこつLLVM最適化のこつ
LLVM最適化のこつ
 
自作RISC-VチップでLチカをやってみた
自作RISC-VチップでLチカをやってみた自作RISC-VチップでLチカをやってみた
自作RISC-VチップでLチカをやってみた
 
C++でHello worldを書いてみた
C++でHello worldを書いてみたC++でHello worldを書いてみた
C++でHello worldを書いてみた
 
PBL1-v1-009j.pptx
PBL1-v1-009j.pptxPBL1-v1-009j.pptx
PBL1-v1-009j.pptx
 
[DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装
[DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装 [DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装
[DLHacks]PyTorch, PixyzによるGenerative Query Networkの実装
 
Rでシステムバイオロジー
RでシステムバイオロジーRでシステムバイオロジー
Rでシステムバイオロジー
 
Rによるデータサイエンス:12章「時系列」
Rによるデータサイエンス:12章「時系列」Rによるデータサイエンス:12章「時系列」
Rによるデータサイエンス:12章「時系列」
 
TVM の紹介
TVM の紹介TVM の紹介
TVM の紹介
 
世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤
世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤
世界におけるKubernetes活用状況と企業向けプライベートクラウド基盤
 
RでGIS
RでGISRでGIS
RでGIS
 
Hello, Guava ! samples
Hello, Guava ! samplesHello, Guava ! samples
Hello, Guava ! samples
 
ネイティブコードを語る
ネイティブコードを語るネイティブコードを語る
ネイティブコードを語る
 
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミング
 
メンテできないコードをメンテする技術
メンテできないコードをメンテする技術メンテできないコードをメンテする技術
メンテできないコードをメンテする技術
 

More from たけおか しょうぞう

俺ASICと俺CPU“松竹V(しょうちくぶい)”
俺ASICと俺CPU“松竹V(しょうちくぶい)”俺ASICと俺CPU“松竹V(しょうちくぶい)”
俺ASICと俺CPU“松竹V(しょうちくぶい)”たけおか しょうぞう
 
あるRISC-V CPUの 浮動小数点数(異常なし)
あるRISC-V CPUの 浮動小数点数(異常なし)あるRISC-V CPUの 浮動小数点数(異常なし)
あるRISC-V CPUの 浮動小数点数(異常なし)たけおか しょうぞう
 
どうして昔の人は八進数でしゃべるのか?
どうして昔の人は八進数でしゃべるのか?どうして昔の人は八進数でしゃべるのか?
どうして昔の人は八進数でしゃべるのか?たけおか しょうぞう
 
無脳スマートスピーカを 越えレレレのレ
無脳スマートスピーカを 越えレレレのレ無脳スマートスピーカを 越えレレレのレ
無脳スマートスピーカを 越えレレレのレたけおか しょうぞう
 
昔の外付けキャッシュ & コヒーレント・キャッシュ
昔の外付けキャッシュ & コヒーレント・キャッシュ昔の外付けキャッシュ & コヒーレント・キャッシュ
昔の外付けキャッシュ & コヒーレント・キャッシュたけおか しょうぞう
 
Lispマシン ドキュメント和訳とか、 ちびLispとか
Lispマシン ドキュメント和訳とか、 ちびLispとかLispマシン ドキュメント和訳とか、 ちびLispとか
Lispマシン ドキュメント和訳とか、 ちびLispとかたけおか しょうぞう
 

More from たけおか しょうぞう (20)

SOAR:Smalltalk on RISC
SOAR:Smalltalk on RISCSOAR:Smalltalk on RISC
SOAR:Smalltalk on RISC
 
俺ASICと俺CPU“松竹V(しょうちくぶい)”
俺ASICと俺CPU“松竹V(しょうちくぶい)”俺ASICと俺CPU“松竹V(しょうちくぶい)”
俺ASICと俺CPU“松竹V(しょうちくぶい)”
 
あるRISC-V CPUの 浮動小数点数(異常なし)
あるRISC-V CPUの 浮動小数点数(異常なし)あるRISC-V CPUの 浮動小数点数(異常なし)
あるRISC-V CPUの 浮動小数点数(異常なし)
 
RISC-Vの可能性
RISC-Vの可能性RISC-Vの可能性
RISC-Vの可能性
 
RISC-Vの可能性
RISC-Vの可能性RISC-Vの可能性
RISC-Vの可能性
 
どうして昔の人は八進数でしゃべるのか?
どうして昔の人は八進数でしゃべるのか?どうして昔の人は八進数でしゃべるのか?
どうして昔の人は八進数でしゃべるのか?
 
Riscv+fpga200606
Riscv+fpga200606Riscv+fpga200606
Riscv+fpga200606
 
Takep lpc1114-190614
Takep lpc1114-190614Takep lpc1114-190614
Takep lpc1114-190614
 
Takep lpc1114-190613
Takep lpc1114-190613Takep lpc1114-190613
Takep lpc1114-190613
 
初歩的な部品の知識
初歩的な部品の知識初歩的な部品の知識
初歩的な部品の知識
 
Takepino LPC1114
Takepino LPC1114Takepino LPC1114
Takepino LPC1114
 
Lisp_chibi_machine 190427
Lisp_chibi_machine 190427Lisp_chibi_machine 190427
Lisp_chibi_machine 190427
 
無脳スマートスピーカを 越えレレレのレ
無脳スマートスピーカを 越えレレレのレ無脳スマートスピーカを 越えレレレのレ
無脳スマートスピーカを 越えレレレのレ
 
Common Lisp ユーザへのScheme紹介
Common Lisp ユーザへのScheme紹介Common Lisp ユーザへのScheme紹介
Common Lisp ユーザへのScheme紹介
 
RISC-V User level ISA
RISC-V User level ISARISC-V User level ISA
RISC-V User level ISA
 
Lispマシン・シミュレータの紹介
Lispマシン・シミュレータの紹介Lispマシン・シミュレータの紹介
Lispマシン・シミュレータの紹介
 
昔の外付けキャッシュ & コヒーレント・キャッシュ
昔の外付けキャッシュ & コヒーレント・キャッシュ昔の外付けキャッシュ & コヒーレント・キャッシュ
昔の外付けキャッシュ & コヒーレント・キャッシュ
 
Ichigojam ossc-170819
Ichigojam ossc-170819Ichigojam ossc-170819
Ichigojam ossc-170819
 
大昔のMMU
大昔のMMU大昔のMMU
大昔のMMU
 
Lispマシン ドキュメント和訳とか、 ちびLispとか
Lispマシン ドキュメント和訳とか、 ちびLispとかLispマシン ドキュメント和訳とか、 ちびLispとか
Lispマシン ドキュメント和訳とか、 ちびLispとか
 

いにしえ的ななにか、カニか? RISC-V picoRV32, e203 改造 オレオレ命令追加した

  • 2. … 今は無き Tang Primer 廃番。EG4S20 , Tang Primer FPGA あらかじめ RISC-Vが焼かれている Humming bird E203 core Verilogで書かれている 秋月で¥2,580円 だった 結構いいものだった… Tang Nano9K Gowin GW1NR-9 FPGAチップ LUT4:8640個 https://akizukidenshi.com/catalog/g/gM-17448/ https://wiki.sipeed.com/hardware/en/tang/Tang-Nano- 9K/Nano-9K.html
  • 3. Humming bird E203 core  2段パイプライン  RV32IMAC 命令セット  密結合メモリ  ITCM (Instruction Tightly Coupled Memory)  DTCM (Data Tightly Coupled Memory)  オープンソース Githubにある  Apacheライセンス 下記より引用解説: https://content.riscv.org/wp-content/uploads/2018/07/Shanghai- 1110_HummingBirdE200forShanghaiDay_v1.pdf Hummingbird Ultra-Low-Power 32bits RISC-V Processor Core
  • 4. picorv32  picorv32 , nano 9k用 https://github.com/sipeed/TangNano-9K-example/tree/main/picotiny  pico rv32 https://github.com/YosysHQ/picorv32  picosoc https://github.com/YosysHQ/picorv32/blob/master/picosoc/README.md  大変、単純なCPUコア  コンパクト  改造しやすい  クロック周波数は上げにくい
  • 5. picorv32,e203に命令追加した “B”拡張命令が無かった。  Parity: ワード中の”1”の個数の偶/奇を得る  Population Count:ワード中の”1”の数を数える Alpha(CTPOP)にはある  Count Leading Zeros(CLZ) x86(lzcnt,bsf), ARM(clz), Power(cntlzd,cntlzw), Sparc2011(lzcnt),Mips32(clz),Alpha(CTLZ), VAX(Find First Set(ffs)),68020(bfffo)にはある  Count Trailing Zero(CTZ) x86(tzcnt),PowerISA3(cnttzw,cnttzd),Alpha(CTTZ)にある  bit reverse: ワードのビット順を逆転  Halt Exchange: ワードを半分に切って、その上下を入れ替え  Quarter Exchange:ハーフ・ワード内でその半分(1/4)を入れ替え
  • 6. parity ワード中の 各ビットの XORを取る 1のビットが奇数個:1 1のビットが偶数個:0 シリアル通信で使うかも… Verilog記述 (^ reg_op1) 前置きの^ :リダクション XOR。各ビットのXORを取る 前置きの| :リダクション OR。各ビットのORを取る。0判定 前置きの& :リダクション AND。各ビットのANDを取る。0xFF判定
  • 7. 遅いclz Count Leading Zeros ワード中で、MSB(最左)から0が何個 続くかを数える。 一番上(左)の1の位置がわかる。 この実装だと、32個の比較の後、 結果が得られる。 遅い ↓ クロック周波数の足を引っ張る Verilog記述→ /* clz 24bit for pmmp0, Slow*/ assign nsh_pmmp[5:0] = pmmp0[23] ? 6'd0 :( pmmp0[22] ? 6'd1 :( pmmp0[21] ? 6'd2 :( pmmp0[20] ? 6'd3 :( pmmp0[19] ? 6'd4 :( pmmp0[18] ? 6'd5 :( pmmp0[17] ? 6'd6 :( pmmp0[16] ? 6'd7 :( pmmp0[15] ? 6'd8 :( pmmp0[14] ? 6'd9 :( pmmp0[13] ? 6'd10 :( pmmp0[12] ? 6'd11 :( pmmp0[11] ? 6'd12 :( pmmp0[10] ? 6'd13 :( pmmp0[9] ? 6'd14 :( pmmp0[8] ? 6'd15 :( pmmp0[7] ? 6'd16 :( pmmp0[6] ? 6'd17 :( pmmp0[5] ? 6'd18 :( pmmp0[4] ? 6'd19 :( pmmp0[3] ? 6'd20 :( pmmp0[2] ? 6'd21 :( pmmp0[1] ? 6'd22 :( pmmp0[0] ? 6'd23 : 6'd24 )))))))))))))))))))))));
  • 8. 「ハッカーのたのしみ」本を読むべし エエこと書いてある! Hacker's Delight (原書は2nd Editionになっている) 出版社: エスアイビーアクセス (2004/09) ISBN-10: 4434046683 clz,clz,population は、この本で勉強
  • 9. 速い clz Count Leading Zeros ワード中で、MSB(最左)から0が何個 続くかを数える。 一番上(左)の1の位置がわかる。 ●判断(?)5段、 !( |(clzx0[X:Y]))演算4段 の9段の演算になる Verilog記述 //// clz wire [31:0] clzx0,clzx1,clzx2,clzx3,clzx4,clzx5,n1,n2,n3,n4,n5,xx1,xx2,xx3,xx4; assign clzx0[31:0] = reg_op1; assign xx1 = !( |(clzx0[31:16])); // & 32'hFFFF0000 assign clzx1[31:0] = xx1 ? clzx0[31-16:0] << 16 : clzx0[31:0] ; assign n1 = (xx1 ? 32'd16 : 32'd0); assign xx2 = !(|(clzx1[31:24])); assign clzx2[31:0] = xx2 ? clzx1[31-8:0] << 8 : clzx1[31:0] ; assign n2 = n1 + (xx2 ? 32'd8 : 32'd0); assign xx3 = !(|(clzx2[31:28])); assign clzx3[31:0] = xx3 ? clzx2[31-4:0] << 4 : clzx2[31:0] ; assign n3 = n2 + (xx3 ? 32'd4 : 32'd0); assign xx4 = !(|(clzx3[31:30])); assign clzx4[31:0] = xx4 ? clzx3[31-2:0] << 2 : clzx3[31:0] ; assign n4 = n3 + (xx4 ? 32'd2 : 32'd0); assign n5 = n4 + !clzx4[31]; //add inverse of MSB wire [31:0] clz_res = !(|(reg_op1))?
  • 10. 最下位(?) 細粒度 並列 assign xx1 = !( |(clzx0[31:16])); assign clzx1[31:0] = xx1 ? clzx0[31-16:0] << 16 : clzx0[31:0] ; assign n1 = (xx1 ? 32'd16 : 32'd0); ●clzx1 と n1 は、同時に計算される ● n1 が参照されるのは、clzx1 … より 少し後だが ●assign clzx1[31:0] = xx1 ? clzx0[15:0] << 16 は、配線の接続となって、シフト演算されない(ことを願う) { clzx0[15:0], 16'd0 } … とか書いた方がいいか
  • 11. ビット選択と線(ワイヤ) ワード中で、MSB(最左)から0が何個 続くかを数える。 一番上(左)の1の位置がわかる。 Verilog記述 assign xx1 = !( |(clzx0[31:16])); ↓あまり良くないことが起きるかも…(通常なら、最適化されて↑になるはず) assign xx1 = !( clzx0[31:0] & 32'hFFFF0000) 1 1 1 1
  • 12. ctz Count Trailing Zero ワード中で、LSB(最右)から0が何個 続くかを数える。 一番下(右)の1の位置がわかる。 clzと同様 Verilog記述 /// ctz wire [31:0] ctzx0;wire [15:0] ctzx1; wire [7:0] ctzx2; wire [3:0] ctzx3; wire [1:0] ctzx4; wire [5:0] m1, m2, m3, m4, m5; wire yy1,yy2,yy3,yy4; assign ctzx0[31:0] = reg_op1; assign yy1 = !( |(ctzx0[15:0])); // & 32'h0000FFFF assign ctzx1[15:0] = yy1 ? (ctzx0[31:16]) : ctzx0[15:0] ; assign m1 = (yy1 ? 32'd16 : 32'd0); assign yy2 = !(|(ctzx1[7:0])); // & 32'h000000FF assign ctzx2[7:0] = yy2 ? (ctzx1[15:8]) : ctzx1[7:0] ; assign m2 = m1 + (yy2 ? 32'd8 : 32'd0); assign yy3 = !(|(ctzx2[3:0])); // & 32'h000000F assign ctzx3[3:0] = yy3 ? (ctzx2[7:4]) : ctzx2[3:0] ; assign m3 = m2 + (yy3 ? 32'd4 : 32'd0); assign yy4 = !(|(ctzx3[1:0])); // & 32'h0000003 assign ctzx4[1:0] = yy4 ? (ctzx3[3:2]) : ctzx3[1:0] ; assign m4 = m3 + (yy4 ? 32'd2 : 32'd0); assign m5 = m4 + !ctzx4[0]; //add inverse of LSB wire [31:0] ctz_res = !(|(reg_op1)) ? 32'd32 : m5;
  • 13. population ワード中の 1のビットの 数を数える Verilog記述 //// population wire [31:0] popx0, popx1, popx2, popx3, popx4, pop_res; assign popx0 = reg_op1; assign popx1 = (popx0 & 32'h55555555) + ((popx0 >> 1)& 32'h55555555); assign popx2 = (popx1 & 32'h33333333) + ((popx1 >> 2)& 32'h33333333); assign popx3 = (popx2 & 32'h0f0f0f0f) + ((popx2 >> 4)& 32'h0f0f0f0f); assign popx4 = (popx3 & 32'h00ff00ff) + ((popx3 >> 8)& 32'h00ff00ff); assign pop_r = (popx4 & 32'h0000ffff) + ((popx4 >>16)& 32'h0000ffff);
  • 14. bit reverse ワード中のビットの順序を逆にする Verilog記述 //// bit reverse alu_brev <= {reg_op1[0],reg_op1[1],reg_op1[2],reg_op1[3], reg_op1[4],reg_op1[5],reg_op1[6],reg_op1[7], reg_op1[8],reg_op1[9],reg_op1[10],reg_op1[11], reg_op1[12],reg_op1[13],reg_op1[14],reg_op1[15], reg_op1[16],reg_op1[17],reg_op1[18],reg_op1[19], reg_op1[20],reg_op1[21],reg_op1[22],reg_op1[23], reg_op1[24],reg_op1[25],reg_op1[26],reg_op1[27], reg_op1[28],reg_op1[29],reg_op1[30],reg_op1[31] };
  • 15. Half Exchange,Quarter Exchange ●Halt Exchange: ワードを半分に切って、その上下を入れ替え 元 3,2 , 1,0 3,2 ⇔ 1,0 結果1,0 , 3,2 ●Quarter Exchange:ハーフ・ワード内でその半分(1/4)を入れ替え 元 3,2 , 1,0 3⇔2 , 1⇔0 結果 2,3 , 0,1 Verilog記述 //// Half Exchange alu_hexg <= {reg_op1[15:0],reg_op1[31:16]}; //// Quarter Exchange alu_qexg <= {reg_op1[23:16],reg_op1[31:24],reg_op1[7:0],reg_op1[15:8]}; //// word Ex (おまけ) alu_wexg <= {reg_op1[7:0],reg_op1[15:8],reg_op1[23:16],reg_op1[31:24]}; ワード中のバイトを逆順にするには、 H-Exg と Q-Exg を行う