【コンピューティング】RAMの仕組みを再現する②

こんにちは、インフラエンジニアです。

前回は入力したビットを受け取る関数とNAND演算を行うコードを作成しました。
今回はRAMのNANDゲートを再現していきます。

↓前回
https://qiita.com/yosuke8291/items/8b0ff3253ec3cabcfa67

↓参考
https://www.youtube.com/watch?v=SSjeGjhwBo0

#### NANDゲートを再現する

##### NANDゲート
参考の動画によると、RAMの入出力では入力値は図のようなNANDゲートを通ってメモリに渡す出力値が割り出されます。
この処理が8bit分連なることで1byteのデータの配列を表します。

[入力値]
input_x、input_y

[出力値]
memBit

![スクリーンショット 2024-12-26 063644.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3953197/b188db8f-3abf-e1cb-5a58-9d08f3e1ddab.png)


それぞれのNANDゲートの出力値については以下のように表すことができます。
```
NAND_00 = NAND(input_x, input_y)

NAND_01 = NAND(NAND(input_x, input_y), input_y)
        = NAND(NAND_00, input_y)

NAND_02 = NAND(NAND(input_x, input_y), NAND_03)
        = NAND(NAND_00, NAND_03)      
        
NAND_03 = NAND(NAND(NAND(input_x, input_y), input_y), NAND_02)
        = NAND(NAND_01, NAND_02)
```
##### メモリに渡すビットを演算する関数
先に示した図を参考に、入力値をNAND演算してメモリに渡すビットを割り出す関数を作成します。

```c
int NAND_gate(int input_x, int input_y) {
	int NAND_00 = get_NAND(input_x, input_y);
	int NAND_01 = get_NAND(NAND_00, input_y);
	int NAND_02 = 1;//仮の初期値
	int NAND_03 = 1;//仮の初期値

        int prev_NAND_02;
        int prev_NAND_03;

do{
        prev_NAND_02 = NAND_02;
        prev_NAND_03 = NAND_03;

        NAND_03 = get_NAND(NAND_01, NAND_02);
        NAND_02 =get_NAND(NAND_00, NAND_03);
}while(NAND_02 != prev_NAND_02 || NAND_03 != prev_NAND_03);

	int memBit = NAND_02;  
        return memBit;
}
```
#### コード全様
前回のコードと組み合わせて、8bit = 1byte のビットの配列を得るコードを作成。
※一部変数名を変更しています。
```c
#include<stdio.h>

int get_bit(const char* prompt)
{
	int bit;

	while (1)
	{
		printf("%s: ", prompt);

		if (scanf_s("%d", &bit) != 1)
		{

			if (getchar() == '\n')
			{
				printf("ERROR\n");
			}
			else
			{
				while (getchar() != '\n');

			}

			continue;
		}

		if (bit == 0 || bit == 1)
		{
			return bit;
		}

		else
		{
			printf("ERROR\n");
			while (getchar() != '\n');

		}
	}

}

int get_NAND(int a, int b)
{
	if (a == 0 && b == 0)
	{
		return 1;
	}

	if (a == 1 && b == 0)
	{
		return 1;
	}

	if (a == 0 && b == 1)
	{
		return 1;
	}

	if (a == 1 && b == 1)
	{
		return 0;
	}

	else
	{
		printf("ERROR");
		return -1;
	}
}

int NAND_gate(int input_x, int input_y) {
	int NAND_00 = get_NAND(input_x, input_y);
	int NAND_01 = get_NAND(NAND_00, input_y);
	int NAND_02 = 1;
	int NAND_03 = 1;

        int prev_NAND_02;
        int prev_NAND_03;

do{
        prev_NAND_02 = NAND_02;
        prev_NAND_03 = NAND_03;

        NAND_03 = get_NAND(NAND_01, NAND_02);
        NAND_02 =get_NAND(NAND_00, NAND_03);
}while(NAND_02 != prev_NAND_02 || NAND_03 != prev_NAND_03);

	int memBit = NAND_02;  
        return memBit;
}

int main()
{
	int bit_00 = get_bit("ビットを入力 bit_00");
	int bit_01 = get_bit("ビットを入力 bit_01");

	int bit_02 = get_bit("ビットを入力 bit_02");
	int bit_03 = get_bit("ビットを入力 bit_03");

	int bit_04 = get_bit("ビットを入力 bit_04");
	int bit_05 = get_bit("ビットを入力 bit_05");

	int bit_06 = get_bit("ビットを入力 bit_06");
	int bit_07 = get_bit("ビットを入力 bit_07");

	int bit_08 = get_bit("ビットを入力 bit_08");
	int bit_09 = get_bit("ビットを入力 bit_09");

	int bit_10 = get_bit("ビットを入力 bit_10");
	int bit_11 = get_bit("ビットを入力 bit_11");

	int bit_12 = get_bit("ビットを入力 bit_12");
	int bit_13 = get_bit("ビットを入力 bit_13");

	int bit_14 = get_bit("ビットを入力 bit_14");
	int bit_15 = get_bit("ビットを入力 bit_15");

	int memBit_00 = NAND_gate(bit_00, bit_01);
	int memBit_01 = NAND_gate(bit_02, bit_03);
	int memBit_02 = NAND_gate(bit_04, bit_05);
	int memBit_03 = NAND_gate(bit_06, bit_07);
	int memBit_04 = NAND_gate(bit_08, bit_09);
	int memBit_05 = NAND_gate(bit_10, bit_11);
	int memBit_06 = NAND_gate(bit_12, bit_13);
	int memBit_07 = NAND_gate(bit_14, bit_15);

	printf("結果：%d%d%d%d%d%d%d%d\n", memBit_00, memBit_01, memBit_02, memBit_03, memBit_04, memBit_05, memBit_06, memBit_07);

		return 0;
}
```

メイン処理がかなり力技になっています。
見やすいっちゃ見やすいけど。

後で修正します。
※繰り返し処理入れたり、バッファにbitを入れるようにしたり。

##### 動作確認
動きとしてはこんな感じ
![スクリーンショット 2025-01-11 094050.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3953197/83951abe-7fc4-20c6-52ec-1a7e2097a62e.png)


今回はRAMのNANDゲートの再現をしました。
参考動画のこの続きの部分が、まだちょっと勉強中なので、続きはいつか書きます。