mikecatのアイコン画像
mikecat 2022年12月04日作成 © CC BY 4+
製作品 製作品 閲覧数 837
mikecat 2022年12月04日作成 © CC BY 4+ 製作品 製作品 閲覧数 837

CalicoCPU で Xorshift による乱数生成

CalicoCPU で Xorshift による乱数生成

自作CPU Advent Calendar 2022 4日目

CalicoCPUXorshift による乱数生成を行った。

3-Digit 7seg Board

3-Digit 7seg Board 3-Digit 7seg Board 回路図

基板設計データ | ソフトウェア

8ビットの入力値を7セグメントLEDで表示する。以下のモードがある。

  • 16進数 (左の2桁を使用)
  • 10進数 (3桁を使用)
  • 直接制御 (左の1桁を使用)
  • シリアル通信による直接制御 (3桁を使用)

方針

8bit用xorshift乱数発生アルゴリズム - Sim's blog
を参考にする。
今回の環境では周期65535 (= 2^16 - 1) がちょうどよさそうだが、この周期はこのサイトには載っていない。
そこで、「周期が16777215 (= 2^24 - 1)」をベースに、自分で適切な A, B, C の値を探索することにした。
以下のアルゴリズムを用いる。

uint8_t x, y, t; t = x ^ x << a; x = y; y ^= y >> c ^ t ^ t >> b; return z;

以下のC言語のプログラムで探索を行う。

#include <stdio.h> #include <string.h> char visited[1 << 16]; int main(void) { int a, b, c; for (a = 0; a < 8; a++) { for (b = 0; b < 8; b++) { for (c = 0; c < 8; c++) { unsigned char x = 0, y = 1, t; int count = 0; memset(visited, 0, sizeof(visited)); while (!visited[x + y * 256]) { count++; visited[x + y * 256] = 1; t = x ^ (x << a); x = y; y ^= (y >> c) ^ t ^ (t >> b); } if (count == (1 << 16) - 1) { printf("%d %d %d\n", a, b, c); } } } } return 0; }

以下の7通りの A, B, C の組が得られた。

3 2 5 3 2 7 5 1 2 5 1 3 5 4 3 7 1 2 7 6 1

今回は、この中から (A, B, C) = (5, 4, 3) を採用した。
以下のC言語のプログラムにより、出力するべき値が得られる。

#include <stdio.h> int main(void) { unsigned char x = 255, y = 0, t; int i; for (i = 0; i < 100; i++) { t = x ^ (x << 5); x = y; y ^= (y >> 3) ^ t ^ (t >> 4); printf("%03d\n", y); } return 0; }

このプログラムの出力の冒頭は、以下のようになった。

030 029 205 098 005 037 142 018 090 006

実装

以下が MikeAssembler 用のプログラムである。

target calico movi a, -1 drive 0, a ; A: x, B: y loop_start: ; t = x ^ (x << 5) mov c, a shl c, 5 xor c, a, d ; // y ^= (y >> 3) ^ t ^ (t >> 4) ; t ^= t >> 4 mov a, c shr a, 4 xor c, a, d ; t ^= y >> 3 mov a, b shr a, 3 xor c, a, d ; x = y mov a, b ; y ^= t xor b, c, d ; return y out 0, b ; proceed to next iteration movi d, loop_start jnz d, d

以下が、機械語をHEX形式で表したものである。

:10000000203F16808789C8C28EC28E080F0FC8C2D3 :100010008EC28E040F0BC8C28EC28E04C4CA4ECAD2 :040020004E52E3DF7A :00000001FF

実行結果

3-Digit 7seg Board を用いて、生成した乱数を10進数で表示する。

ここに動画が表示されます

乱数の値が計算できている。

  • mikecat さんが 2022/12/04 に 編集 をしました。 (メッセージ: 初版)
ログインしてコメントを投稿する