diff options
Diffstat (limited to 'sources/apps/QUAC-TRNG')
22 files changed, 2573 insertions, 0 deletions
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 <DIMM_NAME> <TEMPERATURE_IN_CELCIUS> <QUAC_ITERATIONS> <ROW_STRIDE> +``` + +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 <DIMM_NAME> <TEMPERATURE_IN_CELCIUS> +``` + +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 <DIMM_NAME> <PATTERN> <TEMPERATURE>` +3- Run the SHA-256 bitstream generator script: `python3 scripts/sha_bitstreams.py <DIMM_NAME> <PATTERN> <TEMPERATURE>`
\ 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 --- /dev/null +++ b/sources/apps/QUAC-TRNG/bin/.gitkeep 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 --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/ft200_rc/__init__.py 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 Binary files differnew file mode 100644 index 0000000..8c18eaa --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/1189902393_ft200_lcd.pdf diff --git a/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf Binary files differnew file mode 100644 index 0000000..e4d0d39 --- /dev/null +++ b/sources/apps/QUAC-TRNG/scripts/ft200_rc/docs/210.pdf 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 <fstream> +#include <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <cstring> +#include <list> +#include <algorithm> +#include <iterator> +#include <iomanip> + +#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<uint8_t> 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<int> pre_filter(SoftMCPlatform& platform, int bank, int row) +{ + vector<int> 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<vector<uint8_t>> vnc_bitstreams; + + for (int i = 0 ; i < NO_CELLS ; i++) + vnc_bitstreams.push_back(vector<uint8_t>()); + + // 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<int> 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<int> 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<vector<uint8_t>> stream_per_cell; + for(int i = 0 ; i < cell_pos.size() ; i++) + { + stream_per_cell.push_back(vector<uint8_t>()); + } + + 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 <fstream> +#include <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <cstring> +#include <list> +#include <math.h> +#include <algorithm> +#include <iterator> +#include <iomanip> + +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 <fstream> +#include <iostream> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <cstring> +#include <list> +#include <algorithm> +#include <iterator> +#include <iomanip> +#include <openssl/sha.h> +#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: <number of segments> + // each line: <bank> <segment_start> <placement> + ifstream sf; + string sf_name = string(argv[2]); + sf.open(sf_name); + + int n_segments; sf >> n_segments; + std::vector<std::string> placements; + std::vector<int> banks, segments; + std::vector<float> 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 |
