mmserv

Minimum Mean Square Error detection on RISC-V Vector Extention
git clone https://git.ea.contact/mmserv
Log | Files | Refs | README

commit 682afabb30308f125ac566eca89c1401085c0146
parent b2eb2a6ee415168d82e791c85825047d8f1dbf10
Author: Egor Achkasov <eaachkasov@edu.hse.ru>
Date:   Fri,  8 Nov 2024 13:02:56 +0100

Initial ara changes

Diffstat:
M.gitignore | 4++--
MGNUmakefile | 6+++---
Rinc/define.h -> include/define.h | 0
Rinc/mmserv.h -> include/mmserv.h | 0
Mmain.c | 13++++++++-----
Ascript/gen_data.py | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rscripts/mmse.py -> script/mmse.py | 0
Rscripts/mmse_nosqrt.py -> script/mmse_nosqrt.py | 0
Rscripts/simulation-run.fish -> script/simulation-run.fish | 0
Ascript/util.py | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rscripts/viz_compare_x.py -> script/viz_compare_x.py | 0
Dscripts/gen_data.py | 90-------------------------------------------------------------------------------
Dscripts/util.py | 59-----------------------------------------------------------
Msrc/mmserv.c | 8++++----
14 files changed, 172 insertions(+), 163 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -5,4 +5,5 @@ build obj .vscode *__pycache__* -.gdb_history -\ No newline at end of file +.gdb_history +*.o diff --git a/GNUmakefile b/GNUmakefile @@ -1,7 +1,7 @@ CC = gcc -CFLAGS = -Iinc -fno-builtin -Wall -Wextra +CFLAGS = -Iinclude -fno-builtin -Wall -Wextra OBJDIR = obj -BUILDDIR = build +BUILDDIR = . SRC = $(wildcard src/*.c) OBJ = $(SRC:src/%.c=$(OBJDIR)/%.o) @@ -31,7 +31,7 @@ $(OBJDIR)/main.o: main.c $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -rf $(OBJDIR)/* $(BUILDDIR)/* + rm -rf $(OBJDIR)/* $(BUILDDIR)/mmse .PHONY: all dbg clean diff --git a/inc/define.h b/include/define.h diff --git a/inc/mmserv.h b/include/mmserv.h diff --git a/main.c b/main.c @@ -1,4 +1,4 @@ -#include "inc/mmserv.h" +#include "include/mmserv.h" int main() { uint32_t i, j, k; @@ -8,10 +8,13 @@ int main() { data_t H_raw[NUM_RX_ANT][NUM_TX_ANT][NUM_SC][2]; /* Channel */ data_t R_raw[NUM_TX_ANT][NUM_TX_ANT][NUM_SC][2]; /* Noise covariance matrix */ data_t y_raw[NUM_RX_ANT][NUM_SC][2]; /* Received signal */ - load_data("data\\x.bin", NUM_TX_ANT*NUM_SC*2, x_raw); - load_data("data\\H.bin", NUM_RX_ANT*NUM_TX_ANT*NUM_SC*2, H_raw); - load_data("data\\R.bin", NUM_TX_ANT*NUM_RX_ANT*NUM_SC*2, R_raw); - load_data("data\\y.bin", NUM_RX_ANT*NUM_SC*2, y_raw); + +#ifndef ARA + load_data("data/x.bin", NUM_TX_ANT*NUM_SC*2, x_raw); + load_data("data/H.bin", NUM_RX_ANT*NUM_TX_ANT*NUM_SC*2, H_raw); + load_data("data/R.bin", NUM_TX_ANT*NUM_RX_ANT*NUM_SC*2, R_raw); + load_data("data/y.bin", NUM_RX_ANT*NUM_SC*2, y_raw); +#endif /* Cast the data into complex data structures */ complex x[NUM_TX_ANT][NUM_SC]; diff --git a/script/gen_data.py b/script/gen_data.py @@ -0,0 +1,96 @@ +#!/usr/bin/python + +from util import read_defines, interleave + +import numpy as np +from numpy.random import random, normal +from sys import argv +from os import path, makedirs + +if "--help" in argv: + print("Usage: python scripts/gen_data.py [--txt] [--bin] [--s]") + print(" --txt: write the data/*.txt files") + print(" --bin: write the data/*.bin files") + print(" --s: print the .S file to stdout") + exit(0) + +# Change these flags to control the output +WRITE_DATA_TXT = "--txt" in argv +WRITE_DATA_BIN = "--bin" in argv +WRITE_DATA_S = "--s" in argv or len(argv) == 1 + +NUM_RX_ANT, NUM_TX_ANT, NUM_SC = read_defines() +NOISE_STD_DEVIATION = np.sqrt(.5) / 100 # noise standard deviation + +# Transmitter signal +x = random((NUM_TX_ANT, NUM_SC)) \ + + 1.j * random((NUM_TX_ANT, NUM_SC)) +x = (x - 0.5 - 0.5j) * 2 # scale it from [0, 1] to [-1, 1] +# Channel +H = random((NUM_RX_ANT, NUM_TX_ANT, NUM_SC)) \ + + 1.j * random((NUM_RX_ANT, NUM_TX_ANT, NUM_SC)) +H = (H - 0.5 - 0.5j) * 2 # scale it from [0, 1] to [-1, 1] +# Noise +n = normal(0, NOISE_STD_DEVIATION, (NUM_RX_ANT, NUM_SC)) \ + + 1.j * normal(0, NOISE_STD_DEVIATION, (NUM_RX_ANT, NUM_SC)) +# Received signal +y = np.einsum("ijk,jk->ik", H, x) + n + +# Noise covariance matrix +R = np.eye(NUM_TX_ANT, NUM_TX_ANT, dtype=np.complex64) * NOISE_STD_DEVIATION**2 + +# Cast the complex data to int16 +x_data = interleave(x) +H_data = interleave(H) +R_data = interleave(R) +y_data = interleave(y) +data_tuple = (x_data, H_data, R_data, y_data) + + +class Section: + def __init__(self, name, source, align, sizeof, length, duplicate=False): + self.name = name + self.source = source + self.align = align + self.sizeof = sizeof + self.length = length + self.duplicate = duplicate + + +sections = [ + Section("x_raw", "data/x.txt", "3", 32, x.size * 2), + Section("H_raw", "data/H.txt", "3", 32, H.size * 2), + Section("R_raw", "data/R.txt", "3", 32, R.size * 2), + Section("y_raw", "data/y.txt", "3", 32, y.size * 2), +] + +# Create "data" directory if it does not exist +if WRITE_DATA_BIN or WRITE_DATA_TXT: + data_dir = path.join(path.dirname(__file__), "..", "data") + if not path.exists(data_dir): + makedirs(data_dir) + +if WRITE_DATA_TXT: + for data, sec in zip(data_tuple, sections): + with open(sec.source, "w") as f: + for sample in data: + f.write(f"{sample}\n") + +if WRITE_DATA_BIN: + for data, sec in zip(data_tuple, sections): + with open(sec.source.replace(".txt", ".bin"), "wb") as f: + f.write(data.tobytes()) + +if WRITE_DATA_S: + print(".section .data,\"aw\",@progbits") + for data, sec in zip(data_tuple, sections): + print(f".global {sec.name}") + print(f"{sec.name}:") + for sample in data: + bs = sample.tobytes() + for i in range(0, len(bs), 4): + s = "" + for n in range(4): + s += "%02x" % bs[i+3-n] + print(" .word 0x%s" % s) + diff --git a/scripts/mmse.py b/script/mmse.py diff --git a/scripts/mmse_nosqrt.py b/script/mmse_nosqrt.py diff --git a/scripts/simulation-run.fish b/script/simulation-run.fish diff --git a/script/util.py b/script/util.py @@ -0,0 +1,59 @@ +from os import path +import numpy as np + + +def read_defines(): + """Read the defines from the define.h file + + Returns: + int: Number of receive antennas + int: Number of transmit antennas + int: Number of subcarriers + """ + with open(path.join(path.dirname(__file__), "..", "include", "define.h"), "r") as f: + lines = f.read().split("\n") + for line in lines: + if line.startswith("#define NUM_RX_ANT "): + NUM_RX_ANT = int(line[19:]) + if line.startswith("#define NUM_TX_ANT "): + NUM_TX_ANT = int(line[19:]) + if line.startswith("#define NUM_SC "): + NUM_SC = int(line[15:]) + + # Assert that all the defines are read + assert NUM_RX_ANT + assert NUM_TX_ANT + assert NUM_SC + + return NUM_RX_ANT, NUM_TX_ANT, NUM_SC + + +def interleave(data: np.ndarray) -> np.ndarray: + """Cast a np.complex64 array to np.float32 array. + + Args: + data (np.ndarray): The complex data to be casted. Dtype: np.complex64 + + Returns: + np.ndarray: The interleaved data. Dtype: np.float32 + """ + res = np.empty(2 * data.size, dtype=np.float32) + res[0::2] = data.flatten().real.astype(np.float32) + res[1::2] = data.flatten().imag.astype(np.float32) + return res + + +def deinterleave(data: np.ndarray, shape: tuple) -> np.ndarray: + """Cast a np.float32 array to np.complex64 array. + + Args: + data (np.ndarray): The interleaved data to be casted. Dtype: np.float32 + shape (tuple): The shape of the deinterleaved data. + + Returns: + np.ndarray: The deinterleaved data. Dtype: np.complex64 + """ + res = np.empty(shape, np.complex64) + res.real = data[0::2].reshape(shape) + res.imag = data[1::2].reshape(shape) + return res diff --git a/scripts/viz_compare_x.py b/script/viz_compare_x.py diff --git a/scripts/gen_data.py b/scripts/gen_data.py @@ -1,90 +0,0 @@ -#!/usr/bin/python - -from util import read_defines, interleave - -import numpy as np -from numpy.random import random, normal -from sys import argv -from os import path, makedirs - -if "--help" in argv: - print("Usage: python scripts/gen_data.py [--txt] [--bin] [--s]") - print(" --txt: write the data/*.txt files") - print(" --bin: write the data/*.bin files") - print(" --s: print the .S file to stdout") - exit(0) - -# Change these flags to control the output -WRITE_DATA_TXT = "--txt" in argv -WRITE_DATA_BIN = "--bin" in argv -WRITE_DATA_S = "--s" in argv - -NUM_RX_ANT, NUM_TX_ANT, NUM_SC = read_defines() -NOISE_STD_DEVIATION = np.sqrt(.5) / 100 # noise standard deviation - -# Transmitter signal -x = random((NUM_TX_ANT, NUM_SC)) \ - + 1.j * random((NUM_TX_ANT, NUM_SC)) -x = (x - 0.5 - 0.5j) * 2 # scale it from [0, 1] to [-1, 1] -# Channel -H = random((NUM_RX_ANT, NUM_TX_ANT, NUM_SC)) \ - + 1.j * random((NUM_RX_ANT, NUM_TX_ANT, NUM_SC)) -H = (H - 0.5 - 0.5j) * 2 # scale it from [0, 1] to [-1, 1] -# Noise -n = normal(0, NOISE_STD_DEVIATION, (NUM_RX_ANT, NUM_SC)) \ - + 1.j * normal(0, NOISE_STD_DEVIATION, (NUM_RX_ANT, NUM_SC)) -# Received signal -y = np.einsum("ijk,jk->ik", H, x) + n - -# Noise covariance matrix -R = np.eye(NUM_TX_ANT, NUM_TX_ANT, dtype=np.complex64) * NOISE_STD_DEVIATION**2 - -# Cast the complex data to int16 -x_data = interleave(x) -H_data = interleave(H) -R_data = interleave(R) -y_data = interleave(y) -data_tuple = (x_data, H_data, R_data, y_data) - - -class Section: - def __init__(self, name, source, align, sizeof, length, duplicate=False): - self.name = name - self.source = source - self.align = align - self.sizeof = sizeof - self.length = length - self.duplicate = duplicate - - -sections = [ - Section("x", "data/x.txt", "3", 32, x.size * 2), - Section("H", "data/H.txt", "3", 32, H.size * 2), - Section("R", "data/R.txt", "3", 32, R.size * 2), - Section("y", "data/y.txt", "3", 32, y.size * 2), -] - -# Create "data" directory if it does not exist -if WRITE_DATA_BIN or WRITE_DATA_TXT: - data_dir = path.join(path.dirname(__file__), "..", "data") - if not path.exists(data_dir): - makedirs(data_dir) - -if WRITE_DATA_TXT: - for data, sec in zip(data_tuple, sections): - with open(sec.source, "w") as f: - for sample in data: - f.write(f"{sample}\n") - -if WRITE_DATA_BIN: - for data, sec in zip(data_tuple, sections): - with open(sec.source.replace(".txt", ".bin"), "wb") as f: - f.write(data.tobytes()) - -if WRITE_DATA_S: - print(".section .data,\"aw\",@progbits") - for data, sec in zip(data_tuple, sections): - print(f".global {sec.name}") - print(f"{sec.name}:") - for sample in data: - print(f" .hword 0x{sample.view(np.uint16):04x} // {sample}") diff --git a/scripts/util.py b/scripts/util.py @@ -1,59 +0,0 @@ -from os import path -import numpy as np - - -def read_defines(): - """Read the defines from the define.h file - - Returns: - int: Number of receive antennas - int: Number of transmit antennas - int: Number of subcarriers - """ - with open(path.join(path.dirname(__file__), "..", "inc", "define.h"), "r") as f: - lines = f.read().split("\n") - for line in lines: - if line.startswith("#define NUM_RX_ANT "): - NUM_RX_ANT = int(line[19:]) - if line.startswith("#define NUM_TX_ANT "): - NUM_TX_ANT = int(line[19:]) - if line.startswith("#define NUM_SC "): - NUM_SC = int(line[15:]) - - # Assert that all the defines are read - assert NUM_RX_ANT - assert NUM_TX_ANT - assert NUM_SC - - return NUM_RX_ANT, NUM_TX_ANT, NUM_SC - - -def interleave(data: np.ndarray) -> np.ndarray: - """Cast a np.complex64 array to np.float32 array. - - Args: - data (np.ndarray): The complex data to be casted. Dtype: np.complex64 - - Returns: - np.ndarray: The interleaved data. Dtype: np.float32 - """ - res = np.empty(2 * data.size, dtype=np.float32) - res[0::2] = data.flatten().real.astype(np.float32) - res[1::2] = data.flatten().imag.astype(np.float32) - return res - - -def deinterleave(data: np.ndarray, shape: tuple) -> np.ndarray: - """Cast a np.float32 array to np.complex64 array. - - Args: - data (np.ndarray): The interleaved data to be casted. Dtype: np.float32 - shape (tuple): The shape of the deinterleaved data. - - Returns: - np.ndarray: The deinterleaved data. Dtype: np.complex64 - """ - res = np.empty(shape, np.complex64) - res.real = data[0::2].reshape(shape) - res.imag = data[1::2].reshape(shape) - return res diff --git a/src/mmserv.c b/src/mmserv.c @@ -1,4 +1,4 @@ -#include "mmserv.h" +#include "../include/mmserv.h" #include <stdlib.h> // for exit @@ -18,7 +18,7 @@ complex cmul(IN complex a, IN complex b) complex t; t.re = a.re * b.re - a.im * b.im; t.im = a.im * b.re + a.re * b.im; - return t; + return t; } data_t cabs2(IN complex a) { @@ -292,7 +292,7 @@ void load_data( OUT data_t *out) { FILE *fp = fopen(file, "rb"); - + if (fp == NULL) { fprintf(stderr, "Error opening file %s.\n", file); exit(8); @@ -310,7 +310,7 @@ void save_data( IN data_t x_mmse[NUM_TX_ANT][NUM_SC][2]) { FILE *fp = fopen(file, "wb"); - + if (fp == NULL) { fprintf(stderr, "Error opening file %s.\n", file); exit(8);