From dc0b3db1b4f1895a07e5fe280ee3790e87f97b9f Mon Sep 17 00:00:00 2001 From: Ataberk Date: Sun, 25 Sep 2022 17:22:03 +0200 Subject: Initial commit --- sources/apps/.gitignore | 1 + sources/apps/DebugExample/Makefile | 32 + sources/apps/DebugExample/debug_example.cpp | 58 ++ sources/apps/DebugExample/timings.txt | 14 + sources/apps/QUAC-TRNG/.gitignore | 1 + sources/apps/QUAC-TRNG/Makefile.ent | 28 + sources/apps/QUAC-TRNG/Makefile.observe | 32 + sources/apps/QUAC-TRNG/Makefile.sha | 28 + sources/apps/QUAC-TRNG/README.md | 58 ++ sources/apps/QUAC-TRNG/bin/.gitkeep | 0 sources/apps/QUAC-TRNG/scripts/convert_ent.py | 32 + sources/apps/QUAC-TRNG/scripts/ft200_rc/README.md | 21 + .../apps/QUAC-TRNG/scripts/ft200_rc/__init__.py | 0 .../scripts/ft200_rc/docs/1189902393_ft200_lcd.pdf | Bin 0 -> 14203337 bytes .../apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf | Bin 0 -> 102947 bytes sources/apps/QUAC-TRNG/scripts/ft200_rc/ft200.py | 182 ++++++ .../QUAC-TRNG/scripts/ft200_rc/usb_dev_path.sh | 13 + sources/apps/QUAC-TRNG/scripts/run_ent.py | 43 ++ sources/apps/QUAC-TRNG/scripts/run_vn_nist.py | 125 ++++ sources/apps/QUAC-TRNG/scripts/sha_bitstreams.py | 87 +++ sources/apps/QUAC-TRNG/scripts/top_ents.py | 35 + sources/apps/QUAC-TRNG/src/observe.cpp | 726 +++++++++++++++++++++ sources/apps/QUAC-TRNG/src/slow_entropy.cpp | 204 ++++++ sources/apps/QUAC-TRNG/src/slow_sha.cpp | 233 +++++++ sources/apps/QUAC-TRNG/src/util.cpp | 670 +++++++++++++++++++ sources/apps/QUAC-TRNG/src/util.h | 55 ++ sources/apps/ResetBoard/SoftMC_reset | Bin 0 -> 752008 bytes sources/apps/ResetBoard/full_reset.sh | 9 + sources/apps/RetentionTest/Makefile | 28 + sources/apps/RetentionTest/retention.cpp | 205 ++++++ sources/apps/SanityCheck/.gitignore | 1 + sources/apps/SanityCheck/Makefile | 33 + sources/apps/SanityCheck/sanity.cpp | 294 +++++++++ sources/apps/Smalltest/.gitignore | 1 + sources/apps/Smalltest/Makefile | 32 + sources/apps/Smalltest/read_write.cpp | 293 +++++++++ sources/apps/Smalltest/read_write.smc | 170 +++++ sources/apps/parsertest/Makefile | 27 + sources/apps/parsertest/SoftMC_Example | Bin 0 -> 372120 bytes sources/apps/parsertest/example.smc | 9 + sources/apps/parsertest/ptest.cpp | 18 + 41 files changed, 3798 insertions(+) create mode 100644 sources/apps/.gitignore create mode 100755 sources/apps/DebugExample/Makefile create mode 100644 sources/apps/DebugExample/debug_example.cpp create mode 100644 sources/apps/DebugExample/timings.txt create mode 100644 sources/apps/QUAC-TRNG/.gitignore create mode 100644 sources/apps/QUAC-TRNG/Makefile.ent create mode 100644 sources/apps/QUAC-TRNG/Makefile.observe create mode 100644 sources/apps/QUAC-TRNG/Makefile.sha create mode 100644 sources/apps/QUAC-TRNG/README.md create mode 100644 sources/apps/QUAC-TRNG/bin/.gitkeep create mode 100644 sources/apps/QUAC-TRNG/scripts/convert_ent.py create mode 100644 sources/apps/QUAC-TRNG/scripts/ft200_rc/README.md create mode 100644 sources/apps/QUAC-TRNG/scripts/ft200_rc/__init__.py create mode 100644 sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/1189902393_ft200_lcd.pdf create mode 100644 sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf create mode 100644 sources/apps/QUAC-TRNG/scripts/ft200_rc/ft200.py create mode 100755 sources/apps/QUAC-TRNG/scripts/ft200_rc/usb_dev_path.sh create mode 100644 sources/apps/QUAC-TRNG/scripts/run_ent.py create mode 100644 sources/apps/QUAC-TRNG/scripts/run_vn_nist.py create mode 100644 sources/apps/QUAC-TRNG/scripts/sha_bitstreams.py create mode 100644 sources/apps/QUAC-TRNG/scripts/top_ents.py create mode 100644 sources/apps/QUAC-TRNG/src/observe.cpp create mode 100644 sources/apps/QUAC-TRNG/src/slow_entropy.cpp create mode 100644 sources/apps/QUAC-TRNG/src/slow_sha.cpp create mode 100644 sources/apps/QUAC-TRNG/src/util.cpp create mode 100644 sources/apps/QUAC-TRNG/src/util.h create mode 100755 sources/apps/ResetBoard/SoftMC_reset create mode 100755 sources/apps/ResetBoard/full_reset.sh create mode 100755 sources/apps/RetentionTest/Makefile create mode 100644 sources/apps/RetentionTest/retention.cpp create mode 100644 sources/apps/SanityCheck/.gitignore create mode 100755 sources/apps/SanityCheck/Makefile create mode 100644 sources/apps/SanityCheck/sanity.cpp create mode 100644 sources/apps/Smalltest/.gitignore create mode 100755 sources/apps/Smalltest/Makefile create mode 100644 sources/apps/Smalltest/read_write.cpp create mode 100644 sources/apps/Smalltest/read_write.smc create mode 100755 sources/apps/parsertest/Makefile create mode 100755 sources/apps/parsertest/SoftMC_Example create mode 100644 sources/apps/parsertest/example.smc create mode 100644 sources/apps/parsertest/ptest.cpp (limited to 'sources/apps') diff --git a/sources/apps/.gitignore b/sources/apps/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/sources/apps/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/sources/apps/DebugExample/Makefile b/sources/apps/DebugExample/Makefile new file mode 100755 index 0000000..13ecbb0 --- /dev/null +++ b/sources/apps/DebugExample/Makefile @@ -0,0 +1,32 @@ +program_NAME := Debug_example +program_CXX_SRCS := debug_example.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := +CPPFLAGS += -g -std=c++11 -pthread -O3 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +parser: + $(MAKE) -C ../../api/lexyacc + cp ../../api/lexyacc/smc_parser . + +distclean: clean diff --git a/sources/apps/DebugExample/debug_example.cpp b/sources/apps/DebugExample/debug_example.cpp new file mode 100644 index 0000000..6581354 --- /dev/null +++ b/sources/apps/DebugExample/debug_example.cpp @@ -0,0 +1,58 @@ +#include "instruction.h" +#include "prog.h" +#include "platform.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define PROJECT_DIRECTORY "" + +#define ADD_REG 7 +#define LD_REG 8 +#define STR_REG 9 + +/** + * @return an instruction formed by NOPs + */ +Inst all_nops() +{ + return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); +} + +int main() +{ + + Program program; + + program.add_inst(SMC_LI(5, 3)); //R3=5 + program.add_inst(SMC_LI(15, 4)); //R4=15 + program.add_label("LOOP"); + program.add_inst(SMC_ADDI(3, 1, 3)); //R3++ + //If R4>R3, go to LOOP + program.add_branch(program.BR_TYPE::BL,3,4, "LOOP"); + program.add_inst(all_nops()); //R3=R4=15 + program.add_inst(SMC_LI(121, LD_REG)); + program.add_inst(SMC_LI(62, STR_REG)); + program.add_inst(SMC_LI(100, ADD_REG)); + program.add_inst(SMC_ST(ADD_REG, 0, STR_REG)); + program.add_inst(all_nops()); + program.add_inst(SMC_LD(ADD_REG, 0, LD_REG)); + program.add_inst(all_nops()); + program.add_inst(SMC_END()); + + //DRAM timing parameters are updated with timings.txt + program.debug(PROJECT_DIRECTORY, "timings.txt"); + + //Load the program to instruction memory + program.save_coe(PROJECT_DIRECTORY); + program.pretty_print(); + + //Start the debugger + program.debug(PROJECT_DIRECTORY, false); +} diff --git a/sources/apps/DebugExample/timings.txt b/sources/apps/DebugExample/timings.txt new file mode 100644 index 0000000..8de3bed --- /dev/null +++ b/sources/apps/DebugExample/timings.txt @@ -0,0 +1,14 @@ +tRTP = 7500 +tWTRc_S = 2 +tWTRc_L = 5 +tWR = 15000 +tMOD = 36000 +tRCD = 16000 +tRC = 55000 +tRP = 15000 +tCCDc_S = 4 +tCCDc_L = 5 +tRAS = 39000 +tRRDc_S = 4 +tRRDc_L = 4 +tFAW = 20000 diff --git a/sources/apps/QUAC-TRNG/.gitignore b/sources/apps/QUAC-TRNG/.gitignore new file mode 100644 index 0000000..8fce603 --- /dev/null +++ b/sources/apps/QUAC-TRNG/.gitignore @@ -0,0 +1 @@ +data/ diff --git a/sources/apps/QUAC-TRNG/Makefile.ent b/sources/apps/QUAC-TRNG/Makefile.ent new file mode 100644 index 0000000..468a10b --- /dev/null +++ b/sources/apps/QUAC-TRNG/Makefile.ent @@ -0,0 +1,28 @@ +program_NAME := bin/ENT +program_CXX_SRCS := src/slow_entropy.cpp src/util.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := +CPPFLAGS += -g -std=c++11 -pthread -O3 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +distclean: clean diff --git a/sources/apps/QUAC-TRNG/Makefile.observe b/sources/apps/QUAC-TRNG/Makefile.observe new file mode 100644 index 0000000..d5b1adb --- /dev/null +++ b/sources/apps/QUAC-TRNG/Makefile.observe @@ -0,0 +1,32 @@ +program_NAME := bin/OBSERVE +program_CXX_SRCS := src/observe.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := +CPPFLAGS += -g -std=c++11 -pthread -O3 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +parser: + $(MAKE) -C ../../api/lexyacc + cp ../../api/lexyacc/smc_parser . + +distclean: clean diff --git a/sources/apps/QUAC-TRNG/Makefile.sha b/sources/apps/QUAC-TRNG/Makefile.sha new file mode 100644 index 0000000..bd0c463 --- /dev/null +++ b/sources/apps/QUAC-TRNG/Makefile.sha @@ -0,0 +1,28 @@ +program_NAME := bin/SHA +program_CXX_SRCS := src/slow_sha.cpp src/util.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := ssl crypto +CPPFLAGS += -g -std=c++11 -pthread -O3 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +distclean: clean diff --git a/sources/apps/QUAC-TRNG/README.md b/sources/apps/QUAC-TRNG/README.md new file mode 100644 index 0000000..437d0dd --- /dev/null +++ b/sources/apps/QUAC-TRNG/README.md @@ -0,0 +1,58 @@ +## Scripts to Reproduce QUAC-TRNG + +This directory provides all necessary files and instructions to reproduce the results of [QUAC-TRNG](https://people.inf.ethz.ch/omutlu/pub/QUAC-TRNG-DRAM_isca21.pdf). + +``` +@inproceedings{olgun2022quactrng, + title={QUAC-TRNG: High-Throughput True Random Number Generation Using Quadruple Row Activation in Commodity DRAM Chips}, + author={Ataberk Olgun, Minesh Patel, A. Giray Yaglikci, Haocong Luo, Jeremie S. Kim, F. Nisa Bostanci, Nandita Vijaykumar, Oguz Ergin, and Onur Mutlu}, + year={2021}, + booktitle={ISCA} +} +``` + +### Obtain NIST STS + +Download the NIST standard test suite (NIST STS) for random number generators using [this link](https://github.com/arcetri/sts). Install it under `tools` using the instructions provided in the linked repository's README. + +After installing NIST STS, `QUAC-TRNG/tools/sts` should point to the NIST STS executable. + +### Copy SoftMC_reset to bin/ + +Run the following command to copy the reset program under bin/ directory. + +`cp ../ResetBoard/SoftMC_reset bin/` + +### Entropy Tests + +To run entropy tests, simply execute the `run_ent.py` script (you have to execute this in QUAC-TRNG directory): + +``` +make -f Makefile.ent +python3 scripts/run_ent.py +``` + +Example: `python3 scripts/run_ent.py hytt04 50 1000 4` + +This script will output one text file for every tested 4-bit data pattern (variable named placement in run_ent.py). Each line in the text file starts with the starting `row id` of a DRAM segment, followed by the observed entropy numbers for each bit in the segment. + +### von Neumann Corrected Bitstreams + +This will collect 1 Mb bitstreams from frequently switching bitlines and input them to NIST STS. The script will stop the moment it finds a cell that passes all NIST tests. + +``` +make -f Makefile.observe +python3 scripts/run_vn_nist.py +``` + +Example: `python3 scripts/run_vn_nist.py hytt04 50` + +### SHA-256 Bitstreams + +This section describes how to get the NIST STS results for SHA-256 processed bitstreams. Doing so consists of two steps: 1) finding the DRAM segments with top 10 entropy, 2) generating bitstreams from the top-10-entropy segments and processing them using SHA-256 and performing NIST STS tests. + +First, run `make -f Makefile.sha`. + +1- Obtain the entropy distribution to find the desired 4-bit data pattern (refer to "Entropy Tests"). +2- Get the segments with max. entropy: `python3 scripts/top_ents.py ` +3- Run the SHA-256 bitstream generator script: `python3 scripts/sha_bitstreams.py ` \ No newline at end of file diff --git a/sources/apps/QUAC-TRNG/bin/.gitkeep b/sources/apps/QUAC-TRNG/bin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sources/apps/QUAC-TRNG/scripts/convert_ent.py b/sources/apps/QUAC-TRNG/scripts/convert_ent.py new file mode 100644 index 0000000..b2c66ea --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/convert_ent.py @@ -0,0 +1,32 @@ +import os +import argparse +from numpy import array + +parser = argparse.ArgumentParser(description = "Run this script to preprocess entropy files") +parser.add_argument('indir', help="Path to entropy files") +args = parser.parse_args() + +files = [] +for fname in os.listdir(args.indir): + files.append(fname) + +for file in files: + print("Processing:", file) + # Add this placement + fpath = os.path.normpath(args.indir + '/' + file) + infile = open(fpath,'r') + wfile = file.split('.')[0] + '_floats.bin' + wfpath = os.path.normpath(args.indir + '/' + wfile) + output_file = open(wfpath, 'wb') + + lines = infile.readlines() + + # First row reserved for metadata + for lidx in range(1,len(lines)): + line = lines[lidx].strip() + split = line.split() + elements = [float(i) for i in split[1:]] + a = array(elements,'float32') + a.tofile(output_file) + + output_file.close() \ No newline at end of file diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/README.md b/sources/apps/QUAC-TRNG/scripts/ft200_rc/README.md new file mode 100644 index 0000000..de91b27 --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/ft200_rc/README.md @@ -0,0 +1,21 @@ +# FT200 remote read and write + +Make sure that the FT200 controller match the parameters you are using in your script. +The relevant parameters are: + +PASS-0101 menu (see documentation in doc folder): +* ldN0 (Device address) +* bAUd (rate) +* UCR (parity) + +## Requirements +* pip3 install -U minimalmodbus + + +## Add your user to the dialout group + +sudo gpasswd --add ${USER} dialout +(You need to log out and log back in again for it to be effective) + +## Execute test +* python3 ft200.py diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/__init__.py b/sources/apps/QUAC-TRNG/scripts/ft200_rc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/1189902393_ft200_lcd.pdf b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/1189902393_ft200_lcd.pdf new file mode 100644 index 0000000..8c18eaa Binary files /dev/null and b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/1189902393_ft200_lcd.pdf differ diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf new file mode 100644 index 0000000..e4d0d39 Binary files /dev/null and b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf differ diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/ft200.py b/sources/apps/QUAC-TRNG/scripts/ft200_rc/ft200.py new file mode 100644 index 0000000..aa50a1f --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/ft200_rc/ft200.py @@ -0,0 +1,182 @@ +""""" +Code for monitoring and controlling temperature in the Maxwell FT200 controller using the Modbus RS485 protocol +@author: Lois Orosa +""""" +import minimalmodbus as mm, serial, time +import time +import os +import sys +import pathlib + +class FT200: + """ + Controls and monitors the Maxwell FT200 tempoerature controller + """ + READ_ERROR = -999 + WRITE_ERROR = -998 + def __init__(self, _baud=9600, _ft200_addr=1, _temp_tolerance=2): + self.baud = _baud + self.write_reg = 5 # Write register + self.read_reg = 0 # Read register + self.ft200_addr = _ft200_addr # Address of the device (by default is 1) + self.temp_tolerance = _temp_tolerance # Temperature tolerance. By default, we consider that we reach the target value if the measured value is within +-0.2C + + try: + self.device = self.findDevice() # Get the USB-RS485 device + print("USB-RS485 Device: "+str(self.device)) + self.instrument = mm.Instrument(self.device , 3 , debug = False) + self.instrument.serial.baudrate = self.baud + self.instrument.address = self.ft200_addr + self.instrument.serial.timeout = 1 + self.instrument.serial.parity = serial.PARITY_NONE + self.instrument.mode = mm.MODE_RTU + print("Device "+self.device+": conected") + except: + raise + + # Automatically find the USB-RS485 Device + def findDevice(self): + ''' + Find the USB-RS485 device + This function might raise two exceptions: + -> NameError: There is more than 1 USB-RS485 device, or other USB device has a similar name as the USB-RS485 device + -> IOError: Device not found. + ''' + DEVICENAME = "1a86_USB" + name = '' + while True: + path = pathlib.Path(__file__).parent.absolute() + f = os.popen(str(path)+"/usb_dev_path.sh") + for device in f: + if DEVICENAME in device: + if name == '': + name = device.split()[0] + else: + raise NameError("There are at least two USB devices whose name contains "+str(DEVICENAME)) + if name == '': + raise IOError("Device not found.") + return name + + # Read Temperature from FT200 + # The output value has 1 decimal, and it is multiplied by 10 + # E.g., data= 102 represents a temperature of 10.2C + def readTemp(self): + try: + data = self.instrument.read_register(self.read_reg, functioncode=3) + return data + except IOError: + print("Failed to read from instrument") + return self.READ_ERROR + + # Check if the temperature reached a value + # The input value has 1 decimal, and it is multiplied by 10 + # E.g., data= 102 represents a temperature of 10.2C + def isTemp(self, temperature): + try: + data = self.instrument.read_register(self.read_reg, functioncode=3) + if data >= (temperature-self.temp_tolerance) and data <= (temperature+self.temp_tolerance): + return True + else: + return False + except IOError: + print("Failed to read from instrument") + return False + + # Set Temperature FT200 + # The value should be a integer, and it should be the temperature value with 1 decimal multiplied by 10 + # E.g., value= 102 represents a temperature of 10.2C + def setTemp(self, value): + try: + self.instrument.write_register(self.write_reg, value, functioncode=6) + except IOError: + print("Failed to write to instrument") + return self.WRITE_ERROR + return 0 + + # Set the temperature and wait for the temperature to be stable + # Optimized version that reach the target temperature earlier + # The value should be a integer, and it should be the temperature value with 1 decimal multiplied by 10 + # E.g., value= 102 represents a temperature of 10.2C + def autoSetAndWait(self, temperature, debug = False): + acceleration_factor = 5 + stability = 10 # Iterations that the temperature needs to be stable + time_sleep = 1 # 1 second wait per loop iteration + stable_count = stability # Counter for taking into account the stability of the temperature + stable_margin = 20 # We do not change the set temperature if we are within 2C from the target + optTemp = temperature + self.setTemp(optTemp) # Set the temperature + curTemp = self.readTemp() # Read the temperature + if debug: + print("[TEMPERATURE] current: "+str(curTemp/10.0)+", goal: "+str(temperature/10.0)+", programmed: "+str(optTemp/10.0)) + while (((curTemp > (temperature + self.temp_tolerance)) or (curTemp < (temperature - self.temp_tolerance))) or (stable_count!=0)): + if debug: + print("[TEMPERATURE] current: "+str(curTemp/10.0)+", goal: "+str(temperature/10.0)+", programmed: "+str(optTemp/10.0)+", stable_count: "+str(stable_count)) + prev_optTemp = optTemp + if (temperature - curTemp) > 0: #(stable_margin): # If we are far away more than 2C + optTemp = temperature + (temperature - curTemp)*acceleration_factor # Optimization to accelerate convergence + else: + optTemp = temperature + if optTemp != prev_optTemp: + self.setTemp(optTemp) # Set temperature only if different from the previous iteration + + time.sleep(time_sleep) # WAit for a while + + curTemp = self.readTemp() # Read the temperature + while (curTemp == self.READ_ERROR): # If there is an error, read again + curTemp = self.readTemp() + # Five iterations in the range + if (curTemp > (temperature + self.temp_tolerance)) or (curTemp < (temperature - self.temp_tolerance)): + stable_count = stability + else: + stable_count -= 1 # The temperature has to remain stable for a while + + def autoSetAndWait_2(self, temperature, debug = False): + acceleration_factor = 150 + stability = 10 # Iterations that the temperature needs to be stable + time_sleep = 1 # 1 second wait per loop iteration + stable_count = stability # Counter for taking into account the stability of the temperature + stable_margin = 5 # We do not change the set temperature if we are within 2C from the target + optTemp = temperature + self.setTemp(optTemp) # Set the temperature + curTemp = self.readTemp() # Read the temperature + if debug: + print("[TEMPERATURE] current: "+str(curTemp/10.0)+", goal: "+str(temperature/10.0)+", programmed: "+str(optTemp/10.0)) + while (((curTemp > (temperature + self.temp_tolerance)) or (curTemp < (temperature - self.temp_tolerance))) or (stable_count!=0)): + if debug: + print("[TEMPERATURE] current: "+str(curTemp/10.0)+", goal: "+str(temperature/10.0)+", programmed: "+str(optTemp/10.0)+", stable_count: "+str(stable_count)) + prev_optTemp = optTemp + if abs(temperature - curTemp) > (stable_margin): # If we are far away more than 2C + if temperature > curTemp: + optTemp = temperature + acceleration_factor # Optimization to accelerate convergence + else: + optTemp = temperature - acceleration_factor # Optimization to accelerate convergence + else: + optTemp = temperature + + time.sleep(time_sleep) # WAit for a while + + curTemp = self.readTemp() # Read the temperature + while (curTemp == self.READ_ERROR): # If there is an error, read again + curTemp = self.readTemp() + # Five iterations in the range + if (curTemp > (temperature + self.temp_tolerance)) or (curTemp < (temperature - self.temp_tolerance)): + stable_count = stability + else: + stable_count -= 1 # The temperature has to remain stable for a while + +if __name__ == '__main__': + ## Example of how to use the FT200 class + try: + tc = FT200() + except Exception as error: + print("[ERROR] "+ repr(error)) + sys.exit(0) + + # Temperature + value = int(sys.argv[1]) * 10 + print(value) + print(tc.readTemp()) + tc.autoSetAndWait(value,True) + + + diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/usb_dev_path.sh b/sources/apps/QUAC-TRNG/scripts/ft200_rc/usb_dev_path.sh new file mode 100755 index 0000000..241aef1 --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/ft200_rc/usb_dev_path.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# https://unix.stackexchange.com/questions/144029/command-to-determine-ports-of-a-device-like-dev-ttyusb0 +echo "USB devices:" +for sysdevpath in $(find /sys/bus/usb/devices/usb*/ -name dev); do + ( + syspath="${sysdevpath%/dev}" + devname="$(udevadm info -q name -p $syspath)" +[[ "$devname" == "bus/"* ]] && exit + eval "$(udevadm info -q property --export -p $syspath)" +[[ -z "$ID_SERIAL" ]] && exit + echo "/dev/$devname - $ID_SERIAL" + ) +done diff --git a/sources/apps/QUAC-TRNG/scripts/run_ent.py b/sources/apps/QUAC-TRNG/scripts/run_ent.py new file mode 100644 index 0000000..5163c5f --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/run_ent.py @@ -0,0 +1,43 @@ +import os +import argparse +import subprocess +import time + +parser = argparse.ArgumentParser(description = "Collects entropy for different data patterns") + +parser.add_argument('dimm', help="DIMM label under test") +parser.add_argument('temperature', help="DIMM temperature in centigrades") +parser.add_argument('iters', help="How many times do we QUAC to find entropy") +parser.add_argument('stride', help="Stride (in rows) used to skim through segments, default: 4") + +args = parser.parse_args() + +# ---------------- SETUP DIRECTORIES ------------------- + +if not os.path.isdir("data"): + os.mkdir("data") + +if not os.path.isdir("data/" + args.dimm): + os.mkdir("data/" + args.dimm) + +if not os.path.isdir("data/" + args.dimm + "/ent"): + os.mkdir("data/" + args.dimm + "/ent") + +if not os.path.isdir("data/" + args.dimm + "/ent/" + args.temperature + "C"): + os.mkdir("data/" + args.dimm + "/ent/" + args.temperature + "C") + +outdir = os.path.normpath("data/" + args.dimm + "/ent/" + args.temperature + "C") + +# -------------------- RUN TESTS ----------------------- + +placements = ["1000", "1001", "1010", "1011", "1100" , "1101", "1110", "1111", \ + "0111", "0110", "0101", "0100", "0011" , "0010", "0001", "0000"] + +ent_path = os.path.normpath("bin/ENT") +results_path = outdir +stride = args.stride +iters = args.iters + +for placement in placements: + print("sudo " + ent_path + " " + results_path + " " + placement + " " + stride + " " + iters) + os.system("sudo " + ent_path + " " + results_path + " " + placement + " " + stride + " " + iters) diff --git a/sources/apps/QUAC-TRNG/scripts/run_vn_nist.py b/sources/apps/QUAC-TRNG/scripts/run_vn_nist.py new file mode 100644 index 0000000..c439da8 --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/run_vn_nist.py @@ -0,0 +1,125 @@ +import os +import argparse +import subprocess +import time + +parser = argparse.ArgumentParser(description = "Run this script to evaluate bitstreams") + +parser.add_argument('dimm', help="DIMM label under test") +parser.add_argument('temperature', help="DIMM temperature in centigrades") + +args = parser.parse_args() + +# ---------------- SETUP DIRECTORIES ------------------- + +if not os.path.isdir("data"): + os.mkdir("data") + +if not os.path.isdir("data/" + args.dimm): + os.mkdir("data/" + args.dimm) + +if not os.path.isdir("data/" + args.dimm + "/vnc"): + os.mkdir("data/" + args.dimm + "/vnc") + +if not os.path.isdir("data/" + args.dimm + "/vnc/" + args.temperature + "C"): + os.mkdir("data/" + args.dimm + "/vnc/" + args.temperature + "C") + +if not os.path.isdir("data/" + args.dimm + "/vnc/" + + args.temperature + "C/nist_results"): + os.mkdir("data/" + args.dimm + "/vnc/" + args.temperature + "C/nist_results") + +if not os.path.isdir("data/" + args.dimm + "/vnc/" + + args.temperature + "C/binaries"): + os.mkdir("data/" + args.dimm + "/vnc/" + args.temperature + "C/binaries") + +outdir = os.path.normpath("data/" + args.dimm + "/vnc/" + args.temperature + "C/nist_results") +indir = os.path.normpath("data/" + args.dimm + "/vnc/" + args.temperature + "C/binaries") + +if not os.path.isfile(indir + "/lastrow.txt"): + input("I am going to overwrite 'lastrow.txt', proceed with caution") + init_file = open(indir + "/lastrow.txt", "w") + init_file.write(str(0) + "\n") + +# Hard-reset SoftMC before other experiments +reset_path = os.path.normpath("bin/SoftMC_reset") +reset = subprocess.Popen("exec sudo " + reset_path, shell=True, preexec_fn=os.setpgrp) +time.sleep(5) +os.system("sudo pkill -9 -P" + str(os.getpgid(reset.pid))) +reset.wait() + +# First run OBSERVE to collect von Neumann corrected bitstreams +observe_path = os.path.normpath("bin/OBSERVE " + indir) +observe_args = " > " + os.path.normpath(outdir + "/output.log") +observe = subprocess.Popen("exec sudo " + observe_path + observe_args, shell=True, preexec_fn=os.setpgrp) + +# Watch the bitstream directory for new files +before = ["lastrow.txt"] + +while True: + time.sleep(1) + after = os.listdir(indir) + s = set(before) + diff = [x for x in after if x not in s] + before = after + if len(diff) == 0: + continue + + bitstream = [[] for i in range(8)] # at most 8 STS runs + + # Partition + i = 0 + for fname in diff: + bitstream[i].append(fname) + i = (i+1) % 8 + + found = False + for i in range(len(bitstream[0])): + print("Finished " + str(i) + " out of " + str(len(bitstream[7]))) + processes = [] + for thr in range(0,8): + if len(bitstream[thr]) <= i: + break + command_output = os.path.normpath(outdir + "/thr" + str(thr)) + command_input = os.path.normpath(indir + '/' + bitstream[thr][i]) + command = 'tools/sts -O -i 1 -I 1 -S '+ str(1024*1024) +' -w ' + command_output +' -F r ' + command_input + " 2>/dev/null" + process = subprocess.Popen(command, shell=True) + processes.append(process) + + # Collect statuses + output = [p.wait() for p in processes] + + for thr in range(0,8): + if len(bitstream[thr]) <= i: + break + res_txt = open(os.path.normpath(outdir + '/thr' + str(thr) + '/finalAnalysisReport.txt'), "r") + lines = res_txt.readlines() + n_success = 0 + for j in range(7, len(lines)): + line = lines[j].strip() + if not ("1" in line or "0" in line): + break + split = line.split() + if "/" in split[11]: + n_success += int(split[11].split("/")[0]) + res_txt.close() + print(bitstream[thr][i] + " succeeded in " + str(n_success) + "tests + bits: " + str(1024*1024)) + if n_success < 187: + os.system("rm -f " + indir + "/" + bitstream[thr][i]) + if n_success > 186: + os.system("mkdir " + outdir + "/" + bitstream[thr][i]) + os.system("cp " + outdir + '/thr' + str(thr) + "/finalAnalysisReport.txt " + outdir + "/" + bitstream[thr][i]) + if n_success == 188: + os.system("sudo pkill -9 -P" + str(os.getpgid(observe.pid))) + observe.wait() # wait until the process actually terminates + found = True + if found: + break + +print("Finally found one cell that passes all NIST tests!") + +# Reset SoftMC because last process was killed prematurely +reset_path = os.path.normpath("bin/SoftMC_reset") +reset = subprocess.Popen("exec sudo " + observe_path, shell=True, preexec_fn=os.setpgrp) +time.sleep(5) +os.system("sudo pkill -9 -P" + str(os.getpgid(reset.pid))) +reset.wait() diff --git a/sources/apps/QUAC-TRNG/scripts/sha_bitstreams.py b/sources/apps/QUAC-TRNG/scripts/sha_bitstreams.py new file mode 100644 index 0000000..fd4dbfb --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/sha_bitstreams.py @@ -0,0 +1,87 @@ +import os +import argparse +import subprocess +import time + +parser = argparse.ArgumentParser(description = "Collects sha bitstreams for a data pattern") + +parser.add_argument('dimm', help="DIMM label under test") +parser.add_argument('pattern', help="data pattern to use") +parser.add_argument('temperature', help="DIMM temperature in centigrades") + +args = parser.parse_args() + +bitstreams_available = False + +if not os.path.isdir("data/" + args.dimm + "/sha"): + os.mkdir("data/" + args.dimm + "/sha") + +if os.path.isdir("data/" + args.dimm + "/sha/" + args.temperature + "C"): + bitstreams_available = True + +if not os.path.isdir("data/" + args.dimm + "/sha/" + args.temperature + "C"): + os.mkdir("data/" + args.dimm + "/sha/" + args.temperature + "C") + +infile = os.path.normpath("data/" + args.dimm + "/ent/" + args.temperature + "C/top.txt") +outdir = os.path.normpath("data/" + args.dimm + "/sha/" + args.temperature + "C") + +if not os.path.isdir("data/" + args.dimm + "/sha"): + os.mkdir("data/" + args.dimm + "/sha_nist_results") + +if not os.path.isdir("data/" + args.dimm + "/sha/" + args.temperature + "C"): + os.mkdir("data/" + args.dimm + "/sha_nist_results/" + args.temperature + "C") + +sha_output = os.path.normpath("data/" + args.dimm + "/sha_nist_results/" + args.temperature + "C") + +if not bitstreams_available: + sha_path = "bin/SHA" + print("sudo " + sha_path + " " + outdir + " " + infile) + os.system("sudo " + sha_path + " " + outdir + " " + infile) +else: + print("I think we have the bitstreams available, I won't run softmc code again") + +i=0 +bitstream = [] + +for j in range(0,10): + bitstream.append([]) + +for fname in os.listdir(outdir): + bitstream[i].append(fname) + i+=1 + i = i % 10 + +print(bitstream) + +for i in range(len(bitstream[9])): + print("Finished " + str(i) + " out of " + str(len(bitstream[9]))) + processes = [] + for thr in range(0,10): + outpath = os.path.normpath(sha_output+'/thr'+str(thr)) + if not os.path.isdir(outpath): + os.mkdir(outpath) + command = 'tools/sts -O -i 1024 -I 1 -P 11=0.001 -S '+ str(1024*1024) +' -w '+ outpath +' -F r ' + outdir+'/'+bitstream[thr][i] + " 2>/dev/null" + process = subprocess.Popen(command, shell=True) + processes.append(process) + print(command) + + # Collect statuses + output = [p.wait() for p in processes] + + for thr in range(0,10): + outpath = os.path.normpath(sha_output+'/thr'+str(thr)) + res_txt = open(outpath + '/finalAnalysisReport.txt', "r") + lines = res_txt.readlines() + n_success = 0 + for j in range(7, len(lines)): + line = lines[j].strip() + if not ("1" in line or "0" in line): + break + split = line.split() + if "/" in split[11]: + n_success += int(split[11].split("/")[0]) + res_txt.close() + print(bitstream[thr][i] + " succeeded in " + str(n_success) + "tests + bits: " + str(1024*1024)) + if n_success > 186: + os.system("mkdir "+sha_output+"/" + bitstream[thr][i]) + os.system("cp "+sha_output+'/thr'+str(thr)+"/finalAnalysisReport.txt "+sha_output+"/" + bitstream[thr][i]) diff --git a/sources/apps/QUAC-TRNG/scripts/top_ents.py b/sources/apps/QUAC-TRNG/scripts/top_ents.py new file mode 100644 index 0000000..2a74569 --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/top_ents.py @@ -0,0 +1,35 @@ +import os +import argparse +import pandas as pd +import numpy as np + +parser = argparse.ArgumentParser(description = "Postprocess entropy files and obtain top-10 segments with the highest entropy") +parser.add_argument('dimm', help="DIMM label") +parser.add_argument('pattern', help="4-bit data pattern [1000, 1001, 0111, etc]") +parser.add_argument('temp', help="temperature in centigrades") +args = parser.parse_args() + +dimm = args.dimm +pattern = args.pattern +temp = args.temp + +no_segments = 8192 +no_bitlines = 512 * 128 + +fn = "data/" + dimm + "/ent/" + temp + "C/1_1000_128_32768_" + pattern + "_floats.bin" +dirname = "data/" + dimm + "/ent/" + temp + "C/" + +arr = np.fromfile(fn, dtype=np.float32) +arr = arr.reshape(no_segments, no_bitlines) +arr = arr.sum(axis = 1) +indices = arr.argsort()[-10:][::-1] +print(indices) +print(arr[indices]) + +log = open(dirname + "top.txt", "w") +log.write("10\n") +for index in indices: + # bank is always 1 + # multiply segment # by 4 to get starting row addr + log.write("1 " + str(int(index) * 4) + " " + str(arr[index]) + " " + pattern + "\n") +log.close() diff --git a/sources/apps/QUAC-TRNG/src/observe.cpp b/sources/apps/QUAC-TRNG/src/observe.cpp new file mode 100644 index 0000000..275c516 --- /dev/null +++ b/sources/apps/QUAC-TRNG/src/observe.cpp @@ -0,0 +1,726 @@ +#include "instruction.h" +#include "prog.h" +#include "platform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NEWFILTER + +using namespace std; + +#define NO_BANKS 2 +#define NO_ROWS 32*1024 + +// Stride register ids are fixed and should not be changed +// CASR should always be reg 0 +#define CASR 0 +// BASR should always be reg 1 +#define BASR 1 +// RASR should always be reg 2 +#define RASR 2 + +#define PATTERN_REG 12 +#define INV_PATTERN_REG 13 +#define TEMP_PATTERN_REG 14 + +#define BAR 3 +#define CAR 4 +#define RARBASE 5 +#define RAR1 6 +#define RAR2 9 + +#define ONE_REG 10 +#define ZERO_REG 11 + +#define ITER_REG 7 +#define CTR_REG 8 + +#define INIT_LOOP 15 + +Program genRowCopy(int t1, int t2, int row1_reg, int row2_reg, int bank_reg) +{ + Program ret; + // t1 -> ACT to PRE, t2 -> PRE to 2nd ACT + int sz = 3 + t1 + t2; + sz = (4-(sz%4)) + sz; + Mininst buff[sz]; + for(int i = 0 ; i < sz ; i++) + buff[i] = SMC_NOP(); + + // Overwrite with the actual sequence + buff[0] = SMC_ACT(bank_reg, 0, row1_reg, 0); + buff[1+t1] = SMC_PRE(bank_reg, 0, 0); + buff[2+t1+t2] = SMC_ACT(bank_reg, 0, row2_reg, 0); + + for(int i = 0 ; i < sz ; i+=4) + ret.add_inst(buff[i], buff[i+1], buff[i+2], buff[i+3]); + + return ret; +} + +/** + * To send an ACT -> SLEEP t1 -> PRE -> SLEEP t2 -> ACT sequence + * This seq. will use BAR RAR1 and RAR2 registers + */ +Program genActPreActSequence(int t1, int t2, int row1_reg, int row2_reg, int bank_reg) +{ + Program ret; + // t1 -> ACT to PRE, t2 -> PRE to 2nd ACT + int sz = 3 + t1 + t2; + sz = (4-(sz%4)) + sz; + Mininst buff[sz]; + for(int i = 0 ; i < sz ; i++) + buff[i] = SMC_NOP(); + + // Overwrite with the actual sequence + buff[0] = SMC_ACT(bank_reg, 0, row1_reg, 0); + buff[1+t1] = SMC_PRE(bank_reg, 0, 0); + buff[2+t1+t2] = SMC_ACT(bank_reg, 0, row2_reg, 0); + + for(int i = 0 ; i < sz ; i+=4) + ret.add_inst(buff[i], buff[i+1], buff[i+2], buff[i+3]); + + return ret; +} + + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ + +Program genCopyRange(int row_reg, int no_rows, int bank_reg, bool stripes) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_inst(SMC_LI(0, ONE_REG)); + ret.add_inst(SMC_LI(1, ZERO_REG)); + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_below(genRowCopy(4,4,ONE_REG,row_reg,bank_reg)); + ret.add_inst(SMC_SLEEP(6)); + ret.add_inst(SMC_PRE(bank_reg, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_ADDI(row_reg, 1, row_reg)); + + ret.add_inst(SMC_SLEEP(6)); + ret.add_below(genRowCopy(4,4,ZERO_REG,row_reg,bank_reg)); + ret.add_inst(SMC_SLEEP(6)); + ret.add_inst(SMC_PRE(bank_reg, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_ADDI(row_reg, 1, row_reg)); + + ret.add_inst(SMC_SLEEP(6)); + + ret.add_below(genRowCopy(4,4,ONE_REG,row_reg,bank_reg)); + ret.add_inst(SMC_SLEEP(6)); + ret.add_inst(SMC_PRE(bank_reg, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_ADDI(row_reg, 1, row_reg)); + ret.add_inst(SMC_SLEEP(6)); + + ret.add_below(genRowCopy(4,4,ZERO_REG,row_reg,bank_reg)); + ret.add_inst(SMC_SLEEP(6)); + ret.add_inst(SMC_PRE(bank_reg, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_ADDI(row_reg, 1, row_reg)); + ret.add_inst(SMC_SLEEP(6)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1000(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ + +Program genWriteRange(int row_reg, int no_rows, int bank_reg, bool stripes) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + for(int i = 0 ; i < 64 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + if(stripes) + { + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + } + ret.add_branch(ret.BR_TYPE::BL, row_reg, INIT_LOOP, "genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +Program genReadRange(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // read until this row + ret.add_label("genReadRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); // TODO: fix this + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + for(int i = 0 ; i < 64 ; i++) + { + ret.add_inst(SMC_READ(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_READ(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_branch(ret.BR_TYPE::BL, row_reg, INIT_LOOP, "genReadRange:LOOP_BEGIN"); + /* + ret.add_inst(SMC_SLEEP(5)); + ret.dump_registers(); + ret.add_inst(SMC_END()); + */ + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} +/** + * @return an instruction formed by NOPs + */ +Inst all_nops() +{ + return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); +} + +Program gen_test_prog(int bank, int r1, int r2,int iters) +{ + Program program; + + program.add_inst(SMC_LI(8, CASR)); // Load 8 into CASR since each READ reads 8 columns + program.add_inst(SMC_LI(1, BASR)); // Load 1 into BASR + program.add_inst(SMC_LI(1, RASR)); // Load 1 into RASR + + program.add_inst(SMC_LI(0xffffffff, PATTERN_REG)); + program.add_inst(SMC_LI(0x00000000, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + + program.add_inst(SMC_LI(bank, BAR)); + program.add_inst(SMC_LI(r1-(r1%4), RARBASE)); + + program.add_inst(SMC_LI(iters, ITER_REG)); + program.add_inst(SMC_LI(0, CTR_REG)); + + program.add_label("WRITE_BEGIN"); + program.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + program.add_inst(SMC_SLEEP(3)); + program.add_below(genWriteRange(RARBASE, 4, BAR, true)); + //program.add_below(genWriteRange1000(RARBASE, 4, BAR)); + //program.add_below(genCopyRange(RARBASE, 4, BAR, true)); + program.add_inst(SMC_LI(r1, RAR1)); + program.add_inst(SMC_LI(r2, RAR2)); + + program.add_below(genActPreActSequence(1, 1, RAR1, RAR2, BAR)); + + program.add_inst(SMC_SLEEP(6)); + program.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + program.add_below(genReadRange(RARBASE, 1, BAR)); + program.add_inst(SMC_ADDI(CTR_REG, 1, CTR_REG)); + + program.add_branch(program.BR_TYPE::BL, CTR_REG, ITER_REG, "WRITE_BEGIN"); + program.add_inst(SMC_END()); + + return program; +} + +bool nonoverlapping_pattern(std::vector bv) +{ + unsigned wsize = bv.size()/8; + uint8_t buf[wsize]; + for(int j = 0 ; j < wsize ; j++) + { + uint8_t intermediate = 0; + for(int k = 0 ; k < 8 ; k++) + intermediate = (intermediate << 1) | bv[j*8 + k]; + buf[j] = intermediate; + } + + int bin[8] = {0}; + for (int i = 0 ; i < (1024*128*8 - 3) ; i += 3) + { + if (i % 8 < 6) + bin[(buf[i/8] >> (i%8)) & 0x7]++; + else + { + int next_bits = 3 - (8-(i%8)); + int next_mask = next_bits == 2 ? 0x3 : 0x1; + int this_mask = next_bits == 2 ? 0x1 : 0x3; + uint8_t next_pattern = (buf[(i/8)+1]) & next_mask; + uint8_t this_pattern = (buf[i/8] >> (i%8)) & this_mask; + bin[(next_pattern << (3-next_bits)) | this_pattern]++; + } + } + + bool pass = true; + for (int i = 0 ; i < 8 ; i++) + { + cout << i << ": " << bin[i] << endl; + if (bin[i] < 30000 || bin[i] > 55000) + pass = false; + } + return pass; +} + +vector pre_filter(SoftMCPlatform& platform, int bank, int row) +{ + vector cells_to_track; + + const int NO_CELLS = 64 * 1024; + const int pre_pre_filter_iterations = 128*1024; + const int threshold_size = 4096; + + Program prog = gen_test_prog(bank, row, row+3, pre_pre_filter_iterations); + platform.execute(prog); + uint8_t buf1[8*1024]; + uint8_t buf2[8*1024]; + + vector> vnc_bitstreams; + + for (int i = 0 ; i < NO_CELLS ; i++) + vnc_bitstreams.push_back(vector()); + + // Von neumann corrector first + for (int i = 0 ; i < pre_pre_filter_iterations/2 ; i++) + { + platform.receiveData((char*)buf1, 8*1024); + platform.receiveData((char*)buf2, 8*1024); + + for (int b = 0 ; b < NO_CELLS ; b++) + { + if(vnc_bitstreams[b].size() == threshold_size) + continue; + + int b1 = (buf1[b/8] >> b%8) & 0x1; + int b2 = (buf2[b/8] >> b%8) & 0x1; + + if (~b1 & b2) + vnc_bitstreams[b].push_back(1); + else if (b1 & ~b2) + vnc_bitstreams[b].push_back(0); + } + } + + int cnt = 0; + for (int b = 0 ; b < NO_CELLS ; b++) + { + if (vnc_bitstreams[b].size() == threshold_size) + cnt++; + } + + cout << cnt << " cells have passed initial filtering." << endl; + + // counter bins for each bitline + int bin[NO_CELLS][8]; + for (int i = 0 ; i < NO_CELLS ; i++) + { + for (int j = 0 ; j < 8 ; j++) + bin[i][j] = 0; + } + + int freq[NO_CELLS] = {0}; + + for (int b = 0 ; b < NO_CELLS ; b++) + { + if (vnc_bitstreams[b].size() < threshold_size - 1) + continue; + for (int i = 0 ; i < (threshold_size - 1)/3 ; i++) + { + int b1 = vnc_bitstreams[b][i] & 0x1; + int b2 = vnc_bitstreams[b][i+1] & 0x1; + int b3 = vnc_bitstreams[b][i+2] & 0x1; + + if (b1) + freq[b]++; + if (b2) + freq[b]++; + if (b3) + freq[b]++; + + bin[b][(b3 << 2) | (b2 << 1) | b1]++; + } + } + + bool passed_frequency[NO_CELLS] = {false}; + + int upper_freq = threshold_size/2 + threshold_size/2/100; + int lower_freq = threshold_size/2 - threshold_size/2/100; + for (int i = 0 ; i < NO_CELLS ; i++) + { + if (vnc_bitstreams[i].size() < threshold_size - 1) + continue; + if (freq[i] < upper_freq && freq[i] > lower_freq) + passed_frequency[i] = true; + } + + cnt = 0; + for (int b = 0 ; b < NO_CELLS ; b++) + { + if (passed_frequency[b]) + cnt++; + } + + cout << cnt << " cells have passed frequency filtering." << endl; + + //cout << "Cell: " << i << endl; + int lower_limit = ((threshold_size - 1) / 3 / 8) - (((threshold_size - 1) / 3 / 8) / 10); + int upper_limit = ((threshold_size - 1) / 3 / 8) + (((threshold_size - 1) / 3 / 8) / 10); + cout << "UL: " << upper_limit << " LL: " << lower_limit << endl; + bool passed[NO_CELLS]; + + for (int b = 0 ; b < NO_CELLS ; b++) + passed[b] = true; + + for (int i = 0 ; i < NO_CELLS ; i++) + { + if (!passed_frequency[i]) + { + passed[i] = false; + continue; + } + for (int j = 0 ; j < 8 ; j++) + { + //cout << "Bin" << j << ": " << bin[i][j] << endl; + if (bin[i][j] < lower_limit || bin[i][j] > upper_limit) + { + //cout << "Cell " << i << " Bin" << j << ": " << bin[i][j] << endl; + passed[i] = false; + break; + } + } + if (passed[i]) + cout << i << " " << "PASSed" << endl; + } + + for (int i = 0 ; i < NO_CELLS ; i++) + { + if (passed[i]) + cells_to_track.push_back(i); + } + + return cells_to_track; +} + +int main(int argc, char *argv[]) +{ + SoftMCPlatform platform; + int err; + + // buffer allocated for reading data from the board + uint8_t buf[8*1024]; + uint8_t prev_read[8*1024]; + + // Initialize the platform, opens file descriptors for the board PCI-E interface. + if((err = platform.init()) != SOFTMC_SUCCESS){ + cerr << "Could not initialize SoftMC Platform: " << err << endl; + } + // reset the board to hopefully restore the board's state + platform.reset_fpga(); + platform.set_aref(true); + + ifstream lfFile; + string trackFn = string(argv[1]) + "/" + "lastrow.txt"; + lfFile.open(trackFn); + + int x=0; + lfFile >> x; + + lfFile.close(); + + for(int bank = 1 ; bank < NO_BANKS ; bank++) + { + for(int r1 = x ; r1 < NO_ROWS ; r1 += 4) + { + bool satisfied = false; + #ifdef NEWFILTER + vector cell_pos = pre_filter(platform, bank, r1); + #else + // Enrollment phase: + // Look at switching activity of each cell in a row + Program prog = gen_test_prog(bank, r1, r1+3, 32*1024); + platform.execute(prog); + int n_switches[64*1024]; // how many times each cell have switched + fill(n_switches, n_switches + 64*1024, 0); + platform.receiveData((char*)prev_read, 8*1024); + for(int k = 0; k < 32*1024-1 ; k++) + { + platform.receiveData((char*)buf, 8*1024); // read one segment each iteration + for(int i = 0 ; i < 8 * 1024 ; i++) + { + uint8_t diff = prev_read[i] ^ buf[i]; + for(int j = 0 ; j < 8 ; j++) + n_switches[i*8 + j] += (diff >> j) & 0x1; + } + copy(begin(buf), end(buf), begin(prev_read)); + } + vector cell_pos; // Switching cell positions + float total_bps = 0; + for(int i = 0 ; i < 8*8*1024 ; i++) + { + // In total it takes 132ms to execute all the DRAM commands + // We compute bps based on switching + total_bps += (1000/132.f) * n_switches[i]; + if(n_switches[i] > 1000) + cell_pos.push_back(i); + } + + cout << "Finished enrollment for bank " << bank << + " row " << r1 << "... " << cell_pos.size() << " cells passed... Predicted bps " + << fixed << setw(11) << setprecision(6) << total_bps << endl; + #endif + + cout << "Finished enrollment for bank " << bank << + " row " << r1 << "... " << cell_pos.size() << " cells passed..." << endl; + + if(cell_pos.size() == 0) + continue; + + for (int i = 0 ; i < cell_pos.size() ; i++) + cout << cell_pos[i] << " "; + cout << endl; + + // Begin filtered acquisition phase + vector> stream_per_cell; + for(int i = 0 ; i < cell_pos.size() ; i++) + { + stream_per_cell.push_back(vector()); + } + + int prev_bpc_i = 0; + int prev_cell_flips[cell_pos.size()]{0}; + + int loop_count = 0; + int loop_limit = 15; + bool bcf = false; // has the best cell exceeded the threshold + + while(!satisfied) + { + if(loop_count == loop_limit) + { + cout << "Exiting because we have iterated enough times" << endl; + break; + } + int iterations = 1024*1024; + Program prog = gen_test_prog(bank, r1, r1+3, iterations); + platform.execute(prog); + + for(int k = 0; k < iterations/2 ; k++) + { + platform.receiveData((char*)prev_read, 8*1024); // read one segment each iteration + platform.receiveData((char*)buf, 8*1024); // read one segment each iteration + //VON NEUMANN CORRECTOR BELOW + for(int i = 0 ; i < cell_pos.size() ; i++) + { + uint8_t b1 = (prev_read[cell_pos[i]/8] >> (cell_pos[i]%8)) & 0x1; + uint8_t b2 = (buf[cell_pos[i]/8] >> (cell_pos[i]%8)) & 0x1; + uint8_t b3 = b1 ^ b2; + if(!b3) continue; + if(b2) stream_per_cell[i].push_back(1); + else stream_per_cell[i].push_back(0); + } + } + + int bpc_flips = 0; // best performing cell flip count + int bpc_i = 0; // best performing cell index + for(int i = 0 ; i < cell_pos.size() ; i++) + { + if(stream_per_cell[i].size() > bpc_flips) + { + bpc_flips = stream_per_cell[i].size(); + bpc_i = i; + } + } + + /* + cout << "Dumping # of switches per cell..." << endl; + for(int i = 0 ; i < cell_pos.size() ; i++) + { + cout << "Cell#" << cell_pos[i] << " Got:" << stream_per_cell[i].size() - prev_cell_flips[i] + << "Exp:" << 32*n_switches[cell_pos[i]] << endl; + } + */ + + if(!bcf) + { + if(prev_bpc_i == bpc_i) + { + int remaining_bits = 1024*1024 - bpc_flips; + int count_diff = bpc_flips - prev_cell_flips[bpc_i]; + if(remaining_bits/count_diff + 1 > 16) + { + cout << "Exiting because it will take too long" << endl; + break; + } + if(remaining_bits < 0){ + cout << "Finished one cell, will keep iterating for 5 iterations" << endl; + bcf = true; + loop_limit = loop_count + 5; + } + else{ + cout << "It will take " << remaining_bits/count_diff + 1 << " more iterations to finish" << endl; + cout << "Based on the best cell's performance which has flipped " << bpc_flips << " times so far" << endl; + } + }else + { + cout << "Cannot approximate test time because the best performing cell changed" << endl; + cout << "Was " << cell_pos[prev_bpc_i] << " Now " << cell_pos[bpc_i] << endl; + } + } + cout << "Cells about to finish: " << endl; + for(int i = 0 ; i < cell_pos.size() ; i++){ + if(stream_per_cell[i].size() > 768*1024) + cout << cell_pos[i] << ":" << stream_per_cell[i].size() << " "; + + prev_cell_flips[i] = stream_per_cell[i].size(); + } + cout << endl; + prev_bpc_i = bpc_i; + loop_count ++; + } + + cout << "Writing bitstreams..." << endl; + int filtered_streams = 0; + for(int i = 0 ; i < cell_pos.size() ; i++){ + if(stream_per_cell[i].size() >= 1024*1024){ //&& nonoverlapping_pattern(stream_per_cell[i])){ + ofstream dump_file; + filtered_streams++; + string fn = string(argv[1]) + "/" + to_string(bank) + "_" + to_string(r1) + + "_" + to_string(r1+3) + "_" + to_string(cell_pos[i]); + dump_file.open(fn, ofstream::binary); + unsigned wsize = stream_per_cell[i].size()/8; + uint8_t wbuf[wsize]; + for(int j = 0 ; j < wsize ; j++) + { + uint8_t intermediate = 0; + for(int k = 0 ; k < 8 ; k++) + intermediate = (intermediate << 1) | stream_per_cell[i][j*8 + k]; + wbuf[j] = intermediate; + } + dump_file.write((char*)wbuf, wsize); + dump_file.close(); + } + } + //cout << "Filtered streams: " << filtered_streams << endl; + cout << "Finished processing b:" << bank << " r1:" << r1 << " r2:" << r1+3 << endl; + ofstream lfFile; + string trackFn = string(argv[1]) + "/" + "lastrow.txt"; + lfFile.open(trackFn); + lfFile << r1; + lfFile.close(); + } + } +} diff --git a/sources/apps/QUAC-TRNG/src/slow_entropy.cpp b/sources/apps/QUAC-TRNG/src/slow_entropy.cpp new file mode 100644 index 0000000..a18cf6e --- /dev/null +++ b/sources/apps/QUAC-TRNG/src/slow_entropy.cpp @@ -0,0 +1,204 @@ +#include "instruction.h" +#include "prog.h" +#include "platform.h" +#include "util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +Program gen_test_prog(int bank, int r1, int r2, int iters, int read_cols, int placement) +{ + Program program; + + program.add_inst(SMC_LI(8, CASR)); // Load 8 into CASR since each READ reads 8 columns + program.add_inst(SMC_LI(1, RASR)); // Load 1 into RASR + + program.add_inst(SMC_LI(bank, BAR)); + program.add_inst(SMC_LI(r1, RARBASE)); + + program.add_inst(SMC_LI(iters, ITER_REG)); + program.add_inst(SMC_LI(0, CTR_REG)); + + program.add_inst(SMC_PRE(BAR,0,1),SMC_NOP(),SMC_NOP(),SMC_NOP()); + program.add_inst(SMC_SLEEP(5)); + + program.add_inst(SMC_LI(r1, RAR1)); + program.add_inst(SMC_LI(r2, RAR2)); + + program.add_label("WRITE_BEGIN"); + //program.add_below(genWriteRange(RARBASE, 4, BAR, true)); + switch(placement) + { + // Invert 0-1 start pattern before here when we set the + // WIDEREG + case 1000: + program.add_below(genWriteRange1000(RARBASE, 4, BAR)); + break; + case 1001: + program.add_below(genWriteRange1001(RARBASE, 4, BAR)); + break; + case 1010: + program.add_below(genWriteRange1010(RARBASE, 4, BAR)); + break; + case 1011: + program.add_below(genWriteRange1011(RARBASE, 4, BAR)); + break; + case 1100: + program.add_below(genWriteRange1100(RARBASE, 4, BAR)); + break; + case 1101: + program.add_below(genWriteRange1101(RARBASE, 4, BAR)); + break; + case 1110: + program.add_below(genWriteRange1110(RARBASE, 4, BAR)); + break; + case 1111: + program.add_below(genWriteRange1111(RARBASE, 4, BAR)); + break; + default: + printf("Unexpected placement encoding\n"); + exit(0); + } + + program.add_below(genActPreActSequence(1, 1, RAR1, RAR2, BAR)); + program.add_inst(SMC_SLEEP(4)); + program.add_inst(SMC_PRE(BAR, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + program.add_inst(SMC_SLEEP(4)); + program.add_below(genReadRange(RARBASE, 1, BAR, read_cols)); + + program.add_inst(SMC_ADDI(CTR_REG, 1, CTR_REG)); + program.add_branch(program.BR_TYPE::BL, CTR_REG, ITER_REG, "WRITE_BEGIN"); + program.add_inst(SMC_END()); + + return program; +} + +int main(int argc, char *argv[]) +{ + bool DUMP_RAW = false; + + SoftMCPlatform platform; + int err; + + // buffer allocated for reading data from the board + uint8_t buf[4*READ_CL*64]; + + // Initialize the platform, opens file descriptors for the board PCI-E interface. + if((err = platform.init()) != SOFTMC_SUCCESS){ + cerr << "Could not initialize SoftMC Platform: " << err << endl; + } + // reset the board to hopefully restore the board's state + platform.reset_fpga(); + platform.set_aref(true); + + int bank = 1; + + int row_stride = atoi(argv[3]); + + string placement = argv[2]; + bool invert = false; + + int iters = atoi(argv[4]); + + ofstream ent_file; + string fn = string(argv[1]) + "/" + to_string(bank) + "_" + to_string(iters) + "_" + to_string(READ_CL) + "_" + to_string(NO_ROWS) + "_" + placement + ".txt"; + cout << "Saving to file " << fn << endl; + ent_file.open(fn); + + char new_placement[10]; + if (placement[0] == '0') + { + for (std::string::size_type i = 0 ; i < placement.size() ; i++) + if(placement[i] == '0') + new_placement[i] = '1'; + else if(placement[i] == '1') + new_placement[i] = '0'; + else + new_placement[i] = placement[i]; + placement = string(new_placement); + invert = true; + } + + Program program; + program.add_inst(SMC_LI(invert ? 0x0 : 0xffffffff, PATTERN_REG)); + program.add_inst(SMC_LI(invert ? 0xffffffff : 0x0, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + program.add_inst(SMC_END()); + platform.execute(program); + + unsigned char *byte_buf[READ_CL*64]; + for(int i = 0 ; i < READ_CL*64 ; i++) + byte_buf[i] = new unsigned char[iters]; + + // Frequency of 1s and 0s generated by each bitline + int alphabet[READ_CL*64*8][2]; + + ent_file << NO_ROWS/row_stride << " " << READ_CL << endl; + + for(int r1 = 0 ; r1 < NO_ROWS ; r1+=row_stride) + { + ent_file << r1 << " "; + Program prog = gen_test_prog(bank, r1, r1+3, iters, READ_CL, std::stoi(placement)); + platform.execute(prog); + + for(int i = 0 ; i < iters ; i++) + { + platform.receiveData((char*)buf, READ_CL*64); // read one segment each iteration + for(int j = 0 ; j < READ_CL*64 ; j++) + byte_buf[j][i] = buf[j]; + } + + for(int i = 0 ; i < READ_CL*64*8 ; i++) + for(int j = 0 ; j < 2 ; j++) + alphabet[i][j] = 0; + + for(int j = 0 ; j < READ_CL*64*8 ; j++) + { + for(int i = 0 ; i < iters ; i++) + alphabet[j][(byte_buf[j/8][i]>>(j%8))&0x1] += 1; + + float approxent = 0; + for(int i = 0 ; i < 2 ; i++) + { + int freq = alphabet[j][i]; + float p = ((float) freq) / ((float) iters); + approxent -= freq == 0 ? 0 : p * log2(p); + } + + ent_file << approxent << " "; + + /* + if(approxent > 0.995) + { + unsigned char bits[iters/8]{0}; + for(int i = 0 ; i < iters ; i++) + bits[i/8] |= ((byte_buf[j/8][i] >> (j%8)) & 0x1) << (7-(i%8)); + ofstream dump_file; + string fn = string(argv[2]) + "/" + to_string(r1) + "_" + to_string(j) + ".bin"; + dump_file.open(fn, ofstream::binary); + dump_file.write((char*)(bits), iters/8); + dump_file.close(); + } + */ + } + + ent_file << endl; + + printf("\rrow %d", r1); + fflush(stdout); + } + for(int i = 0 ; i < READ_CL*64 ; i++) + delete byte_buf[i]; + ent_file.close(); +} diff --git a/sources/apps/QUAC-TRNG/src/slow_sha.cpp b/sources/apps/QUAC-TRNG/src/slow_sha.cpp new file mode 100644 index 0000000..69bf72f --- /dev/null +++ b/sources/apps/QUAC-TRNG/src/slow_sha.cpp @@ -0,0 +1,233 @@ +#include "instruction.h" +#include "prog.h" +#include "platform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "util.h" + +using namespace std; + +// each iter generates 320 bytes of RN +// #define ITERS_SHA 450000 +#define READ_CL 128 + +// Stride register ids are fixed and should not be changed +// CASR should always be reg 0 +#define CASR 0 +// BASR should always be reg 1 +#define BASR 1 +// RASR should always be reg 2 +#define RASR 2 + +#define PATTERN_REG 12 +#define INV_PATTERN_REG 13 +#define TEMP_PATTERN_REG 14 + +#define BAR 3 +#define CAR 4 +#define RARBASE 5 +#define RAR1 6 +#define RAR2 9 + +#define COPY_REG1 10 +#define COPY_REG2 11 + +#define ITER_REG 7 +#define CTR_REG 8 + +#define INIT_LOOP 15 + +Program gen_test_prog(int bank, int r1, int r2, int iters, int placement) +{ + Program program; + + program.add_inst(SMC_LI(8, CASR)); // Load 8 into CASR since each READ reads 8 columns + program.add_inst(SMC_LI(1, BASR)); // Load 1 into BASR + program.add_inst(SMC_LI(1, RASR)); // Load 1 into RASR + + program.add_inst(SMC_LI(bank, BAR)); + program.add_inst(SMC_LI(r1-(r1%4), RARBASE)); + + program.add_inst(SMC_LI(iters, ITER_REG)); + program.add_inst(SMC_LI(0, CTR_REG)); + + program.add_label("WRITE_BEGIN"); + program.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + program.add_inst(SMC_SLEEP(3)); + switch(placement) + { + // Invert 0-1 start pattern before here when we set the + // WIDEREG + case 1000: + program.add_below(genWriteRange1000(RARBASE, 4, BAR)); + break; + case 1001: + program.add_below(genWriteRange1001(RARBASE, 4, BAR)); + break; + case 1010: + program.add_below(genWriteRange1010(RARBASE, 4, BAR)); + break; + case 1011: + program.add_below(genWriteRange1011(RARBASE, 4, BAR)); + break; + case 1100: + program.add_below(genWriteRange1100(RARBASE, 4, BAR)); + break; + case 1101: + program.add_below(genWriteRange1101(RARBASE, 4, BAR)); + break; + case 1110: + program.add_below(genWriteRange1110(RARBASE, 4, BAR)); + break; + case 1111: + program.add_below(genWriteRange1111(RARBASE, 4, BAR)); + break; + default: + printf("Unexpected placement encoding\n"); + exit(0); + } + + //program.add_below(genCopyRange(RARBASE, 4, BAR, true)); + program.add_inst(SMC_LI(r1, RAR1)); + program.add_inst(SMC_LI(r2, RAR2)); + + program.add_below(genActPreActSequence(1, 1, RAR1, RAR2, BAR)); + + program.add_inst(SMC_SLEEP(6)); + program.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + program.add_below(genReadRange(RARBASE, 1, BAR, 128)); + program.add_inst(SMC_ADDI(CTR_REG, 1, CTR_REG)); + + program.add_branch(program.BR_TYPE::BL, CTR_REG, ITER_REG, "WRITE_BEGIN"); + program.add_inst(SMC_END()); + + return program; +} + +int main(int argc, char *argv[]) +{ + SoftMCPlatform platform; + int err; + + // buffer allocated for reading data from the board + unsigned char buf[4*READ_CL*64]; + + // Initialize the platform, opens file descriptors for the board PCI-E interface. + if((err = platform.init()) != SOFTMC_SUCCESS){ + cerr << "Could not initialize SoftMC Platform: " << err << endl; + } + // reset the board to hopefully restore the board's state + platform.reset_fpga(); + platform.set_aref(true); + // Read selected segments from file + // first line: + // each line: + ifstream sf; + string sf_name = string(argv[2]); + sf.open(sf_name); + + int n_segments; sf >> n_segments; + std::vector placements; + std::vector banks, segments; + std::vector ents; + for(int i = 0 ; i < n_segments ; i++) + { + int read; + sf >> read; banks.push_back(read); + sf >> read; segments.push_back(read); + float ent; + sf >> ent; ents.push_back(ent); + std::string rd; + sf >> rd; placements.push_back(rd); + } + + for(int i = 0 ; i < n_segments ; i++) + { + int bank = banks[i]; + int r1 = segments[i]; + float ent = ents[i]; + + if (ent < 1) + continue; + + std::string placement = placements[i]; + + bool invert = false; + // placement_magic + char new_placement[10]; + if (placement[0] == '0') + { + for (std::string::size_type i = 0 ; i < placement.size() ; i++) + if(placement[i] == '0') + new_placement[i] = '1'; + else if(placement[i] == '1') + new_placement[i] = '0'; + else + new_placement[i] = placement[i]; + placement = string(new_placement); + invert = true; + } + + Program program; + program.add_inst(SMC_LI(invert ? 0x0 : 0xffffffff, PATTERN_REG)); + program.add_inst(SMC_LI(invert ? 0xffffffff : 0x0, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + program.add_inst(SMC_END()); + platform.execute(program); + + unsigned char *bitstream; + + unsigned int sha_input_ent = 256; + unsigned int sha_input_blocks = ent/sha_input_ent + 1; + unsigned int row_partition_size = 8192/sha_input_blocks; + // UNTODO //TODO: from now on this is going to be 16Mbits + unsigned int test_iters = (1024*1024*1024)/(8*sha_input_blocks*32); + + + bitstream = new unsigned char[test_iters*32*sha_input_blocks]; + + cout << "Running for " << test_iters << " iterations." << endl; + cout << "Total bits of entropy: " << ent << " -> " << sha_input_blocks << " sha input blocks for the row" << endl; + + Program prog = gen_test_prog(bank, r1, r1+3, test_iters, std::stoi(placement)); + platform.execute(prog); + + for(int i = 0 ; i < test_iters ; i++) + { + platform.receiveData((char*)buf, 8192); // read one segment each iteration + // https://stackoverflow.com/q/13784434 + for(int j = 0 ; j < sha_input_blocks ; j++) + { + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, (char*)(buf+row_partition_size*j), row_partition_size); + SHA256_Final(hash, &sha256); + for(int k = 0 ; k < SHA256_DIGEST_LENGTH ; k++) + { + bitstream[i*sha_input_blocks*SHA256_DIGEST_LENGTH + j*SHA256_DIGEST_LENGTH + k] = hash[k]; + } + } + } + ofstream dump_file; + string fn = string(argv[1]) + "/" + placements[i] + "_" + to_string(r1) + ".bin"; + dump_file.open(fn, ofstream::binary); + dump_file.write((char*)(bitstream), test_iters*32*sha_input_blocks); + dump_file.close(); + printf("\rrow %d", r1); + fflush(stdout); + delete bitstream; + } + +} diff --git a/sources/apps/QUAC-TRNG/src/util.cpp b/sources/apps/QUAC-TRNG/src/util.cpp new file mode 100644 index 0000000..41e4d50 --- /dev/null +++ b/sources/apps/QUAC-TRNG/src/util.cpp @@ -0,0 +1,670 @@ +#include "util.h" + +/** + * To send an ACT -> SLEEP t1 -> PRE -> SLEEP t2 -> ACT sequence + * This seq. will use BAR RAR1 and RAR2 registers + */ +Program genActPreActSequence(int t1, int t2, int row1_reg, int row2_reg, int bank_reg) +{ + Program ret; + // t1 -> ACT to PRE, t2 -> PRE to 2nd ACT + int sz = 3 + t1 + t2; + sz = (4-(sz%4)) + sz; + Mininst buff[sz]; + for(int i = 0 ; i < sz ; i++) + buff[i] = SMC_NOP(); + + // Overwrite with the actual sequence + buff[0] = SMC_ACT(bank_reg, 0, row1_reg, 0); + buff[1+t1] = SMC_PRE(bank_reg, 0, 0); + buff[2+t1+t2] = SMC_ACT(bank_reg, 0, row2_reg, 0); + + for(int i = 0 ; i < sz ; i+=4) + ret.add_inst(buff[i], buff[i+1], buff[i+2], buff[i+3]); + + return ret; +} + +Program genReadRange(int row_reg, int no_rows, int bank_reg, int read_cols) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // read until this row + ret.add_label("genReadRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < read_cols/4 ; i++) + { + ret.add_inst(SMC_READ(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_READ(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_READ(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_READ(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_branch(ret.BR_TYPE::BL, row_reg, INIT_LOOP, "genReadRange:LOOP_BEGIN"); + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + + + + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1000(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1001(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1010(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_branch(ret.BR_TYPE::BL, row_reg, INIT_LOOP, "genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1011(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1100(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_SLEEP(4)); + + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1101(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_SLEEP(4)); + + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1110(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + ret.add_inst(SMC_MV(PATTERN_REG, TEMP_PATTERN_REG)); + ret.add_inst(SMC_MV(INV_PATTERN_REG, PATTERN_REG)); + ret.add_inst(SMC_MV(TEMP_PATTERN_REG, INV_PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + ret.add_inst(SMC_LDWD(PATTERN_REG,i)); + + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * This function will generate a block of instructions that will + * write to a range of rows. It assumes the bank will be precharged. + */ +Program genWriteRange1111(int row_reg, int no_rows, int bank_reg) +{ + Program ret; + ret.add_inst(SMC_LI(no_rows, INIT_LOOP)); + ret.add_inst(SMC_ADD(INIT_LOOP, row_reg, INIT_LOOP)); // write until this row + + ret.add_label("genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_LI(0, CAR)); + + ret.add_inst(SMC_ACT(bank_reg, 0, row_reg, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_SLEEP(4)); + + for(int i = 0 ; i < 32 ; i++) + { + ret.add_inst(SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP(), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0), SMC_NOP()); + ret.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_WRITE(bank_reg, 0, CAR, 1, 0, 0)); + ret.add_inst(SMC_NOP(),SMC_NOP(),SMC_NOP(),SMC_NOP()); + } + ret.add_inst(SMC_SLEEP(4)); + ret.add_inst(SMC_PRE(bank_reg, 0, 1), SMC_NOP(), SMC_NOP(), SMC_NOP()); + + ret.add_branch(ret.BR_TYPE::BL, row_reg, INIT_LOOP, "genWriteRange:LOOP_BEGIN"); + ret.add_inst(SMC_SUBI(row_reg, no_rows, row_reg)); + return ret; +} + +/** + * @return an instruction formed by NOPs + */ +Inst all_nops() +{ + return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); +} diff --git a/sources/apps/QUAC-TRNG/src/util.h b/sources/apps/QUAC-TRNG/src/util.h new file mode 100644 index 0000000..1f07e0e --- /dev/null +++ b/sources/apps/QUAC-TRNG/src/util.h @@ -0,0 +1,55 @@ +#ifndef UTIL_HH +#define UTIL_HH + +#include "prog.h" + +#define ITERS_DUMP 1024*1024 +#define READ_CL_DUMP 8 + +#define ITERS 10000 //1024*1024 // 256*8 +#define READ_CL 128 + +#define NO_BANKS 1 +#define NO_ROWS 1024*32 + +// Stride register ids are fixed and should not be changed +// CASR should always be reg 0 +#define CASR 0 +// BASR should always be reg 1 +#define BASR 1 +// RASR should always be reg 2 +#define RASR 2 + +#define PATTERN_REG 12 +#define INV_PATTERN_REG 13 +#define TEMP_PATTERN_REG 14 + +#define BAR 3 +#define CAR 4 +#define RARBASE 5 +#define RAR1 6 +#define RAR2 9 + +#define COPY_REG1 10 +#define COPY_REG2 11 + +#define ITER_REG 7 +#define CTR_REG 8 + +#define INIT_LOOP 15 + +Program genActPreActSequence(int t1, int t2, int row1_reg, int row2_reg, int bank_reg); +Program genReadRange(int row_reg, int no_rows, int bank_reg, int read_cols); +Program genWriteRange1000(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1111(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1001(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1010(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1011(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1100(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1101(int row_reg, int no_rows, int bank_reg); +Program genWriteRange1110(int row_reg, int no_rows, int bank_reg); +Inst all_nops(); + + + +#endif diff --git a/sources/apps/ResetBoard/SoftMC_reset b/sources/apps/ResetBoard/SoftMC_reset new file mode 100755 index 0000000..709b93c Binary files /dev/null and b/sources/apps/ResetBoard/SoftMC_reset differ diff --git a/sources/apps/ResetBoard/full_reset.sh b/sources/apps/ResetBoard/full_reset.sh new file mode 100755 index 0000000..577a9a9 --- /dev/null +++ b/sources/apps/ResetBoard/full_reset.sh @@ -0,0 +1,9 @@ +#!/bin/bash + + +($( dirname "${BASH_SOURCE[0]}" )/SoftMC_reset) & +pid=$! + +sleep 2 + +kill -9 $pid diff --git a/sources/apps/RetentionTest/Makefile b/sources/apps/RetentionTest/Makefile new file mode 100755 index 0000000..c3828af --- /dev/null +++ b/sources/apps/RetentionTest/Makefile @@ -0,0 +1,28 @@ +program_NAME := SoftMC_Retention +program_CXX_SRCS := retention.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := pthread +CPPFLAGS += -g -std=c++11 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +distclean: clean diff --git a/sources/apps/RetentionTest/retention.cpp b/sources/apps/RetentionTest/retention.cpp new file mode 100644 index 0000000..86b8d98 --- /dev/null +++ b/sources/apps/RetentionTest/retention.cpp @@ -0,0 +1,205 @@ +#include "instruction.h" +#include "prog.h" +#include "platform.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define RETENTION_IN_MS 1000 +#define NUM_BANKS 1 +#define NUM_ROWS 32*1024 + +#define GET_TIME_INIT(num) struct timeval _timers[num] +#define GET_TIME_VAL(num) gettimeofday(&_timers[num], NULL) +#define TIME_VAL_TO_MS(num) (((double)_timers[num].tv_sec*1000.0) + ((double)_timers[num].tv_usec/1000.0)) + +// Need to hand-calculate below value? +// indicates how many rows we can write to +// before testing for retention +// TODO SET THIS TO A REASONABLE VALUE +#define MAX_ROW_PER_ITER 512 + +Inst all_nops() +{ + return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); +} + +int main(int argc, char*argv[]) +{ + Program program; + SoftMCPlatform platform; + int err; + + if(argc != 3) + { + printf("Usage: \n ./SoftMC_RETENTION \n"); + exit(0); + } + + if((err = platform.init()) != SOFTMC_SUCCESS){ + cerr << "Could not initialize SoftMC Platform: " << err << endl; + } + + char* buf = (char*) malloc(sizeof(char)*32*1024); + platform.reset_fpga(); + // sleep(1); + + uint64_t sleep_counter = (uint64_t) ((double) RETENTION_IN_MS * 1000 * 1000 // retention in ns + / 6) ; // 6ns clock period + + assert(sleep_counter < (uint64_t)4*1024*1024*1024 && "Retention time too large to fit into a 32 bit register"); + + printf("Retention time given as %d ms\n", RETENTION_IN_MS); + printf("Will sleep for %ld cycles\n", sleep_counter*6); + + program.add_inst(SMC_LI(8, 0)); // CASR + program.add_inst(SMC_LI(1, 1)); // BASR + program.add_inst(SMC_LI(1, 2)); // RASR + + program.add_inst(SMC_LI(NUM_ROWS, 8)); // NUM_ROWS + program.add_inst(SMC_LI(NUM_BANKS, 11)); + + // To fill wide-reg with data + program.add_inst(SMC_LI(0xffffffff, 7)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(7,i)); + + + program.add_inst(SMC_LI(0, 5)); // BAR + program.add_label("BANK_BEGIN"); + program.add_inst(SMC_LI(MAX_ROW_PER_ITER,7)); + program.add_inst(SMC_LI(0, 4)); // CAR + program.add_inst(SMC_LI(0, 6)); // RAR + + program.add_label("WRITE"); + + // PRE & wait for tRP + program.add_inst(__pack_mininsts( + SMC_PRE(5, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // ACT & wait for tRCD + program.add_inst(__pack_mininsts( + SMC_ACT(5, 0, 6, 1), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // Write to a whole row + for(int i = 0 ; i < 128 ; i++){ + program.add_inst(__pack_mininsts( + SMC_WRITE(5, 0, 4, 1, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + program.add_inst(all_nops()); + } + + // Wait for t(write-precharge) + // & precharge the open bank + program.add_inst(all_nops()); + program.add_inst(all_nops()); + program.add_inst(__pack_mininsts( + SMC_PRE(5, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + + program.add_branch(program.BR_TYPE::BL, 6, 7, "WRITE"); + + // implement "sleep" as a counter + //program.add_label("SLEEP"); + //program.add_inst(SMC_LI(0, 9)); + //program.add_inst(SMC_LI(sleep_counter/7, 10)); + //program.add_label("SLEEP_INNER"); + //program.add_inst(SMC_ADDI(9,1,9)); + //program.add_branch(program.BR_TYPE::BL, 9, 10, "SLEEP_INNER"); + program.add_inst(SMC_SLEEP(sleep_counter)); + + // decrement RAR to read from newly written rows + program.add_inst(SMC_SUBI(6, MAX_ROW_PER_ITER, 6)); + + program.add_label("READ"); + // PRE & wait for tRP + program.add_inst(__pack_mininsts( + SMC_PRE(5, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // ACT & wait for tRCD + program.add_inst(__pack_mininsts( + SMC_ACT(5, 0, 6, 1), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // Read from a whole row + for(int i = 0 ; i < 128 ; i++){ + program.add_inst(__pack_mininsts( + SMC_READ(5, 0, 4, 1, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + program.add_inst(all_nops()); + } + + // Wait for t(read-precharge) + // & precharge the open bank + program.add_inst(all_nops()); + program.add_inst(all_nops()); + program.add_inst(__pack_mininsts( + SMC_PRE(5, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + )); + + program.add_branch(program.BR_TYPE::BEQ, 6, 8, "INC_BANK"); + program.add_branch(program.BR_TYPE::BL, 6, 7, "READ"); + program.add_inst(SMC_ADDI(7, MAX_ROW_PER_ITER, 7)); + program.add_branch(program.BR_TYPE::JUMP, 0, 0, "WRITE"); + + program.add_label("INC_BANK"); + program.add_inst(SMC_ADDI(5,1,5)); + program.add_branch(program.BR_TYPE::BEQ, 5, 11, "END"); + program.add_branch(program.BR_TYPE::JUMP,0,0,"BANK_BEGIN"); + + program.add_label("END"); + program.add_inst(SMC_END()); + + platform.execute(program); + + uint8_t pattern = 0xff; + uint64_t r_count = 0; + + ofstream failures_file; + failures_file.open(std::string(argv[2]), ofstream::binary); + while(1) + { + platform.receiveData(buf,8*1024); + for(int j = 0 ; j < 8*1024 ; j++) + failures_file << (buf[j] ^ pattern); + r_count++; + if(r_count % (NUM_ROWS) == 0) + printf("Bank %ld complete\n", r_count/(NUM_ROWS)); + if(r_count == NUM_BANKS*NUM_ROWS) + break; + printf("\rRead: %ld",r_count); + fflush(stdout); + } + printf("Test complete!\n"); +} diff --git a/sources/apps/SanityCheck/.gitignore b/sources/apps/SanityCheck/.gitignore new file mode 100644 index 0000000..5f2829a --- /dev/null +++ b/sources/apps/SanityCheck/.gitignore @@ -0,0 +1 @@ +SoftMC_Sanity \ No newline at end of file diff --git a/sources/apps/SanityCheck/Makefile b/sources/apps/SanityCheck/Makefile new file mode 100755 index 0000000..19e8a5c --- /dev/null +++ b/sources/apps/SanityCheck/Makefile @@ -0,0 +1,33 @@ +program_NAME := SoftMC_Sanity +program_CXX_SRCS := sanity.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := +CPPFLAGS += -g -std=c++11 -pthread -O3 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) +LDFLAGS += -lboost_program_options + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +parser: + $(MAKE) -C ../../api/lexyacc + cp ../../api/lexyacc/smc_parser . + +distclean: clean diff --git a/sources/apps/SanityCheck/sanity.cpp b/sources/apps/SanityCheck/sanity.cpp new file mode 100644 index 0000000..0c7b0f2 --- /dev/null +++ b/sources/apps/SanityCheck/sanity.cpp @@ -0,0 +1,294 @@ +#include + +#include + +#include "instruction.h" +#include "prog.h" +#include "platform.h" + +using namespace std; +namespace po = boost::program_options; + +#define USE_SMC_FILE 0 + +#define NUM_ROWS_REG 8 +#define NUM_BANKS_REG 11 +#define CASR 0 +#define BASR 1 +#define RASR 2 + +#define PATTERN_REG 12 + +#define BAR 7 +#define RAR 6 +#define CAR 4 + +#define NUM_COLS_REG 14 +#define LOOP_COLS 13 + +#define TEMP_PATTERN_REG 15 + +/** + * @return an instruction formed by NOPs + */ +Inst all_nops() +{ + return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); +} + +int main(int argc, char* argv[]) +{ + uint num_banks, num_rows, num_cols; + + po::options_description help("General options"); + help.add_options()("help,h", "Display the help message\n"); + + po::options_description dram_org("DRAM organization options"); + dram_org.add_options() + ("num_banks", po::value(&num_banks)->required(), "Specify the number of banks in the chip") + ("num_rows", po::value(&num_rows )->required(), "Specify the number of rows per bank") + ("num_cols", po::value(&num_cols )->required(), "Specify the number of columns (cachelines) per row\n") + ; + + po::options_description all; + all.add(help).add(dram_org); + + po::variables_map vm; + try + { + po::store(po::parse_command_line(argc, argv, all), vm); + po::notify(vm); + } + catch(const po::error& e) + { + if (vm.count("help") || argc == 1) + { + std::cout << all << "\n"; + std::exit(1); + } + else + { + std::cerr << "CRITICAL: " << e.what() << std::endl; + std::cerr << " Use \"--help\" to view all options" << std::endl; + std::exit(1); + } + } + + SoftMCPlatform platform; + int err; + uint32_t wr_pattern; + // buffer allocated for reading data from the board + char* buf = (char*) malloc(sizeof(char)*32*1024); + + // Initialize the platform, opens file descriptors for the board PCI-E interface. + if((err = platform.init()) != SOFTMC_SUCCESS) + { + cerr << "Could not initialize SoftMC Platform: " << err << endl; + exit(-1); + } + // reset the board to hopefully restore the board's state + platform.reset_fpga(); + + Program program; + /* SoftMC programs are formed sequentially by adding + * instructions to the program one by one. Instructions + * can be added to the program using add_inst(). + */ + + program.add_inst(SMC_LI(num_rows, NUM_ROWS_REG)); // load NUM_ROWS into NUM_ROWS_REG + program.add_inst(SMC_LI(num_banks, NUM_BANKS_REG)); // load NUM_BANKS into NUM_BANKS_REG + + // Stride registers are used to increment the row,bank,column registers without + // using regular (non-DDR) instructions. This way the DRAM array can be traversed much faster + + program.add_inst(SMC_LI(8, CASR)); // Load 8 into CASR since each READ reads 8 columns + program.add_inst(SMC_LI(1, BASR)); // Load 1 into BASR + program.add_inst(SMC_LI(1, RASR)); // Load 1 into RASR + + // Initialize PRNG, this test will randomly generate + // the first data to write into DRAM, it will modify + // the data by cyclic shifting and multiplying it with itself + // during runtime (this will be further explained down below). + srand(time(NULL)+getpid()); + uint16_t rand1 = (uint16_t) rand(); + wr_pattern = rand1 << 16; + wr_pattern |= ((uint16_t)rand()); + printf("wr_pattern: %x\n", wr_pattern); + + // Load WR data into pattern register whose content + // will be replicated among all words in the wide register + // Wide register is a 512-bit register, its content will + // be written to DRAM with SMC_WR commands. + program.add_inst(SMC_LI(wr_pattern, PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + + program.add_inst(SMC_LI(0, BAR)); // Initialize BAR (bank address register) with 0 + + // add_label is used to add a label that can be used as a branch target to the program + program.add_label("BANK_BEGIN"); + + program.add_inst(SMC_LI(0, RAR)); // Initialize RAR with 0 + + program.add_label("ROW_BEGIN"); + + program.add_inst(SMC_LI(0, CAR)); // Initialize CAR with 0 + + // Four DRAM commands are issued at the same time + // to DRAM by SoftMC. + + // PREcharge bank BAR and wait for tRP (11 NOPs, 11 SoftMC cycles) + program.add_inst( + SMC_PRE(BAR, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + ); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // ACT & wait for tRCD + program.add_inst( + SMC_ACT(BAR, 0, RAR, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + ); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // We are now going to loop over all 512-bits in the row + // Since each row is 2^13 bytes we need to WR 128 times + program.add_inst(SMC_LI(128,NUM_COLS_REG)); // Load COL_SIZE register + program.add_inst(SMC_LI(0,LOOP_COLS)); // Load loop variable + + /* + * Try to write a different pattern to each cache line + * in DRAM. + */ + program.add_label("WR_BEGIN"); + + // Write to a whole row, increment CAR per WR + program.add_inst( + SMC_WRITE(BAR, 0, CAR, 1, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + ); + + // Reload wide reg with the new data pattern + program.add_inst(SMC_SRC(PATTERN_REG,PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + + program.add_inst(SMC_ADDI(LOOP_COLS,1,LOOP_COLS)); + // add a branch lower instruction which will jump to WR_BEGIN + // as long as LOOP_COLS> ((uint32_t)(k%4)*8); + if(mini_patt != (uint8_t)buf[j*64 + k]){ + err_count++; + fprintf(stderr,"t1: Pattern mismatch! Bank: %d Row: %d CacheLine: %d Byte: %d Expect: %x Read: %x\n", + rc/(num_rows), rc%(num_rows), j, k, mini_patt, (uint8_t)buf[j*64 + k]); + } + } + + //shift pattern at each row iteration + uint32_t imd = pattern >> (uint32_t)1; + uint32_t imd2 = pattern << (uint32_t)31; + pattern = imd | imd2; + } + pattern = pattern*(uint32_t)3; + rc++; + if(rc % (num_rows) == 0) + printf("Bank %d finished!\n", rc/num_rows); + if(rc == num_rows*num_banks) + break; + } + + if (err_count != 0) + exit(-1); + else + return 0; +} diff --git a/sources/apps/Smalltest/.gitignore b/sources/apps/Smalltest/.gitignore new file mode 100644 index 0000000..57855ab --- /dev/null +++ b/sources/apps/Smalltest/.gitignore @@ -0,0 +1 @@ +SoftMC_rdwr diff --git a/sources/apps/Smalltest/Makefile b/sources/apps/Smalltest/Makefile new file mode 100755 index 0000000..c7498df --- /dev/null +++ b/sources/apps/Smalltest/Makefile @@ -0,0 +1,32 @@ +program_NAME := SoftMC_rdwr +program_CXX_SRCS := read_write.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.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 := ../../api ../../../boost-lib +program_LIBRARY_DIRS := +program_LIBRARIES := +CPPFLAGS += -g -std=c++11 -pthread -O3 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +parser: + $(MAKE) -C ../../api/lexyacc + cp ../../api/lexyacc/smc_parser . + +distclean: clean diff --git a/sources/apps/Smalltest/read_write.cpp b/sources/apps/Smalltest/read_write.cpp new file mode 100644 index 0000000..608b17a --- /dev/null +++ b/sources/apps/Smalltest/read_write.cpp @@ -0,0 +1,293 @@ +#include "instruction.h" +#include "prog.h" +#include "platform.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define USE_SMC_FILE 0 + +#define NUM_BANKS 16 +#define NUM_ROWS 1024*32 + +#define NUM_ROWS_REG 8 +#define NUM_BANKS_REG 11 +// Stride register ids are fixed and should not be changed +// CASR should always be reg 0 +// BASR should always be reg 1 +// RASR should always be reg 2 +#define CASR 0 +#define BASR 1 +#define RASR 2 + +#define PATTERN_REG 12 + +#define BAR 7 +#define RAR 6 +#define CAR 4 + +#define NUM_COLS_REG 14 +#define LOOP_COLS 13 + +#define TEMP_PATTERN_REG 15 + +/** + * @return an instruction formed by NOPs + */ +Inst all_nops() +{ + return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP()); +} + +int main() +{ + SoftMCPlatform platform; + int err; + uint32_t wr_pattern; + // buffer allocated for reading data from the board + char* buf = (char*) malloc(sizeof(char)*32*1024); + + // Demo using the smc file as program input + if(USE_SMC_FILE) + { + // Load demo smc program from file using + // program's constructor + Program program("read_write.smc"); + wr_pattern = 0x1a2b3c4d; + printf("Program Ready\n"); + + // Initialize the platform, opens file descriptors for the board PCI-E interface. + if((err = platform.init()) != SOFTMC_SUCCESS){ + cerr << "Could not initialize SoftMC Platform: " << err << endl; + } + // reset the board to hopefully restore the board's state + platform.reset_fpga(); + // Transfer the program to the FPGA board + platform.execute(program); + printf("Sent instructions\n"); + } + else + { + + // Initialize the platform, opens file descriptors for the board PCI-E interface. + if((err = platform.init()) != SOFTMC_SUCCESS){ + cerr << "Could not initialize SoftMC Platform: " << err << endl; + } + // reset the board to hopefully restore the board's state + platform.reset_fpga(); + + Program program; + /* SoftMC programs are formed sequentially by adding + * instructions to the program one by one. Instructions + * can be added to the program using add_inst(). + */ + + program.add_inst(SMC_LI(NUM_ROWS, NUM_ROWS_REG)); // load NUM_ROWS into NUM_ROWS_REG + program.add_inst(SMC_LI(NUM_BANKS, NUM_BANKS_REG)); // load NUM_BANKS into NUM_BANKS_REG + + // Stride registers are used to increment the row,bank,column registers without + // using regular (non-DDR) instructions. This way the DRAM array can be traversed much faster + + program.add_inst(SMC_LI(8, CASR)); // Load 8 into CASR since each READ reads 8 columns + program.add_inst(SMC_LI(1, BASR)); // Load 1 into BASR + program.add_inst(SMC_LI(1, RASR)); // Load 1 into RASR + + // Initialize PRNG, this test will randomly generate + // the first data to write into DRAM, it will modify + // the data by cyclic shifting and multiplying it with itself + // during runtime (this will be further explained down below). + srand(time(NULL)+getpid()); + uint16_t rand1 = (uint16_t) rand(); + wr_pattern = rand1 << 16; + wr_pattern |= ((uint16_t)rand()); + printf("wr_pattern: %x\n", wr_pattern); + + // Load WR data into pattern register whose content + // will be replicated among all words in the wide register + // Wide register is a 512-bit register, its content will + // be written to DRAM with SMC_WR commands. + program.add_inst(SMC_LI(wr_pattern, PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + + program.add_inst(SMC_LI(0, BAR)); // Initialize BAR (bank address register) with 0 + + // add_label is used to add a label that can be used as a branch target to the program + program.add_label("BANK_BEGIN"); + + program.add_inst(SMC_LI(0, RAR)); // Initialize RAR with 0 + + program.add_label("ROW_BEGIN"); + + program.add_inst(SMC_LI(0, CAR)); // Initialize CAR with 0 + + // Four DRAM commands are issued at the same time + // to DRAM by SoftMC. + + // PREcharge bank BAR and wait for tRP (11 NOPs, 11 SoftMC cycles) + program.add_inst( + SMC_PRE(BAR, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + ); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // ACT & wait for tRCD + program.add_inst( + SMC_ACT(BAR, 0, RAR, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + ); + program.add_inst(all_nops()); + program.add_inst(all_nops()); + + // We are now going to loop over all 512-bits in the row + // Since each row is 2^13 bytes we need to WR 128 times + program.add_inst(SMC_LI(128,NUM_COLS_REG)); // Load COL_SIZE register + program.add_inst(SMC_LI(0,LOOP_COLS)); // Load loop variable + + /* + * Try to write a different pattern to each cache line + * in DRAM. + */ + program.add_label("WR_BEGIN"); + + // Write to a whole row, increment CAR per WR + program.add_inst( + SMC_WRITE(BAR, 0, CAR, 1, 0, 0), + SMC_NOP(), SMC_NOP(), SMC_NOP() + ); + + // Reload wide reg with the new data pattern + program.add_inst(SMC_SRC(PATTERN_REG,PATTERN_REG)); + for(int i = 0 ; i < 16 ; i++) + program.add_inst(SMC_LDWD(PATTERN_REG,i)); + + program.add_inst(SMC_ADDI(LOOP_COLS,1,LOOP_COLS)); + // add a branch lower instruction which will jump to WR_BEGIN + // as long as LOOP_COLS> ((uint32_t)(k%4)*8); + if(mini_patt != (uint8_t)buf[j*64 + k]){ + err_count++; + fprintf(stderr,"t1: Pattern mismatch! Bank: %d Row: %d CacheLine: %d Byte: %d Expect: %x Read: %x\n", + rc/(1024*32), rc%(1024*32), j, k, mini_patt, (uint8_t)buf[j*64 + k]); + //fprintf(stderr,"%d %d %d %x\n", + // rc/(1024*32), rc%(1024*32), j*64 + k, mini_patt^(uint8_t)buf[j*64 + k]); + } + } + + //shift pattern at each row iteration + uint32_t imd = pattern >> (uint32_t)1; + uint32_t imd2 = pattern << (uint32_t)31; + pattern = imd | imd2; + } + pattern = pattern*(uint32_t)3; + rc++; + if(rc % (1024*32) == 0) + printf("Bank %d finished!\n", rc/1024/32); + if(rc == 1024*32*16) + break; + } + printf("%ld out of %ld bytes have errors, last pattern: 0x%x\n", + err_count, (uint64_t)NUM_BANKS*NUM_ROWS*8192, pattern); + platform.readRegisterDump(); +} diff --git a/sources/apps/Smalltest/read_write.smc b/sources/apps/Smalltest/read_write.smc new file mode 100644 index 0000000..c4bfd5f --- /dev/null +++ b/sources/apps/Smalltest/read_write.smc @@ -0,0 +1,170 @@ +// Initialize register ids +// Similar to #define +casr = 0 +basr = 1 +rasr = 2 +bar = 7 +rar = 6 +car = 4 +pattern_reg = 12 +no_row_reg = 8 +no_bank_reg = 11 +no_cols_reg = 14 +loop_cols_reg = 13 +temp_pattern_reg = 15 + +// Begin writing the program +LI no_row_reg 32768 // Write 2^15 to no_row_Reg +LI no_bank_reg 16 // write 16 to no_bank_reg + +// Set stride registers (not required if you +// are not going to increment address registers +// with ddr commands) +LI casr 8 // set column address stride to 8 +LI basr 1 // set bas to 1 +LI rasr 1 // set ras to 1 + +// Init pattern register, we are going to fill +// dram with some random pattern. +LI pattern_reg 0x1a2b3c4d + +// Load the data register with the pattern +// second argument here is the word offset +// we are writing to in the data register +// e.g. LDWD 0 pattern reg fills the first four bytes + +LDWD 0 pattern_reg +LDWD 1 pattern_reg +LDWD 2 pattern_reg +LDWD 3 pattern_reg +LDWD 4 pattern_reg +LDWD 5 pattern_reg +LDWD 6 pattern_reg +LDWD 7 pattern_reg +LDWD 8 pattern_reg +LDWD 9 pattern_reg +LDWD 10 pattern_reg +LDWD 11 pattern_reg +LDWD 12 pattern_reg +LDWD 13 pattern_reg +LDWD 14 pattern_reg +LDWD 15 pattern_reg + +LI bar 0 // Initialize bank address register + +BANK_BEGIN: // Add label to loop over banks +LI rar 0 // Reload rar per bank loop + +ROW_BEGIN: // Add label to loop over rows +LI car 0 // Reload car per row loop + +PRE bar // PREcharge bar, don't increment, no precharge-all +WAIT 11 // Insert seven cycles of NOPs + +ACT bar rar // ACTivate bar, rar +WAIT 11 + +// Each write will write a different pattern +// "car++" indicates that we will increment +// car by casr value. + +LI no_cols_reg 128 +LI loop_cols_reg 0 + +WR_BEGIN: + +WR bar car++ +WAIT 3 + +// Cyclic shift pattern register to add "randomness" +SRC pattern_reg pattern_reg + +// Reload the wide data register +LDWD 0 pattern_reg +LDWD 1 pattern_reg +LDWD 2 pattern_reg +LDWD 3 pattern_reg +LDWD 4 pattern_reg +LDWD 5 pattern_reg +LDWD 6 pattern_reg +LDWD 7 pattern_reg +LDWD 8 pattern_reg +LDWD 9 pattern_reg +LDWD 10 pattern_reg +LDWD 11 pattern_reg +LDWD 12 pattern_reg +LDWD 13 pattern_reg +LDWD 14 pattern_reg +LDWD 15 pattern_reg + +// increment loop variable and iterate +ADDI loop_cols_reg loop_cols_reg 1 +BL WR_BEGIN loop_cols_reg no_cols_reg + +// multiply pattern_reg by 3 +MOV temp_pattern_reg pattern_reg +ADD pattern_reg pattern_reg temp_pattern_reg +ADD pattern_reg pattern_reg temp_pattern_reg + +// Reload the wide data register +LDWD 0 pattern_reg +LDWD 1 pattern_reg +LDWD 2 pattern_reg +LDWD 3 pattern_reg +LDWD 4 pattern_reg +LDWD 5 pattern_reg +LDWD 6 pattern_reg +LDWD 7 pattern_reg +LDWD 8 pattern_reg +LDWD 9 pattern_reg +LDWD 10 pattern_reg +LDWD 11 pattern_reg +LDWD 12 pattern_reg +LDWD 13 pattern_reg +LDWD 14 pattern_reg +LDWD 15 pattern_reg + +WAIT 8 +PRE bar +WAIT 3 + +// Reload car, we are now going to read from DRAM +LI car 0 + +// Precharge the open bank +PRE bar +WAIT 11 + +ACT bar rar +WAIT 11 + +// This is a basic primitive that can be used +// to replicate instructions-commands +// this block replicates the RD command 128 times +// and adds it to the program +times 128 { + RD bar car++ + WAIT 7 +} + +WAIT 8 +PRE bar +WAIT 3 + +// Increment rar per row loop +ADDI rar rar 1 +// if rar < no_row_reg, execute the "row loop" once more +BL ROW_BEGIN rar no_row_reg + +ADDI bar bar 1 +BL BANK_BEGIN bar no_bank_reg + +WAIT 16 + +// Tell softmc that the program has ended +// This is important! +END + +// Tell the parser the program definition has ended +// This is even more important!! +ENDPROGRAM diff --git a/sources/apps/parsertest/Makefile b/sources/apps/parsertest/Makefile new file mode 100755 index 0000000..6ca92f2 --- /dev/null +++ b/sources/apps/parsertest/Makefile @@ -0,0 +1,27 @@ +program_NAME := SoftMC_Example +program_CXX_SRCS := ptest.cpp $(wildcard ../../api/*.c*) +program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o} +program_OBJS := $(program_CXX_OBJS) +program_INCLUDE_DIRS := ../../api/ +program_LIBRARY_DIRS := +program_LIBRARIES := +CPPFLAGS += -g -std=c++11 + +CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir)) +LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir)) +LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library)) + +CC=g++ + +.PHONY: all clean distclean + +all: $(program_NAME) + +$(program_NAME): $(program_OBJS) + $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS) + +clean: + @- $(RM) $(program_NAME) + @- $(RM) $(program_OBJS) + +distclean: clean diff --git a/sources/apps/parsertest/SoftMC_Example b/sources/apps/parsertest/SoftMC_Example new file mode 100755 index 0000000..c5146bf Binary files /dev/null and b/sources/apps/parsertest/SoftMC_Example differ diff --git a/sources/apps/parsertest/example.smc b/sources/apps/parsertest/example.smc new file mode 100644 index 0000000..a8cac7a --- /dev/null +++ b/sources/apps/parsertest/example.smc @@ -0,0 +1,9 @@ +LI 0 8; +LI 1 1; +LI 2 1; +LI 3 0; +LI 4 0; +LI 5 0; +BEGIN:; +WR 5 0 4 0 0 0, NOP, NOP, NOP; +END; diff --git a/sources/apps/parsertest/ptest.cpp b/sources/apps/parsertest/ptest.cpp new file mode 100644 index 0000000..28aabac --- /dev/null +++ b/sources/apps/parsertest/ptest.cpp @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include +#include "prog.h" +#include "parser.h" + +int main() +{ + // https://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring + std::ifstream t("example.smc"); + std::stringstream buffer; + buffer << t.rdbuf(); + string program = buffer.str(); + Parser p; + p.parse_program(program); +} -- cgit v1.2.3