From 48d52ca7ea3214102d6dc878806bd0eb1f57bf06 Mon Sep 17 00:00:00 2001 From: Minseong Jang Date: Tue, 12 Nov 2024 16:33:58 +0000 Subject: [PATCH] Update assignment 5 grading scripts --- scripts/gemmini/unit_test.sh | 2 +- scripts/gemmini/unit_tests/mesh/test_mesh.py | 74 +++++------ .../unit_tests/transposer/test_transposer.py | 120 ++++++++++++------ 3 files changed, 123 insertions(+), 73 deletions(-) diff --git a/scripts/gemmini/unit_test.sh b/scripts/gemmini/unit_test.sh index 7e958d5..47b03d1 100755 --- a/scripts/gemmini/unit_test.sh +++ b/scripts/gemmini/unit_test.sh @@ -39,7 +39,7 @@ pip3 install -r $CURR_DIR/requirements.txt cd $CURR_DIR/unit_tests/$1 make clean make WAVES=1 | tee $CURR_DIR/$LOG_FILE -echo "To see the waveform, go to the directory: $CURR_DIR/unit_tests/$1 and check \`$1_top.fst\` file with gtkwave." +echo "To see the waveform, go to the directory: $CURR_DIR/unit_tests/$1 and check \`${TARGET_NAME}_top.fst\` file with gtkwave." FAILED_COUNT=$(grep -o "failed" $CURR_DIR/$LOG_FILE | wc -l) if [ $FAILED_COUNT -eq 0 ]; then diff --git a/scripts/gemmini/unit_tests/mesh/test_mesh.py b/scripts/gemmini/unit_tests/mesh/test_mesh.py index 0d4dcd2..4932968 100644 --- a/scripts/gemmini/unit_tests/mesh/test_mesh.py +++ b/scripts/gemmini/unit_tests/mesh/test_mesh.py @@ -13,7 +13,6 @@ gemmini_unit_tb_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) sys.path.append(gemmini_unit_tb_dir) -random.seed(0) # Dataflow discriminant OS = 0 @@ -86,7 +85,7 @@ def concatenate_data(data: list, width): return data_concat -def decopmose_data(data: BinaryValue, width): +def decompose_data(data: BinaryValue, width): data_list = [] data_len = len(data.binstr) num_data = data_len // width @@ -106,6 +105,9 @@ async def ws_simple(dut): """ Test Weight Stationary with ones """ + random.seed(0) + np.random.seed(0) + np.set_printoptions(linewidth=200) tb = TB(dut) await tb.reset() @@ -119,10 +121,10 @@ async def ws_simple(dut): golden_output_data = np.matmul(activation, weight) + bias cocotb.log.info("== Weight Stationary testcase1 ==") - cocotb.log.info(f"Input data: {activation}") - cocotb.log.info(f"Weight data: {weight}") - cocotb.log.info(f"Bias data: {bias}") - cocotb.log.info(f"Expected Output data: {golden_output_data}") + cocotb.log.info(f"Input data:\n{activation}") + cocotb.log.info(f"Weight data:\n{weight}") + cocotb.log.info(f"Bias data:\n{bias}") + cocotb.log.info(f"Expected output data:\n{golden_output_data}") output_data = [] @@ -220,7 +222,7 @@ async def ws_simple(dut): tb.in_col_ctrl_propagate.value = concatenate_data([REG1] * 16, 1) if tb.out_col_ctrl_propagate.value.binstr == "1111111111111111": - data_decomposed = decopmose_data(tb.out_col_data_b.value, 20) + data_decomposed = decompose_data(tb.out_col_data_b.value, 20) output_data.append(data_decomposed) await RisingEdge(dut.clk) @@ -229,11 +231,11 @@ async def ws_simple(dut): for i in range(24): if tb.out_col_ctrl_propagate.value.binstr == "1111111111111111": - data_decomposed = decopmose_data(tb.out_col_data_b.value, 20) + data_decomposed = decompose_data(tb.out_col_data_b.value, 20) output_data.append(data_decomposed) await RisingEdge(dut.clk) - tb.log.info(f"output_data: {output_data}") + cocotb.log.info(f"Output data (skewed form):\n{np.array(output_data)}") # Check output for i in range(16): @@ -246,6 +248,9 @@ async def ws_random(dut): """ Test Weight Stationary with random inputs """ + random.seed(0) + np.random.seed(0) + np.set_printoptions(linewidth=200) tb = TB(dut) await tb.reset() @@ -259,10 +264,10 @@ async def ws_random(dut): golden_output_data = np.matmul(activation, weight) + bias cocotb.log.info("== Weight Stationary testcase1 ==") - cocotb.log.info(f"Input data: {activation}") - cocotb.log.info(f"Weight data: {weight}") - cocotb.log.info(f"Bias data: {bias}") - cocotb.log.info(f"Expected Output data: {golden_output_data}") + cocotb.log.info(f"Input data:\n{activation}") + cocotb.log.info(f"Weight data:\n{weight}") + cocotb.log.info(f"Bias data:\n{bias}") + cocotb.log.info(f"Expected output data:\n{golden_output_data}") output_data = [] @@ -360,7 +365,7 @@ async def ws_random(dut): tb.in_col_ctrl_propagate.value = concatenate_data([REG1] * 16, 1) if tb.out_col_ctrl_propagate.value.binstr == "1111111111111111": - data_decomposed = decopmose_data(tb.out_col_data_b.value, 20) + data_decomposed = decompose_data(tb.out_col_data_b.value, 20) output_data.append(data_decomposed) await RisingEdge(dut.clk) @@ -369,11 +374,11 @@ async def ws_random(dut): for i in range(24): if tb.out_col_ctrl_propagate.value.binstr == "1111111111111111": - data_decomposed = decopmose_data(tb.out_col_data_b.value, 20) + data_decomposed = decompose_data(tb.out_col_data_b.value, 20) output_data.append(data_decomposed) await RisingEdge(dut.clk) - tb.log.info(f"output_data: {output_data}") + cocotb.log.info(f"Output data (skewed form):\n{np.array(output_data)}") # Check output for i in range(16): @@ -386,6 +391,9 @@ async def os_simple(dut): """ Test Output Stationary with ones """ + random.seed(0) + np.random.seed(0) + np.set_printoptions(linewidth=200) tb = TB(dut) await tb.reset() @@ -398,10 +406,9 @@ async def os_simple(dut): golden_output_data = np.matmul(activation, weight) cocotb.log.info("== Output Stationary testcase1 ==") - - cocotb.log.info(f"Input data: {activation}") - cocotb.log.info(f"Weight data: {weight}") - cocotb.log.info(f"Expected Output data: {golden_output_data}") + cocotb.log.info(f"Input data:\n{activation}") + cocotb.log.info(f"Weight data:\n{weight}") + cocotb.log.info(f"Expected output data:\n{golden_output_data}") output_data = [] @@ -443,8 +450,6 @@ async def os_simple(dut): col_data[j] = weight[i - j][j] propagate[j] = REG1 if j <= i else REG2 - # tb.log.info(f"i: {i}, row_data: {row_data}, col_data: {col_data}, propagete: {propagate}") - tb.in_row_data_valids.value = concatenate_data(data_valids, 1) tb.in_col_data_valids.value = concatenate_data(data_valids, 1) tb.in_row_data_a.value = concatenate_data(row_data, 8) @@ -465,8 +470,6 @@ async def os_simple(dut): col_data[j] = weight[16 - (j - i)][j] if j > i else 0 propagate[j] = REG1 if j > i else REG2 - # tb.log.info(f"i: {i}, row_data: {row_data}, col_data: {col_data}, propagete: {propagate}") - tb.in_row_data_valids.value = concatenate_data(data_valids, 1) tb.in_col_data_valids.value = concatenate_data(data_valids, 1) tb.in_row_data_a.value = concatenate_data(row_data, 8) @@ -481,20 +484,24 @@ async def os_simple(dut): tb.in_col_ctrl_propagate.value = concatenate_data([REG2] * 16, 1) for i in range(64): - output_data.append(decopmose_data(tb.out_col_data_d.value, 20)) + output_data.append(decompose_data(tb.out_col_data_d.value, 20)) await RisingEdge(dut.clk) output_data = output_data[2:] - tb.log.info(f"output_data: {output_data}") + cocotb.log.info(f"Output data (skewed form):\n{np.array(output_data)}") for i in range(16): for j in range(16): assert golden_output_data[i][j] == output_data[15 - i + j][j] + @cocotb.test(timeout_time=10, timeout_unit="ms") async def os_random(dut): """ Test Output Stationary with random numbers """ + random.seed(0) + np.random.seed(0) + np.set_printoptions(linewidth=200) tb = TB(dut) await tb.reset() @@ -507,10 +514,9 @@ async def os_random(dut): golden_output_data = np.matmul(activation, weight) cocotb.log.info("== Output Stationary testcase1 ==") - - cocotb.log.info(f"Input data: {activation}") - cocotb.log.info(f"Weight data: {weight}") - cocotb.log.info(f"Expected Output data: {golden_output_data}") + cocotb.log.info(f"Input data:\n{activation}") + cocotb.log.info(f"Weight data:\n{weight}") + cocotb.log.info(f"Expected output data:\n{golden_output_data}") output_data = [] @@ -552,8 +558,6 @@ async def os_random(dut): col_data[j] = weight[i - j][j] propagate[j] = REG1 if j <= i else REG2 - # tb.log.info(f"i: {i}, row_data: {row_data}, col_data: {col_data}, propagete: {propagate}") - tb.in_row_data_valids.value = concatenate_data(data_valids, 1) tb.in_col_data_valids.value = concatenate_data(data_valids, 1) tb.in_row_data_a.value = concatenate_data(row_data, 8) @@ -574,8 +578,6 @@ async def os_random(dut): col_data[j] = weight[16 - (j - i)][j] if j > i else 0 propagate[j] = REG1 if j > i else REG2 - # tb.log.info(f"i: {i}, row_data: {row_data}, col_data: {col_data}, propagete: {propagate}") - tb.in_row_data_valids.value = concatenate_data(data_valids, 1) tb.in_col_data_valids.value = concatenate_data(data_valids, 1) tb.in_row_data_a.value = concatenate_data(row_data, 8) @@ -590,10 +592,10 @@ async def os_random(dut): tb.in_col_ctrl_propagate.value = concatenate_data([REG2] * 16, 1) for i in range(64): - output_data.append(decopmose_data(tb.out_col_data_d.value, 20)) + output_data.append(decompose_data(tb.out_col_data_d.value, 20)) await RisingEdge(dut.clk) output_data = output_data[2:] - tb.log.info(f"output_data: {output_data}") + cocotb.log.info(f"Output data (skewed form):\n{np.array(output_data)}") for i in range(16): for j in range(16): diff --git a/scripts/gemmini/unit_tests/transposer/test_transposer.py b/scripts/gemmini/unit_tests/transposer/test_transposer.py index 9f7701d..0bdaa4f 100644 --- a/scripts/gemmini/unit_tests/transposer/test_transposer.py +++ b/scripts/gemmini/unit_tests/transposer/test_transposer.py @@ -2,6 +2,7 @@ import random import numpy as np +from itertools import product import cocotb from cocotb.clock import Clock @@ -10,7 +11,7 @@ from cocotb.binary import BinaryValue -random.seed(0) +DIM = 16 class TB(object): @@ -40,58 +41,105 @@ async def reset(self): def concatenate_data(data: list, width): data_concat = 0 bitmask = (1 << width) - 1 + for i in range(len(data)): data_concat |= (int(data[i]) << (width * i)) & (bitmask << (width * i)) + return data_concat -def decopmose_data(data: BinaryValue, width): +def decompose_data(data: BinaryValue, width): data_list = [] data_len = len(data.binstr) num_data = data_len // width + for i in reversed(range(num_data)): - data_list.append( - BinaryValue(data.binstr[i * width : (i + 1) * width]).signed_integer - ) + data_list.append(BinaryValue(data.binstr[i * width : (i + 1) * width]).signed_integer) + return data_list @cocotb.test(timeout_time=10, timeout_unit="ms") -async def transpose_test1(dut): +async def transpose_test(dut): """ - Weight Stationary testcase1 + Testcase. """ + random.seed(0) + np.set_printoptions(linewidth=200) tb = TB(dut) await tb.reset() await ClockCycles(dut.clk, 10) - # Generate inputs randomly - input_data = [[random.randint(-128, 127) for _ in range(16)] for _ in range(16)] - - cocotb.log.info("== Tranaposer testcase1 ==") - cocotb.log.info(f"Input data: {input_data}") - - output_data = np.transpose(input_data) - cocotb.log.info(f"Expected Output data: {output_data}") - - for i in range(16): - in_row_data = concatenate_data(input_data[i], 8) - tb.in_row_data.value = in_row_data - tb.in_row_valid.value = 1 - await RisingEdge(dut.clk) - for i in range(16): - tb.in_row_valid.value = 0 - tb.in_row_data.value = 0 - await RisingEdge(dut.clk) - - tb.in_row_valid.value = 1 - tb.in_row_data.value = 0 - - await FallingEdge(dut.clk) - - out_col_data = np.array(decopmose_data(tb.out_col_data.value, 8)) - assert np.array_equal(out_col_data, output_data[i]) - cocotb.log.info(f"Output data: {out_col_data}") - - await RisingEdge(dut.clk) + # Generate random matrices + A = np.array([[random.randint(-128, 127) for _ in range(DIM)] for _ in range(DIM)]) + B = np.array([[random.randint(-128, 127) for _ in range(DIM)] for _ in range(DIM)]) + + A_t = np.transpose(A) + B_t = np.transpose(B) + + cocotb.log.info("== Transposer testcase ==") + + cocotb.log.info(f"A (input 1):\n{A}") + cocotb.log.info(f"A transposed (expected output 1):\n{A_t}") + + cocotb.log.info(f"B (input 2):\n{B}") + cocotb.log.info(f"B transposed (expected output 2):\n{B_t}") + + for (i, (delay1, delay2, delay3)) in enumerate(product([False, True], repeat=3)): + cocotb.log.info(f"Config {i}:") + if i == 0: + cocotb.log.info("No delay") + else: + if delay1: + cocotb.log.info("Add a delay for inputting A") + if delay2: + cocotb.log.info("Add a delay for outputting A and inputting B") + if delay3: + cocotb.log.info("Add a delay for outputting B") + + A_o, B_o = [], [] + + for i in range(DIM): + # Add a delay for inputting A + if delay1: + tb.in_row_valid.value = 0 + await RisingEdge(dut.clk) + + tb.in_row_valid.value = 1 + tb.in_row_data.value = concatenate_data(A[i], 8) + await RisingEdge(dut.clk) + + for i in range(DIM): + # Add a delay for outputting A and inputting B + if delay2: + tb.in_row_valid.value = 0 + await RisingEdge(dut.clk) + + tb.in_row_valid.value = 1 + tb.in_row_data.value = concatenate_data(B[i], 8) + await FallingEdge(dut.clk) + + A_o.append(decompose_data(tb.out_col_data.value, 8)) + await RisingEdge(dut.clk) + + A_o = np.array(A_o) + cocotb.log.info(f"A transposed (output):\n{A_o}") + assert np.array_equal(A_o, A_t) + + for i in range(DIM): + # Add a delay for outputting B + if delay3: + tb.in_row_valid.value = 0 + await RisingEdge(dut.clk) + + tb.in_row_valid.value = 1 + tb.in_row_data.value = 0 + await FallingEdge(dut.clk) + + B_o.append(decompose_data(tb.out_col_data.value, 8)) + await RisingEdge(dut.clk) + + B_o = np.array(B_o) + cocotb.log.info(f"B transposed (output):\n{B_o}") + assert np.array_equal(B_o, B_t)