aboutsummaryrefslogtreecommitdiffstats
path: root/sources/api/pySoftMC
diff options
context:
space:
mode:
authorAtaberk <olgunataberk@gmail.com>2022-09-25 17:22:03 +0200
committerAtaberk <olgunataberk@gmail.com>2022-09-25 17:22:03 +0200
commitdc0b3db1b4f1895a07e5fe280ee3790e87f97b9f (patch)
treeb47203aa281bdd959def4451c84d310cd9cf2e12 /sources/api/pySoftMC
downloaddram-bender-dc0b3db1b4f1895a07e5fe280ee3790e87f97b9f.tar.gz
Initial commit
Diffstat (limited to 'sources/api/pySoftMC')
-rw-r--r--sources/api/pySoftMC/.gitignore1
-rw-r--r--sources/api/pySoftMC/Makefile36
-rw-r--r--sources/api/pySoftMC/example.py153
-rw-r--r--sources/api/pySoftMC/pySoftMC.cpp95
4 files changed, 285 insertions, 0 deletions
diff --git a/sources/api/pySoftMC/.gitignore b/sources/api/pySoftMC/.gitignore
new file mode 100644
index 0000000..f1fe8d1
--- /dev/null
+++ b/sources/api/pySoftMC/.gitignore
@@ -0,0 +1 @@
+*.so \ No newline at end of file
diff --git a/sources/api/pySoftMC/Makefile b/sources/api/pySoftMC/Makefile
new file mode 100644
index 0000000..771df53
--- /dev/null
+++ b/sources/api/pySoftMC/Makefile
@@ -0,0 +1,36 @@
+# https://stackoverflow.com/questions/4933285/how-to-determine-python-version-in-makefile
+python_version_full := $(wordlist 2,4,$(subst ., ,$(shell python3 --version 2>&1)))
+python_version := $(word 1,${python_version_full}).$(word 2,${python_version_full})
+
+program_NAME := pySoftMC
+program_CXX_SRCS := $(wildcard ../*.c) $(wildcard ../*.cpp) ./pySoftMC.cpp
+program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
+program_CXX_OBJS := ${program_CXX_OBJS:.c=.o}
+program_OBJS := $(program_CXX_OBJS)
+
+program_INCLUDE_DIRS := . .. /usr/include/python${python_version} ../ext/pybind11/include/pybind11
+program_LIBRARY_DIRS :=
+program_LIBRARIES := python${python_version}
+CPPFLAGS += -g -std=c++14 -pthread -O3 -fPIC -Wall
+
+CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) -DPYSMC
+LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
+LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
+
+SHARED_LIB_FLAGS := -shared -fPIC
+
+CC=g++
+
+.PHONY: all clean distclean
+
+all: $(program_NAME)
+ @- $(RM) $(program_OBJS)
+
+$(program_NAME): $(program_OBJS)
+ $(CC) $(CPPFLAGS) ${SHARED_LIB_FLAGS} $(program_OBJS) -o $(program_NAME)$(shell python3-config --extension-suffix) $(LDFLAGS)
+
+clean:
+ @- $(RM) $(program_NAME)$(shell python3-config --extension-suffix)
+ @- $(RM) $(program_OBJS)
+
+distclean: clean
diff --git a/sources/api/pySoftMC/example.py b/sources/api/pySoftMC/example.py
new file mode 100644
index 0000000..2dd2615
--- /dev/null
+++ b/sources/api/pySoftMC/example.py
@@ -0,0 +1,153 @@
+from pySoftMC import *
+import numpy as np
+
+# Initialize SoftMC platform
+platform = SoftMCPlatform()
+err = platform.init()
+if (err != 0):
+ print("SoftMC platform initialization failed!")
+ exit(-1)
+platform.reset_fpga()
+
+# Define registers
+CASR = 0
+BASR = 1
+RASR = 2
+BAR = 3
+RAR = 4
+CAR = 5
+PATTERN_REG = 6
+
+
+def initialize_row(platform: SoftMCPlatform, data32: int, bank: int, row: int):
+ p = Program()
+ p.add_inst(SMC_LI(bank, BAR))
+ p.add_inst(SMC_LI(row, RAR))
+ p.add_inst(SMC_LI(8, CASR))
+
+ p.add_inst(SMC_LI(data32, PATTERN_REG))
+ for i in range(16):
+ p.add_inst(SMC_LDWD(PATTERN_REG, i))
+
+ p.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_LI(0, CAR))
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+
+ p.add_inst(SMC_ACT(BAR, 0, RAR, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+
+ for i in range(128):
+ p.add_inst(SMC_WRITE(BAR, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_SLEEP(3))
+
+ p.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+
+ p.add_inst(SMC_END())
+ platform.execute(p)
+
+def read_row(platform: SoftMCPlatform, bank: int, row: int):
+ p = Program()
+ p.add_inst(SMC_LI(bank, BAR))
+ p.add_inst(SMC_LI(row, RAR))
+ p.add_inst(SMC_LI(8, CASR))
+
+ p.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_LI(0, CAR))
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+
+ p.add_inst(SMC_ACT(BAR, 0, RAR, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+
+ for i in range(128):
+ p.add_inst(SMC_READ(BAR, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_SLEEP(3))
+
+ p.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+
+ p.add_inst(SMC_END())
+ platform.execute(p)
+
+def hammer_row_double(bank, aggressor_row_1, aggressor_row_2, hammer_count, RAS_scale, RP_scale):
+ HMR_COUNTER_REG = 7
+ NUM_HMR_REG = 8
+
+ p = Program()
+ p.add_inst(SMC_LI(bank, BAR))
+ p.add_inst(SMC_LI(aggressor_row_1, RAR))
+
+ p.add_inst(SMC_LI(0, HMR_COUNTER_REG))
+ p.add_inst(SMC_LI(hammer_count, NUM_HMR_REG))
+
+ p.add_label("HMR_BEGIN")
+ if (RAS_scale > 1):
+ p.add_inst(SMC_SLEEP(5 * (RAS_scale - 1)))
+
+ p.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_LI(aggressor_row_1, RAR))
+ if (RP_scale > 1):
+ p.add_inst(SMC_SLEEP(3 * (RP_scale - 1)))
+
+
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_ACT(BAR, 0, RAR, 0))
+ p.add_inst(SMC_LI(aggressor_row_2, RAR))
+ p.add_inst(SMC_SLEEP(5))
+ if (RAS_scale > 1):
+ p.add_inst(SMC_SLEEP(5 * (RAS_scale - 1)))
+
+ p.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_ADDI(HMR_COUNTER_REG, 1, HMR_COUNTER_REG))
+ if (RP_scale > 1):
+ p.add_inst(SMC_SLEEP(3 * (RP_scale - 1)))
+
+
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_ACT(BAR, 0, RAR, 0))
+ p.add_branch(Program.BR_TYPE.BL, HMR_COUNTER_REG, NUM_HMR_REG, "HMR_BEGIN")
+
+
+ p.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP())
+ p.add_inst(SMC_END())
+
+ platform.execute(p)
+
+def check_flips(buffer, pattern):
+ d = []
+ out = np.bitwise_xor(buffer, pattern)
+ for cl in range(128):
+ for w in range(8):
+ if (out[cl * 8 + w]) != 0:
+ _w = out[cl * 8 + w]
+ for byte in range(8):
+ for bit in range(8):
+ bit_id = np.uint64(byte * 8 + bit)
+ if ((np.right_shift(_w, bit_id)) & np.uint64(0x1)):
+ d.append((i, cl, w, byte, bit))
+ print(f"ITR {i}\tCL {cl}\t Word {w}\t Byte {byte}\t Bit {bit}")
+
+
+# Get the buffer from the underlying C++ API
+buffer = np.frombuffer(platform.get_buffer_memoryview()[:8192], dtype=np.uint64)
+
+ITR_COUNT=10
+ACT_COUNT = 100000
+pattern = 0xFFFFFFFF
+
+for i in range(ITR_COUNT):
+ initialize_row(platform, 0xFFFFFFFF, 0, 233)
+ initialize_row(platform, 0x0, 0, 234)
+ initialize_row(platform, 0xFFFFFFFF, 0, 235)
+
+ hammer_row_double(0, 233, 235, ACT_COUNT, 1, 1)
+
+ read_row(platform, 0, 234)
+ platform.receiveData(8*1024)
+
+ check_flips(buffer, 0x0)
+
diff --git a/sources/api/pySoftMC/pySoftMC.cpp b/sources/api/pySoftMC/pySoftMC.cpp
new file mode 100644
index 0000000..992d9a5
--- /dev/null
+++ b/sources/api/pySoftMC/pySoftMC.cpp
@@ -0,0 +1,95 @@
+#include "platform.h"
+#include "instruction.h"
+#include "prog.h"
+
+#include "ext/pybind11/include/pybind11/pybind11.h"
+namespace py = pybind11;
+
+PYBIND11_MODULE(pySoftMC, m)
+{
+ py::enum_<PC_TYPE>(m, "PC_TYPE")
+ .value("WRITE", PC_TYPE::WRITE)
+ .value("READ", PC_TYPE::READ)
+ .value("PRE", PC_TYPE::PRE)
+ .value("ACT", PC_TYPE::ACT)
+ .value("ZQ", PC_TYPE::ZQ)
+ .value("REF", PC_TYPE::REF)
+ .value("CYC", PC_TYPE::CYC)
+ .export_values();
+
+ m.def("SMC_LD", &SMC_LD, py::arg("rb"), py::arg("offset"), py::arg("rt"));
+ m.def("SMC_ST", &SMC_ST, py::arg("rb"), py::arg("offset"), py::arg("rt"));
+
+ m.def("SMC_AND", &SMC_AND, py::arg("rs1"), py::arg("rs2"), py::arg("rt"));
+ m.def("SMC_OR", &SMC_OR, py::arg("rs1"), py::arg("rs2"), py::arg("rt"));
+ m.def("SMC_XOR", &SMC_XOR, py::arg("rs1"), py::arg("rs2"), py::arg("rt"));
+ m.def("SMC_ADD", &SMC_ADD, py::arg("rs1"), py::arg("rs2"), py::arg("rt"));
+ m.def("SMC_ADDI", &SMC_ADDI, py::arg("rs1"), py::arg("imd"), py::arg("rt"));
+ m.def("SMC_SUB", &SMC_SUB, py::arg("rs1"), py::arg("rs2"), py::arg("rt"));
+ m.def("SMC_SUBI", &SMC_SUBI, py::arg("rs1"), py::arg("imd"), py::arg("rt"));
+ m.def("SMC_SRC", &SMC_SRC, py::arg("rs1"), py::arg("rt"));
+
+ m.def("SMC_LI", &SMC_LI, py::arg("imd"), py::arg("rt"));
+ m.def("SMC_MV", &SMC_MV, py::arg("rs1"), py::arg("rt"));
+
+ m.def("SMC_LDWD", &SMC_LDWD, py::arg("rs1"), py::arg("offset"));
+ m.def("SMC_LDPC", &SMC_LDPC, py::arg("type"), py::arg("rt"));
+
+ m.def("SMC_BL", &SMC_BL, py::arg("rs1"), py::arg("rs2"), py::arg("tgt"));
+ m.def("SMC_BEQ", &SMC_BEQ, py::arg("rs1"), py::arg("rs2"), py::arg("tgt"));
+ m.def("SMC_JUMP", &SMC_JUMP, py::arg("tgt"));
+
+ m.def("SMC_END", &SMC_END);
+ m.def("SMC_INFO", &SMC_INFO, py::arg("rdcnt"));
+ m.def("SMC_SLEEP", &SMC_SLEEP, py::arg("samt"));
+
+ m.def("SMC_WRITE", &SMC_WRITE, py::arg("bar"), py::arg("ibar"), py::arg("car"), py::arg("icar"), py::arg("BL4"), py::arg("ap"));
+ m.def("SMC_READ", &SMC_READ, py::arg("bar"), py::arg("ibar"), py::arg("car"), py::arg("icar"), py::arg("BL4"), py::arg("ap"));
+ m.def("SMC_PRE", &SMC_PRE, py::arg("bar"), py::arg("ibar"), py::arg("pall"));
+ m.def("SMC_ACT", &SMC_ACT, py::arg("bar"), py::arg("ibar"), py::arg("rar"), py::arg("irar"));
+
+ m.def("SMC_ZQ", &SMC_ZQ);
+ m.def("SMC_REF", &SMC_REF);
+ m.def("SMC_NOP", &SMC_NOP);
+ m.def("SMC_SRE", &SMC_SRE);
+ m.def("SMC_SRX", &SMC_SRX);
+
+ m.def("__pack_mininsts", &__pack_mininsts, py::arg("i1"), py::arg("i2"), py::arg("i3"), py::arg("i4"));
+
+ py::class_<SoftMCPlatform>(m, "SoftMCPlatform")
+ .def(py::init())
+ .def("init", &SoftMCPlatform::init)
+ .def("reset_fpga", &SoftMCPlatform::reset_fpga)
+ .def("execute", &SoftMCPlatform::execute, py::arg("program"))
+ .def("receiveData", &SoftMCPlatform::py_receiveData, py::arg("num_words"))
+ .def("get_buffer_memoryview", &SoftMCPlatform::get_buffer_memoryview)
+ .def("set_aref", &SoftMCPlatform::set_aref, py::arg("on"))
+ .def("readRegisterDump", &SoftMCPlatform::readRegisterDump)
+ .def("count_bitflips_in_row", &SoftMCPlatform::count_bitflips_in_row, py::arg("char_data"));
+
+ py::class_<Program> program(m, "Program");
+
+ py::enum_<Program::SEQ_TYPE>(program, "SEQ_TYPE")
+ .value("WRITE", Program::SEQ_TYPE::WRITE)
+ .value("READ", Program::SEQ_TYPE::READ)
+ .export_values();
+
+ py::enum_<Program::BR_TYPE>(program, "BR_TYPE")
+ .value("BEQ", Program::BR_TYPE::BEQ)
+ .value("BL", Program::BR_TYPE::BL)
+ .value("JUMP", Program::BR_TYPE::JUMP)
+ .export_values();
+
+ program
+ .def(py::init())
+ .def("add_mininst", &Program::add_mininst, py::arg("mi"), py::arg("wait_after"))
+ .def("add_wait", &Program::add_wait, py::arg("wait_cycles"))
+ .def("pack_minprogram", &Program::pack_minprogram)
+ .def("add_inst", py::overload_cast<Inst>(&Program::add_inst), py::arg("inst"))
+ .def("add_inst", py::overload_cast<Mininst, Mininst, Mininst, Mininst>(&Program::add_inst))
+ .def("add_label", &Program::add_label, py::arg("name"))
+ .def("add_branch", &Program::add_branch, py::arg("type"), py::arg("rs1"), py::arg("rs2"), py::arg("tgt"))
+ .def("add_below", &Program::add_below)
+ .def("pretty_print", &Program::pretty_print)
+ .def("dump_registers", &Program::dump_registers);
+}