aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/apps/case_studies/cs1_interleaving_pattern/Makefile33
-rw-r--r--sources/apps/case_studies/cs1_interleaving_pattern/README.md10
-rw-r--r--sources/apps/case_studies/cs1_interleaving_pattern/test.cpp435
-rw-r--r--sources/apps/case_studies/cs1_interleaving_pattern/tools.h213
-rw-r--r--sources/apps/case_studies/cs2_data_patterns/Makefile33
-rw-r--r--sources/apps/case_studies/cs2_data_patterns/README.md11
-rw-r--r--sources/apps/case_studies/cs2_data_patterns/test.cpp561
-rw-r--r--sources/apps/case_studies/cs2_data_patterns/tools.h213
-rw-r--r--sources/apps/case_studies/cs3_bitwise/Makefile33
-rw-r--r--sources/apps/case_studies/cs3_bitwise/README.md23
-rw-r--r--sources/apps/case_studies/cs3_bitwise/run_tests.sh12
-rw-r--r--sources/apps/case_studies/cs3_bitwise/test.cpp309
12 files changed, 1886 insertions, 0 deletions
diff --git a/sources/apps/case_studies/cs1_interleaving_pattern/Makefile b/sources/apps/case_studies/cs1_interleaving_pattern/Makefile
new file mode 100644
index 0000000..953fe34
--- /dev/null
+++ b/sources/apps/case_studies/cs1_interleaving_pattern/Makefile
@@ -0,0 +1,33 @@
+program_NAME := TEST
+program_CXX_SRCS := test.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/case_studies/cs1_interleaving_pattern/README.md b/sources/apps/case_studies/cs1_interleaving_pattern/README.md
new file mode 100644
index 0000000..43d7f32
--- /dev/null
+++ b/sources/apps/case_studies/cs1_interleaving_pattern/README.md
@@ -0,0 +1,10 @@
+## Case Study #1: RowHammer: Interleaving Pattern of Activations
+
+### Instructions
+
+1. run `make` to compile the DRAM Bender program
+2. execute `./TEST <hc_per_aggr> <cascade_amount> <data_pattern_select> <out_filename>` to run the experiment
+ - hc_per_aggr: Total number of activation per aggressor row.
+ - cascade_amount: The number of consecutive activations for a aggressor row. Value 1 results with double-sided RH attack.
+ - data_pattern_select: selects the data pattern for victim and aggressor rows.
+ - out_filename: output filename for the results. The output file has the number of bitflips for each victim row.
diff --git a/sources/apps/case_studies/cs1_interleaving_pattern/test.cpp b/sources/apps/case_studies/cs1_interleaving_pattern/test.cpp
new file mode 100644
index 0000000..13646b5
--- /dev/null
+++ b/sources/apps/case_studies/cs1_interleaving_pattern/test.cpp
@@ -0,0 +1,435 @@
+#include "instruction.h"
+#include "prog.h"
+#include "platform.h"
+#include "tools.h"
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <cassert>
+#include <bitset>
+#include <chrono>
+#include <math.h>
+
+#include <array>
+#include <algorithm>
+#include <numeric>
+#include <ctime>
+
+// #define PRINT_SOFTMC_PROGS
+
+using namespace std;
+
+#define CASR 0
+#define BASR 1
+#define RASR 2
+
+#define NUM_SOFTMC_REGS 16
+#define FPGA_PERIOD 1.5015f // ns
+
+#define RED_TXT "\033[31m"
+#define GREEN_TXT "\033[32m"
+#define YELLOW_TXT "\033[33m"
+#define BLUE_TXT "\033[34m"
+#define MAGENTA_TXT "\033[35m"
+#define NORMAL_TXT "\033[0m"
+
+int NUM_BANKS = 16; // this is the total number of banks in the chip
+int NUM_BANK_GROUPS = 4;
+int NUM_ROWS = 32768;
+int ROW_SIZE = 8192;
+int NUM_COLS_PER_ROW = 128;
+int CHIP_NUM = 4;
+int CACHE_LINE_BITS = 512;
+
+float DEFAULT_TRCD = 13.5f; // ns
+float DEFAULT_TRAS = 35.0f; // ns
+float DEFAULT_TRP = 13.5f; // ns
+float DEFAULT_TWR = 15.0f; // ns
+float DEFAULT_TRFC = 260.0f; // ns
+float DEFAULT_TRRDS = 5.3f; // ns (ACT-ACT to different bank groups)
+float DEFAULT_TRRDL = 6.4f; // ns (ACT-ACT to same bank group)
+float DEFAULT_TREFI = 7800.0f;
+
+int trcd_cycles = (int) ceil(DEFAULT_TRCD/FPGA_PERIOD);
+int tras_cycles = (int) ceil(DEFAULT_TRAS/FPGA_PERIOD);
+int trp_cycles = (int) ceil(DEFAULT_TRP/FPGA_PERIOD);
+int twr_cycles = (int) ceil(DEFAULT_TWR/FPGA_PERIOD);
+int trfc_cycles = (int) ceil(DEFAULT_TRFC/FPGA_PERIOD);
+int trrds_cycles = (int) ceil(DEFAULT_TRRDS/FPGA_PERIOD);
+int trrdl_cycles = (int) ceil(DEFAULT_TRRDL/FPGA_PERIOD);
+int trefi_cycles = (int) ceil(DEFAULT_TREFI/FPGA_PERIOD);
+
+bitset<512> vic_data_pattern, aggr_data_pattern;
+vector<uint32_t> reserved_regs{CASR, BASR, RASR};
+
+typedef struct RowSet {
+ vector<uint> victim_ids;
+ vector<uint> aggr_ids;
+ uint bank_id;
+} RowSet;
+
+void init_program(Program& prog){
+ add_op_with_delay(prog, SMC_PRE(0, 0, 1), 0, trp_cycles); // precharge all banks
+}
+
+void end_program(Program& prog){
+ prog.add_inst(all_nops());
+ prog.add_inst(SMC_END());
+}
+
+void init_row(Program* prog, SoftMCRegAllocator* reg_alloc, const uint target_bank, const uint target_row, const bool is_victim){
+
+ SMC_REG reg_row_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_col_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_bank_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_cols = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_wrdata = reg_alloc->allocate_SMC_REG();
+
+ bitset<512> bitset_int_mask(0xFFFFFFFF);
+ bitset<512> data_pattern;
+
+ if(is_victim)
+ data_pattern = vic_data_pattern;
+ else
+ data_pattern = aggr_data_pattern;
+
+ prog->add_inst(SMC_LI(NUM_COLS_PER_ROW*8, reg_num_cols));
+ prog->add_inst(SMC_LI(target_bank, reg_bank_addr));
+ prog->add_inst(SMC_LI(target_row, reg_row_addr));
+ prog->add_inst(SMC_LI(8, CASR));
+
+ // set up the input data in the wide register
+ for(int pos = 0; pos < 16; pos++){
+ prog->add_inst(SMC_LI((((data_pattern >> 32*pos) & bitset_int_mask).to_ulong() & 0xFFFFFFFF), reg_wrdata));
+ prog->add_inst(SMC_LDWD(reg_wrdata, pos));
+ }
+
+ // activate the target row
+ uint remaining = add_op_with_delay(*prog, SMC_ACT(reg_bank_addr, 0, reg_row_addr, 0), 0, trcd_cycles - 5);
+
+ // write data to the row and precharge
+ prog->add_inst(SMC_LI(0, reg_col_addr));
+
+ string new_lbl = createSMCLabel("INIT_ROW");
+ prog->add_label(new_lbl);
+ add_op_with_delay(*prog, SMC_WRITE(reg_bank_addr, 0, reg_col_addr, 1, 0, 0), 0, 0);
+ prog->add_branch(Program::BR_TYPE::BL, reg_col_addr, reg_num_cols, new_lbl);
+
+ // precharge the open bank
+ add_op_with_delay(*prog, SMC_PRE(reg_bank_addr, 0, 0), 0, trp_cycles);
+
+ reg_alloc->free_SMC_REG(reg_row_addr);
+ reg_alloc->free_SMC_REG(reg_col_addr);
+ reg_alloc->free_SMC_REG(reg_wrdata);
+ reg_alloc->free_SMC_REG(reg_bank_addr);
+ reg_alloc->free_SMC_REG(reg_num_cols);
+
+}
+
+void init_rs(Program* prog, SoftMCRegAllocator* reg_alloc, const RowSet rs) {
+ //init aggrs
+ for(auto aggr_id: rs.aggr_ids)
+ init_row(prog, reg_alloc, rs.bank_id, aggr_id, false);
+ //init victims
+ for(auto victim_id: rs.victim_ids)
+ init_row(prog, reg_alloc, rs.bank_id, victim_id, true);
+}
+
+void hammer_rs(Program* prog, SoftMCRegAllocator* reg_alloc, const RowSet rs,
+ const uint hc_per_run, const uint num_runs){
+
+ SMC_REG reg_bank_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_row_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_hammers = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_cur_hammers = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_runs = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_cur_runs = reg_alloc->allocate_SMC_REG();
+
+ prog->add_inst(SMC_LI(rs.bank_id, reg_bank_addr));
+ prog->add_inst(SMC_LI(hc_per_run, reg_num_hammers));
+ prog->add_inst(SMC_LI(num_runs, reg_num_runs));
+
+ prog->add_inst(SMC_LI(0, reg_cur_runs));
+ string lbl_hammer_run = createSMCLabel("HAMMER_RUN");
+ prog->add_label(lbl_hammer_run);
+
+ for(auto aggr_id: rs.aggr_ids){
+ prog->add_inst(SMC_LI(aggr_id, reg_row_addr));
+ prog->add_inst(SMC_LI(0, reg_cur_hammers));
+
+ string lbl_rh = createSMCLabel("ROWHAMMERING");
+ prog->add_label(lbl_rh);
+
+ uint remaining_cycs = add_op_with_delay(*prog, SMC_ACT(reg_bank_addr, 0, reg_row_addr, 0), 0, tras_cycles - 1);
+ remaining_cycs = add_op_with_delay(*prog, SMC_PRE(reg_bank_addr, 0, 0), remaining_cycs, 0);
+
+ prog->add_inst(SMC_ADDI(reg_cur_hammers, 1, reg_cur_hammers));
+ prog->add_branch(Program::BR_TYPE::BL, reg_cur_hammers, reg_num_hammers, lbl_rh);
+
+ }
+
+ prog->add_inst(SMC_ADDI(reg_cur_runs, 1, reg_cur_runs));
+ prog->add_branch(Program::BR_TYPE::BL, reg_cur_runs, reg_num_runs, lbl_hammer_run);
+
+ reg_alloc->free_SMC_REG(reg_bank_addr);
+ reg_alloc->free_SMC_REG(reg_row_addr);
+ reg_alloc->free_SMC_REG(reg_num_hammers);
+ reg_alloc->free_SMC_REG(reg_cur_hammers);
+ reg_alloc->free_SMC_REG(reg_num_runs);
+ reg_alloc->free_SMC_REG(reg_cur_runs);
+}
+
+void read_row(Program* prog, SoftMCRegAllocator* reg_alloc, const uint bank_id, const uint row_id){
+
+ SMC_REG reg_bank_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_cols = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_row_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_col_addr = reg_alloc->allocate_SMC_REG();
+
+ prog->add_inst(SMC_LI(8, CASR));
+ prog->add_inst(SMC_LI(NUM_COLS_PER_ROW*8, reg_num_cols));
+ prog->add_inst(SMC_LI(bank_id, reg_bank_addr));
+ prog->add_inst(SMC_LI(row_id, reg_row_addr));
+
+ // activate the victim row
+ add_op_with_delay(*prog, SMC_ACT(reg_bank_addr, 0, reg_row_addr, 0), 0, trcd_cycles - 5);
+ prog->add_inst(SMC_LI(0, reg_col_addr));
+
+ // read data from the row and precharge
+ string new_lbl = createSMCLabel("READ_ROW");
+ prog->add_label(new_lbl);
+ add_op_with_delay(*prog, SMC_READ(reg_bank_addr, 0, reg_col_addr, 1, 0, 0), 0, 0);
+ prog->add_branch(Program::BR_TYPE::BL, reg_col_addr, reg_num_cols, new_lbl);
+
+ // precharge the open bank
+ add_op_with_delay(*prog, SMC_PRE(reg_bank_addr, 0, 0), 0, trp_cycles);
+
+ reg_alloc->free_SMC_REG(reg_bank_addr);
+ reg_alloc->free_SMC_REG(reg_num_cols);
+ reg_alloc->free_SMC_REG(reg_row_addr);
+ reg_alloc->free_SMC_REG(reg_col_addr);
+
+}
+
+void read_rs(Program* prog, SoftMCRegAllocator* reg_alloc, const RowSet rs){
+ for(auto victim_id: rs.victim_ids)
+ read_row(prog, reg_alloc, rs.bank_id, victim_id);
+}
+
+vector<uint> collect_bitflips(const char* read_data){
+
+ bitset<512> read_data_bitset;
+ vector<uint> bitflips;
+ uint32_t* iread_data = (uint32_t*) read_data;
+ uint bit_loc;
+
+ // check for bitflips in each cache line
+ for(int cl = 0; cl < ROW_SIZE/64; cl++) {
+ read_data_bitset.reset();
+ for(int i = 0; i < 512/32; i++) {
+ bitset<512> tmp_bitset = iread_data[cl*(512/32) + i];
+
+ read_data_bitset |= (tmp_bitset << i*32);
+ }
+ // compare and print errors
+ bitset<512> error_mask = read_data_bitset ^ vic_data_pattern;
+ if(error_mask.any()) {
+ // there is at least one bitflip in this cache line
+ for(uint i = 0; i < error_mask.size(); i++){
+ if(error_mask.test(i)){
+ bit_loc = cl*CACHE_LINE_BITS + i;
+ bitflips.push_back(bit_loc);
+ }
+ }
+ }
+ }
+
+ return bitflips;
+}
+
+vector<uint> get_bitflips(SoftMCPlatform& platform, const RowSet& rs){
+
+ vector<uint> num_bitflips;
+ uint read_data_size = ROW_SIZE*rs.victim_ids.size();
+
+ char buf[read_data_size*2];
+
+ platform.receiveData(buf, read_data_size);
+ for(uint vic_ind = 0; vic_ind < rs.victim_ids.size(); vic_ind++){
+ auto bitflips = collect_bitflips(buf + vic_ind*ROW_SIZE);
+ num_bitflips.push_back(bitflips.size());
+ }
+ return num_bitflips;
+}
+
+vector<uint> run_single_test(SoftMCPlatform& platform, const RowSet rs,
+ const uint hc_per_run, const uint num_runs,
+ const uint remaining_hc){
+
+ Program prog;
+ SoftMCRegAllocator reg_alloc = SoftMCRegAllocator(NUM_SOFTMC_REGS, reserved_regs);
+
+ init_program(prog);
+ // INIT DATA
+ init_rs(&prog, &reg_alloc, rs);
+
+ // HAMMER
+ if(hc_per_run > 0)
+ hammer_rs(&prog, &reg_alloc, rs, hc_per_run, num_runs);
+ if(remaining_hc > 0)
+ hammer_rs(&prog, &reg_alloc, rs, remaining_hc, 1);
+
+ // READ DATA
+ read_rs(&prog, &reg_alloc, rs);
+
+ // END PROGRAM
+ end_program(prog);
+
+ #ifdef PRINT_SOFTMC_PROGS
+ std::cout << "--- SoftMCProg ---" << std::endl;
+ prog.pretty_print(); // DEBUG
+ #endif
+
+ // EXECUTE PROGRAM
+ platform.execute(prog);
+
+ return get_bitflips(platform, rs);
+}
+
+RowSet get_rowset(string rh_pattern, uint bank, uint row){
+ RowSet rs;
+
+ rs.bank_id = bank;
+ for(int i = 0; i < rh_pattern.length(); i++){
+ if(rh_pattern.at(i) == 'A')
+ rs.aggr_ids.push_back(to_physical_row_id(row + i));
+ else if(rh_pattern.at(i) == 'V')
+ rs.victim_ids.push_back(to_physical_row_id(row + i));
+ }
+
+ return rs;
+}
+
+int main(int argc, char** argv){
+
+ //========================Program Options========================
+ string rh_pattern = "VAVAV";
+ uint target_bank = 1;
+ uint arg_log_phys_conv_scheme = 0;
+ uint data_pattern_select = 2;
+ uint cascade_amount = 1;
+ uint hc = 1000;
+ string out_filename = "";
+
+ if (argc != 5) {
+ cerr << RED_TXT << "Usage: " << argv[0] << " <hc_per_aggr> <cascade_amount> <data_pattern_select> <out_filename>" << NORMAL_TXT << endl;
+ return -1;
+ }
+
+ hc = atoi(argv[1]);
+ cascade_amount = atoi(argv[2]);
+ data_pattern_select = atoi(argv[3]);
+ out_filename = argv[4];
+
+ //========================Input Checking========================
+ if(!(data_pattern_select >= 0 && data_pattern_select < 8)){
+ cerr << RED_TXT << "--data_pattern should be between 0 and 8." << NORMAL_TXT << endl;
+ return -1;
+ }
+ //========================Platform Config========================
+ SoftMCPlatform platform;
+ int err;
+ if((err = platform.init()) != SOFTMC_SUCCESS){
+ cerr << "Could not initialize SoftMC Platform: " << err << endl;
+ return err;
+ }
+ platform.reset_fpga();
+ platform.set_aref(false); // disable refresh
+ //========================Out_file Config========================
+ std::ofstream out_file;
+ if(out_filename != ""){
+ out_file.open(out_filename);
+ }else{
+ out_file.open("/dev/null");
+ }
+ //========================Parse Inputs========================
+ // Logical to physical conversion
+ logical_physical_conversion_scheme = (LogPhysRowIDScheme) arg_log_phys_conv_scheme;
+ // Input Row Data
+ const uint vic_patterns[] = {0x00000000, 0xFFFFFFFF, 0x55555555, 0xAAAAAAAA, 0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF};
+ const uint aggr_patterns[] = {0xFFFFFFFF, 0x00000000, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x00000000, 0xFFFFFFFF};
+ for(int i = 0; i < 16; i++){
+ vic_data_pattern <<=32;
+ vic_data_pattern |= vic_patterns[data_pattern_select];
+ aggr_data_pattern <<=32;
+ aggr_data_pattern |= aggr_patterns[data_pattern_select];
+ }
+ //========================Parameter Calculations========================
+ uint total_victims = count(rh_pattern.begin(), rh_pattern.end(), 'V');
+ uint total_aggrs = count(rh_pattern.begin(), rh_pattern.end(), 'A');
+
+ uint hc_per_run = (cascade_amount != -1)? cascade_amount: hc;
+ uint num_runs = (uint) floor(hc/hc_per_run);
+ uint remaining_hc = hc - hc_per_run*num_runs;
+ //========================Information========================
+ out_file << "RH_pattern: " << rh_pattern << endl
+ << "HC_per_run: " << hc_per_run << endl
+ << "Num_runs: " << num_runs << endl
+ << "Remaining hc: " << remaining_hc << endl
+ << "Total_hc: " << hc << endl
+ << "Results" << endl
+ << "====================" << endl;
+ //========================Run Analyzer========================
+
+
+ vector<uint> total_bitflips(total_victims, 0);
+
+
+ for(uint r = 0; r < NUM_ROWS; r++){
+
+ RowSet rs = get_rowset(rh_pattern, target_bank, r);
+
+ auto num_bitflips = run_single_test(platform, rs, hc_per_run, num_runs, remaining_hc);
+
+ if(accumulate(num_bitflips.begin(), num_bitflips.end(), 0) > 0){
+ out_file << "Row " << r << ": ";
+
+ uint bitflips_ind = 0;
+
+ for(int i = 0; i < rh_pattern.length(); i++){
+ if(rh_pattern.at(i) == 'V'){
+ out_file << num_bitflips[bitflips_ind] << "-";
+ total_bitflips[bitflips_ind] += num_bitflips[bitflips_ind];
+ bitflips_ind++;
+ }else if(rh_pattern.at(i) == 'A'){
+ out_file << "A-";
+ }else{
+ out_file << "_-";
+ }
+ }
+ out_file << endl;
+ }
+
+ }
+
+ out_file << "Total bitflips: ";
+ uint bitflips_ind = 0;
+ for(int i = 0; i < rh_pattern.length(); i++){
+ if(rh_pattern.at(i) == 'V'){
+ out_file << total_bitflips[bitflips_ind++] << "-";
+ }else if(rh_pattern.at(i) == 'A'){
+ out_file << "A-";
+ }else{
+ out_file << "_-";
+ }
+ }
+ out_file << endl;
+
+ cout << "The test has finished!" << endl;
+
+ out_file.close();
+
+ return 0;
+} \ No newline at end of file
diff --git a/sources/apps/case_studies/cs1_interleaving_pattern/tools.h b/sources/apps/case_studies/cs1_interleaving_pattern/tools.h
new file mode 100644
index 0000000..2c00865
--- /dev/null
+++ b/sources/apps/case_studies/cs1_interleaving_pattern/tools.h
@@ -0,0 +1,213 @@
+#pragma once
+#define TOOLS_H
+
+#include "instruction.h"
+#include "prog.h"
+
+#include <cstdint>
+#include <vector>
+#include <exception>
+#include <cassert>
+#include <algorithm>
+#include <chrono>
+#include <iostream>
+
+Inst all_nops()
+{
+ return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+}
+
+void sleep_delay (Program& program, uint64_t sleep_time) {
+ while(sleep_time > UINT32_MAX){
+ program.add_inst(SMC_SLEEP(UINT32_MAX));
+ sleep_time -= UINT32_MAX;
+ }
+ switch(sleep_time){
+ case 0:
+ break;
+ case 1:
+ program.add_inst(all_nops());
+ break;
+ case 2:
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+ break;
+ default:
+ program.add_inst(SMC_SLEEP(sleep_time));
+ break;
+ }
+}
+
+int add_op_with_delay (Program& prog, Mininst ins, int before_cycles, int after_cycles) {
+
+ int remaining = before_cycles < 0 ? 0 : before_cycles;
+
+ while(remaining >= 4) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ switch(remaining) {
+ case 0:
+ prog.add_inst(__pack_mininsts(ins, SMC_NOP(), SMC_NOP(), SMC_NOP()));
+ remaining = after_cycles - 3;
+ break;
+ case 1:
+ prog.add_inst(__pack_mininsts(SMC_NOP(), ins, SMC_NOP(), SMC_NOP()));
+ remaining = after_cycles - 2;
+ break;
+ case 2:
+ prog.add_inst(__pack_mininsts(SMC_NOP(), SMC_NOP(), ins, SMC_NOP()));
+ remaining = after_cycles - 1;
+ break;
+ case 3:
+ prog.add_inst(__pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), ins));
+ remaining = after_cycles;
+ break;
+
+ default:
+ assert(false && "This line should not be reached. Possible bug in the program.");
+ }
+
+ while (remaining >= 4) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ return remaining;
+}
+
+int add_op_with_delay (Program& prog, Inst ins, int before_cycles, int after_cycles) {
+
+ int remaining = before_cycles;
+
+ while(remaining > 0) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ prog.add_inst(ins);
+ remaining = after_cycles;
+
+ while (remaining >= 4) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ return remaining;
+}
+
+
+
+typedef uint32_t SMC_REG;
+
+struct OutOfSoftMCRegsException : public std::exception {
+ const char * what () const throw () {
+ return "No more SoftMC registers to allocate.";
+ }
+};
+
+static uint32_t label_counter = 0;
+std::string createSMCLabel(const std::string& name) {
+ return name + std::to_string(label_counter++);
+}
+
+class SoftMCRegAllocator {
+
+ public:
+ SoftMCRegAllocator(uint32_t num_regs, const std::vector<uint32_t>& reserved_regs) {
+ free_regs.reserve(num_regs);
+
+ for(uint32_t i = 0; i < num_regs; i++) {
+ if(std::find(reserved_regs.begin(), reserved_regs.end(), i) == reserved_regs.end())
+ free_regs.emplace_back(i);
+ }
+ }
+
+ SMC_REG allocate_SMC_REG() {
+ if(free_regs.size() == 0)
+ throw OutOfSoftMCRegsException();
+
+ SMC_REG ret_reg = *(free_regs.begin());
+ free_regs.erase(free_regs.begin());
+ return ret_reg;
+ }
+
+ void free_SMC_REG(const SMC_REG r) {
+ // make sure r is not in the free list
+ auto it = std::find(free_regs.begin(), free_regs.end(), r);
+ assert(it == free_regs.end());
+
+ free_regs.push_back(r);
+ }
+
+ uint num_free_regs() const {
+ return free_regs.size();
+ }
+
+ private:
+ std::vector<uint32_t> free_regs;
+};
+
+
+typedef uint PhysicalRowID;
+typedef uint LogicalRowID;
+
+typedef enum LogPhysRowIDScheme {
+ SEQUENTIAL,
+ SAMSUNG,
+ MAX
+} LogPhysRowIDScheme;
+
+LogPhysRowIDScheme logical_physical_conversion_scheme = LogPhysRowIDScheme::SEQUENTIAL;
+
+PhysicalRowID to_physical_row_id(uint logical_row_id) {
+
+ switch(logical_physical_conversion_scheme) {
+ case LogPhysRowIDScheme::SEQUENTIAL: {
+ return logical_row_id;
+ break;
+ }
+ case LogPhysRowIDScheme::SAMSUNG: {
+ if(logical_row_id & 0x8) {
+ PhysicalRowID phys_row_id = logical_row_id & 0xFFFFFFF9;
+ phys_row_id |= (~logical_row_id & 0x00000006); // set bit pos 3 and 2
+
+ return phys_row_id;
+ } else {
+ return logical_row_id;
+ }
+ break;
+ }
+ default: {
+ std::cout << "ERROR: unimplemented logical to physical row id conversion scheme!" << std::endl;
+ exit(1);
+ }
+ }
+}
+
+LogicalRowID to_logical_row_id(uint physical_row_id) {
+ switch(logical_physical_conversion_scheme) {
+ case LogPhysRowIDScheme::SEQUENTIAL: {
+ return physical_row_id;
+ break;
+ }
+ case LogPhysRowIDScheme::SAMSUNG: {
+ if(physical_row_id & 0x8) {
+ PhysicalRowID log_row_id = physical_row_id & 0xFFFFFFF9;
+ log_row_id |= (~physical_row_id & 0x00000006); // set bit pos 3 and 2
+
+ return log_row_id;
+ } else {
+ return physical_row_id;
+ }
+ break;
+ }
+ default: {
+ std::cout << "ERROR: unimplemented physical to logical row id conversion scheme!" << std::endl;
+ exit(1);
+ }
+ }
+
+ return 0;
+}
diff --git a/sources/apps/case_studies/cs2_data_patterns/Makefile b/sources/apps/case_studies/cs2_data_patterns/Makefile
new file mode 100644
index 0000000..953fe34
--- /dev/null
+++ b/sources/apps/case_studies/cs2_data_patterns/Makefile
@@ -0,0 +1,33 @@
+program_NAME := TEST
+program_CXX_SRCS := test.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/case_studies/cs2_data_patterns/README.md b/sources/apps/case_studies/cs2_data_patterns/README.md
new file mode 100644
index 0000000..e4a94b3
--- /dev/null
+++ b/sources/apps/case_studies/cs2_data_patterns/README.md
@@ -0,0 +1,11 @@
+## Case Study #2: RowHammer: Data Patterns
+
+### Instructions
+
+1. run `make` to compile the DRAM Bender program
+2. execute `./TEST <hc_per_aggr> <target_row> <aggr_pattern_select> <vic_pattern_select> <out_filename>` to run the experiment
+ - hc_per_aggr: Total number of activation per aggressor row.
+ - target_row: The target row for RH attack.
+ - aggr_pattern_select: SoftMC for 0x00 to 0xFF patterns, DRAM-Bender for 256 random patterns.
+ - vic_pattern_select: 0 for all-zeros, 1 for all-ones.
+ - out_filename: output filename for the results. The output file has the bitflip locations for each victim row and aggr pattern.
diff --git a/sources/apps/case_studies/cs2_data_patterns/test.cpp b/sources/apps/case_studies/cs2_data_patterns/test.cpp
new file mode 100644
index 0000000..a1a19a0
--- /dev/null
+++ b/sources/apps/case_studies/cs2_data_patterns/test.cpp
@@ -0,0 +1,561 @@
+#include "instruction.h"
+#include "prog.h"
+#include "platform.h"
+#include "tools.h"
+
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <cassert>
+#include <bitset>
+#include <chrono>
+#include <iomanip>
+#include <math.h>
+
+#include <array>
+#include <algorithm>
+#include <numeric>
+#include <ctime>
+
+// #define PRINT_SOFTMC_PROGS
+
+using namespace std;
+
+#define CASR 0
+#define BASR 1
+#define RASR 2
+
+#define NUM_SOFTMC_REGS 16
+#define FPGA_PERIOD 1.5015f // ns
+
+#define RED_TXT "\033[31m"
+#define GREEN_TXT "\033[32m"
+#define YELLOW_TXT "\033[33m"
+#define BLUE_TXT "\033[34m"
+#define MAGENTA_TXT "\033[35m"
+#define NORMAL_TXT "\033[0m"
+
+int NUM_BANKS = 16; // this is the total number of banks in the chip
+int NUM_BANK_GROUPS = 4;
+int NUM_ROWS = 32768;
+int ROW_SIZE = 8192;
+int NUM_COLS_PER_ROW = 128;
+int CHIP_NUM = 4;
+int CACHE_LINE_BITS = 512;
+
+float DEFAULT_TRCD = 13.5f; // ns
+float DEFAULT_TRAS = 35.0f; // ns
+float DEFAULT_TRP = 13.5f; // ns
+float DEFAULT_TWR = 15.0f; // ns
+float DEFAULT_TRFC = 260.0f; // ns
+float DEFAULT_TRRDS = 5.3f; // ns (ACT-ACT to different bank groups)
+float DEFAULT_TRRDL = 6.4f; // ns (ACT-ACT to same bank group)
+float DEFAULT_TREFI = 7800.0f;
+
+int trcd_cycles = (int) ceil(DEFAULT_TRCD/FPGA_PERIOD);
+int tras_cycles = (int) ceil(DEFAULT_TRAS/FPGA_PERIOD);
+int trp_cycles = (int) ceil(DEFAULT_TRP/FPGA_PERIOD);
+int twr_cycles = (int) ceil(DEFAULT_TWR/FPGA_PERIOD);
+int trfc_cycles = (int) ceil(DEFAULT_TRFC/FPGA_PERIOD);
+int trrds_cycles = (int) ceil(DEFAULT_TRRDS/FPGA_PERIOD);
+int trrdl_cycles = (int) ceil(DEFAULT_TRRDL/FPGA_PERIOD);
+int trefi_cycles = (int) ceil(DEFAULT_TREFI/FPGA_PERIOD);
+
+vector<uint32_t> reserved_regs{CASR, BASR, RASR};
+vector<uint> special_pattern;
+
+typedef struct RowSet {
+ vector<uint> victim_ids;
+ vector<uint> aggr_ids;
+ vector<uint> isol_ids;
+ uint bank_id;
+} RowSet;
+
+void init_program(Program& prog){
+ add_op_with_delay(prog, SMC_PRE(0, 0, 1), 0, trp_cycles); // precharge all banks
+}
+
+void end_program(Program& prog){
+ prog.add_inst(all_nops());
+ prog.add_inst(SMC_END());
+}
+
+void init_row(Program* prog, SoftMCRegAllocator* reg_alloc, const uint target_bank, const uint target_row,
+ const bitset<512> pattern){
+
+ SMC_REG reg_row_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_col_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_bank_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_cols = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_wrdata = reg_alloc->allocate_SMC_REG();
+
+ bitset<512> bitset_int_mask(0xFFFFFFFF);
+
+ prog->add_inst(SMC_LI(NUM_COLS_PER_ROW*8, reg_num_cols));
+ prog->add_inst(SMC_LI(target_bank, reg_bank_addr));
+ prog->add_inst(SMC_LI(target_row, reg_row_addr));
+ prog->add_inst(SMC_LI(8, CASR));
+
+ // set up the input data in the wide register
+ for(int pos = 0; pos < 16; pos++){
+ prog->add_inst(SMC_LI((((pattern >> 32*pos) & bitset_int_mask).to_ulong() & 0xFFFFFFFF), reg_wrdata));
+ prog->add_inst(SMC_LDWD(reg_wrdata, pos));
+ }
+
+ // activate the target row
+ uint remaining = add_op_with_delay(*prog, SMC_ACT(reg_bank_addr, 0, reg_row_addr, 0), 0, trcd_cycles - 5);
+
+ // write data to the row and precharge
+ prog->add_inst(SMC_LI(0, reg_col_addr));
+
+ string new_lbl = createSMCLabel("INIT_ROW");
+ prog->add_label(new_lbl);
+ add_op_with_delay(*prog, SMC_WRITE(reg_bank_addr, 0, reg_col_addr, 1, 0, 0), 0, 0);
+ prog->add_branch(Program::BR_TYPE::BL, reg_col_addr, reg_num_cols, new_lbl);
+
+ // precharge the open bank
+ add_op_with_delay(*prog, SMC_PRE(reg_bank_addr, 0, 0), 0, trp_cycles);
+
+ reg_alloc->free_SMC_REG(reg_row_addr);
+ reg_alloc->free_SMC_REG(reg_col_addr);
+ reg_alloc->free_SMC_REG(reg_wrdata);
+ reg_alloc->free_SMC_REG(reg_bank_addr);
+ reg_alloc->free_SMC_REG(reg_num_cols);
+
+}
+
+void init_rs(Program* prog, SoftMCRegAllocator* reg_alloc, const RowSet rs,
+ const bitset<512> vic_pattern, const bitset<512> aggr_pattern) {
+ //init aggrs
+ for(auto aggr_id: rs.aggr_ids)
+ init_row(prog, reg_alloc, rs.bank_id, aggr_id, aggr_pattern);
+ //init victims
+ for(auto victim_id: rs.victim_ids)
+ init_row(prog, reg_alloc, rs.bank_id, victim_id, vic_pattern);
+}
+
+void hammer_rs(Program* prog, SoftMCRegAllocator* reg_alloc, const RowSet rs,
+ const uint hc){
+
+ SMC_REG reg_bank_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_row_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_hammers = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_cur_hammers = reg_alloc->allocate_SMC_REG();
+
+ prog->add_inst(SMC_LI(rs.bank_id, reg_bank_addr));
+ prog->add_inst(SMC_LI(hc, reg_num_hammers));
+ prog->add_inst(SMC_LI(0, reg_cur_hammers));
+
+ string lbl_rh = createSMCLabel("ROWHAMMERING");
+ prog->add_label(lbl_rh);
+ for(auto aggr_id: rs.aggr_ids){
+ prog->add_inst(SMC_LI(aggr_id, reg_row_addr));
+
+ uint remaining_cycs = add_op_with_delay(*prog, SMC_ACT(reg_bank_addr, 0, reg_row_addr, 0), 0, tras_cycles - 1);
+ remaining_cycs = add_op_with_delay(*prog, SMC_PRE(reg_bank_addr, 0, 0), remaining_cycs, trp_cycles - 25);
+ }
+ prog->add_inst(SMC_ADDI(reg_cur_hammers, 1, reg_cur_hammers));
+ prog->add_branch(Program::BR_TYPE::BL, reg_cur_hammers, reg_num_hammers, lbl_rh);
+
+ reg_alloc->free_SMC_REG(reg_bank_addr);
+ reg_alloc->free_SMC_REG(reg_row_addr);
+ reg_alloc->free_SMC_REG(reg_num_hammers);
+ reg_alloc->free_SMC_REG(reg_cur_hammers);
+}
+
+void read_row(Program* prog, SoftMCRegAllocator* reg_alloc, const uint bank_id, const uint row_id){
+
+ SMC_REG reg_bank_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_num_cols = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_row_addr = reg_alloc->allocate_SMC_REG();
+ SMC_REG reg_col_addr = reg_alloc->allocate_SMC_REG();
+
+ prog->add_inst(SMC_LI(8, CASR));
+ prog->add_inst(SMC_LI(NUM_COLS_PER_ROW*8, reg_num_cols));
+ prog->add_inst(SMC_LI(bank_id, reg_bank_addr));
+ prog->add_inst(SMC_LI(row_id, reg_row_addr));
+
+ // activate the victim row
+ add_op_with_delay(*prog, SMC_ACT(reg_bank_addr, 0, reg_row_addr, 0), 0, trcd_cycles - 5);
+ prog->add_inst(SMC_LI(0, reg_col_addr));
+
+ // read data from the row and precharge
+ string new_lbl = createSMCLabel("READ_ROW");
+ prog->add_label(new_lbl);
+ add_op_with_delay(*prog, SMC_READ(reg_bank_addr, 0, reg_col_addr, 1, 0, 0), 0, 0);
+ prog->add_branch(Program::BR_TYPE::BL, reg_col_addr, reg_num_cols, new_lbl);
+
+ // precharge the open bank
+ add_op_with_delay(*prog, SMC_PRE(reg_bank_addr, 0, 0), 0, trp_cycles);
+
+ reg_alloc->free_SMC_REG(reg_bank_addr);
+ reg_alloc->free_SMC_REG(reg_num_cols);
+ reg_alloc->free_SMC_REG(reg_row_addr);
+ reg_alloc->free_SMC_REG(reg_col_addr);
+
+}
+
+void read_rs(Program* prog, SoftMCRegAllocator* reg_alloc, const RowSet rs){
+ for(auto victim_id: rs.victim_ids)
+ read_row(prog, reg_alloc, rs.bank_id, victim_id);
+}
+
+vector<uint> collect_bitflips(const char* read_data,
+ const bitset<512> vic_pattern){
+
+ bitset<512> read_data_bitset;
+ vector<uint> bitflips;
+ uint32_t* iread_data = (uint32_t*) read_data;
+ uint bit_loc;
+
+ // check for bitflips in each cache line
+ for(int cl = 0; cl < ROW_SIZE/64; cl++) {
+ read_data_bitset.reset();
+ for(int i = 0; i < 512/32; i++) {
+ bitset<512> tmp_bitset = iread_data[cl*(512/32) + i];
+
+ read_data_bitset |= (tmp_bitset << i*32);
+ }
+ // compare and print errors
+ bitset<512> error_mask = read_data_bitset ^ vic_pattern;
+ if(error_mask.any()){
+ // there is at least one bitflip in this cache line
+ for(uint i = 0; i < error_mask.size(); i++){
+ if(error_mask.test(i)){
+ bit_loc = cl*CACHE_LINE_BITS + i;
+ bitflips.push_back(bit_loc);
+ }
+ }
+ }
+ }
+
+ return bitflips;
+}
+
+vector<vector<uint>> get_bitflips(SoftMCPlatform& platform, const RowSet& rs,
+ const bitset<512> vic_pattern){
+
+ vector<vector<uint>> loc_bitflips;
+ uint read_data_size = ROW_SIZE*rs.victim_ids.size();
+
+ char buf[read_data_size*2];
+
+ platform.receiveData(buf, read_data_size);
+ for(uint vic_ind = 0; vic_ind < rs.victim_ids.size(); vic_ind++){
+ auto bitflips = collect_bitflips(buf + vic_ind*ROW_SIZE, vic_pattern);
+ loc_bitflips.push_back(bitflips);
+ }
+ return loc_bitflips;
+}
+
+vector<vector<uint>> run_single_test(SoftMCPlatform& platform, const RowSet rs, const uint hc,
+ const bitset<512> vic_pattern, const bitset<512> aggr_pattern){
+
+ Program prog;
+ SoftMCRegAllocator reg_alloc = SoftMCRegAllocator(NUM_SOFTMC_REGS, reserved_regs);
+
+ init_program(prog);
+ // INIT DATA
+ init_rs(&prog, &reg_alloc, rs, vic_pattern, aggr_pattern);
+
+ // HAMMER
+ hammer_rs(&prog, &reg_alloc, rs, hc);
+
+ // READ DATA
+ read_rs(&prog, &reg_alloc, rs);
+
+ // END PROGRAM
+ end_program(prog);
+
+ #ifdef PRINT_SOFTMC_PROGS
+ std::cout << "--- SoftMCProg ---" << std::endl;
+ prog.pretty_print(); // DEBUG
+ #endif
+
+ // EXECUTE PROGRAM
+ platform.execute(prog);
+
+ return get_bitflips(platform, rs, vic_pattern);
+}
+
+RowSet get_rowset(string rh_pattern, uint bank, uint row){
+ RowSet rs;
+
+ rs.bank_id = bank;
+ for(int i = 0; i < rh_pattern.length(); i++){
+ if(rh_pattern.at(i) == 'A')
+ rs.aggr_ids.push_back(to_physical_row_id(row + i));
+ else if(rh_pattern.at(i) == 'V')
+ rs.victim_ids.push_back(to_physical_row_id(row + i));
+ else if(rh_pattern.at(i) == 'I')
+ rs.isol_ids.push_back(to_physical_row_id(row + i));
+ }
+
+ return rs;
+}
+
+vector<vector<bitset<512>>> parse_data_patterns(const uint aggr_pattern_select, const uint vic_pattern_select, const uint isol_pattern_select,
+ const vector<uint> spec_data_patterns){
+
+ vector<bitset<512>> aggr_patterns, vic_patterns, isol_patterns;
+ bitset<512> aggr_set;
+ aggr_set.reset();
+ switch (aggr_pattern_select){
+ case 0:
+ aggr_patterns.push_back(aggr_set);
+ break;
+ case 1:
+ aggr_set.set();
+ aggr_patterns.push_back(aggr_set);
+ break;
+ case 2:
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= 0x55;
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ break;
+ case 3:
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= 0xAA;
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ break;
+ case 8:
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= 0x0F;
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ break;
+ case 9:
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= 0xF0;
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ break;
+ case 4:
+ for(uint p = 0; p < 256; p++){
+ aggr_set.reset();
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= p;
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ }
+ break;
+ case 6:
+ for(auto p: spec_data_patterns){
+ aggr_set.reset();
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= p;
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ }
+ break;
+ case 7:
+ for(uint b = 0; b < 64; b++){
+ aggr_set |= spec_data_patterns[b];
+ aggr_set <<= 8;
+ }
+ aggr_patterns.push_back(aggr_set);
+ break;
+ }
+
+ bitset<512> vic_set;
+ vic_set.reset();
+ switch (vic_pattern_select){
+ case 0:
+ vic_patterns.push_back(vic_set);
+ break;
+ case 1:
+ vic_set.set();
+ vic_patterns.push_back(vic_set);
+ break;
+ case 2:
+ for(uint b = 0; b < 64; b++){
+ vic_set |= 0x55;
+ vic_set <<= 8;
+ }
+ vic_patterns.push_back(vic_set);
+ break;
+ case 3:
+ for(uint b = 0; b < 64; b++){
+ vic_set |= 0xAA;
+ vic_set <<= 8;
+ }
+ vic_patterns.push_back(vic_set);
+ break;
+ case 8:
+ for(uint b = 0; b < 64; b++){
+ vic_set |= 0x0F;
+ vic_set <<= 8;
+ }
+ vic_patterns.push_back(vic_set);
+ break;
+ case 9:
+ for(uint b = 0; b < 64; b++){
+ vic_set |= 0xF0;
+ vic_set <<= 8;
+ }
+ vic_patterns.push_back(vic_set);
+ break;
+ case 5:
+ vic_patterns.push_back(vic_set);
+ break;
+ }
+
+ bitset<512> isol_set;
+ isol_set.reset();
+ switch (isol_pattern_select){
+ case 0:
+ isol_patterns.push_back(isol_set);
+ break;
+ case 1:
+ isol_set.set();
+ isol_patterns.push_back(isol_set);
+ break;
+ case 2:
+ for(uint b = 0; b < 64; b++){
+ isol_set |= 0x55;
+ isol_set <<= 8;
+ }
+ isol_patterns.push_back(isol_set);
+ break;
+ case 3:
+ for(uint b = 0; b < 64; b++){
+ isol_set |= 0xAA;
+ isol_set <<= 8;
+ }
+ isol_patterns.push_back(isol_set);
+ break;
+ case 8:
+ for(uint b = 0; b < 64; b++){
+ isol_set |= 0x0F;
+ isol_set <<= 8;
+ }
+ isol_patterns.push_back(isol_set);
+ break;
+ case 9:
+ for(uint b = 0; b < 64; b++){
+ isol_set |= 0xF0;
+ isol_set <<= 8;
+ }
+ isol_patterns.push_back(isol_set);
+ break;
+ }
+
+ vector<vector<bitset<512>>> patterns;
+ patterns.push_back(aggr_patterns);
+ patterns.push_back(vic_patterns);
+ patterns.push_back(isol_patterns);
+
+ return patterns;
+}
+
+int main(int argc, char** argv){
+
+ //========================Program Options========================
+ string out_filename = "";
+ string rh_pattern = "AVA";
+ uint target_bank = 0;
+ uint target_row = 0;
+ string aggr_pattern_select = "SoftMC";
+ uint vic_pattern_select = 0;
+ uint arg_log_phys_conv_scheme = 0;
+ uint hc = 1000;
+
+ if(argc != 6){
+ cerr << RED_TXT << "Usage: " << argv[0] << " <hc_per_aggr> <target_row> <aggr_pattern_select> <vic_pattern_select> <out_filename>" << NORMAL_TXT << endl;
+ return -1;
+ }
+
+ hc = atoi(argv[1]);
+ target_row = atoi(argv[2]);
+ aggr_pattern_select = argv[3];
+ vic_pattern_select = atoi(argv[4]);
+ out_filename = argv[5];
+
+ //========================Input Checking========================
+ if(arg_log_phys_conv_scheme >= LogPhysRowIDScheme::MAX){
+ cerr << RED_TXT << "No logical to physical conversion scheme found." << NORMAL_TXT << endl;
+ return -1;
+ }
+ //========================Platform Config========================
+ SoftMCPlatform platform;
+ int err;
+ if((err = platform.init()) != SOFTMC_SUCCESS){
+ cerr << "Could not initialize SoftMC Platform: " << err << endl;
+ return err;
+ }
+ platform.reset_fpga();
+ platform.set_aref(false); // disable refresh
+ //========================Out_file Config========================
+ std::ofstream out_file;
+ if(out_filename != ""){
+ out_file.open(out_filename);
+ }else{
+ out_file.open("/dev/null");
+ }
+ //========================Parse Inputs========================
+ // Logical to physical conversion
+ logical_physical_conversion_scheme = (LogPhysRowIDScheme) arg_log_phys_conv_scheme;
+ //========================Parameter Calculations========================
+ uint total_victims = count(rh_pattern.begin(), rh_pattern.end(), 'V');
+ uint total_aggrs = count(rh_pattern.begin(), rh_pattern.end(), 'A');
+ //========================INFO MSG========================
+ std::cout << "RH_pattern: " << rh_pattern << endl
+ << "Hammer Count: " << hc << endl
+ << "Target Bank: " << target_bank << endl
+ << "Target Row: " << target_row << endl
+ << "Aggressor Data Pattern: " << aggr_pattern_select << endl
+ << "Victim Data Pattern: " << vic_pattern_select << endl;
+ //========================Run Analyzer========================
+
+ RowSet rs = get_rowset(rh_pattern, target_bank, target_row);
+ bitset<512> aggr_pattern, vic_pattern;
+ for(uint pattern_id = 0; pattern_id < 256; pattern_id++){
+
+ string ap_str;
+ if(aggr_pattern_select == "SoftMC"){
+ bitset<8> ap_set(pattern_id);
+ ap_str = ap_set.to_string();
+ }else if(aggr_pattern_select == "DRAM-Bender"){
+ bitset<512> ap_set;
+ for(uint b = 0; b < 512; b++){
+ ap_set[b] = rand() % 2;
+ }
+ ap_str = "RAND_" + to_string(pattern_id);
+ }
+
+ if(vic_pattern_select == 0){
+ vic_pattern.reset();
+ } else if(vic_pattern_select == 1){
+ vic_pattern.set();
+ }
+
+ auto loc_bitflips = run_single_test(platform, rs, hc, vic_pattern, aggr_pattern);
+
+ uint vic_ind = 0;
+
+ for(auto victim_id: rs.victim_ids){
+ out_file << "Victim " << to_logical_row_id(victim_id) << " - Aggr Pat "
+ << ap_str << ": " << loc_bitflips[vic_ind].size() << " : ";
+ for(auto bit_loc: loc_bitflips[vic_ind]){
+ out_file << bit_loc << ",";
+ }
+ vic_ind++;
+ }
+ out_file << endl;
+
+ }
+
+ std::cout << "The test has finished!" << endl;
+
+ out_file.close();
+ return 0;
+} \ No newline at end of file
diff --git a/sources/apps/case_studies/cs2_data_patterns/tools.h b/sources/apps/case_studies/cs2_data_patterns/tools.h
new file mode 100644
index 0000000..2c00865
--- /dev/null
+++ b/sources/apps/case_studies/cs2_data_patterns/tools.h
@@ -0,0 +1,213 @@
+#pragma once
+#define TOOLS_H
+
+#include "instruction.h"
+#include "prog.h"
+
+#include <cstdint>
+#include <vector>
+#include <exception>
+#include <cassert>
+#include <algorithm>
+#include <chrono>
+#include <iostream>
+
+Inst all_nops()
+{
+ return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+}
+
+void sleep_delay (Program& program, uint64_t sleep_time) {
+ while(sleep_time > UINT32_MAX){
+ program.add_inst(SMC_SLEEP(UINT32_MAX));
+ sleep_time -= UINT32_MAX;
+ }
+ switch(sleep_time){
+ case 0:
+ break;
+ case 1:
+ program.add_inst(all_nops());
+ break;
+ case 2:
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+ break;
+ default:
+ program.add_inst(SMC_SLEEP(sleep_time));
+ break;
+ }
+}
+
+int add_op_with_delay (Program& prog, Mininst ins, int before_cycles, int after_cycles) {
+
+ int remaining = before_cycles < 0 ? 0 : before_cycles;
+
+ while(remaining >= 4) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ switch(remaining) {
+ case 0:
+ prog.add_inst(__pack_mininsts(ins, SMC_NOP(), SMC_NOP(), SMC_NOP()));
+ remaining = after_cycles - 3;
+ break;
+ case 1:
+ prog.add_inst(__pack_mininsts(SMC_NOP(), ins, SMC_NOP(), SMC_NOP()));
+ remaining = after_cycles - 2;
+ break;
+ case 2:
+ prog.add_inst(__pack_mininsts(SMC_NOP(), SMC_NOP(), ins, SMC_NOP()));
+ remaining = after_cycles - 1;
+ break;
+ case 3:
+ prog.add_inst(__pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), ins));
+ remaining = after_cycles;
+ break;
+
+ default:
+ assert(false && "This line should not be reached. Possible bug in the program.");
+ }
+
+ while (remaining >= 4) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ return remaining;
+}
+
+int add_op_with_delay (Program& prog, Inst ins, int before_cycles, int after_cycles) {
+
+ int remaining = before_cycles;
+
+ while(remaining > 0) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ prog.add_inst(ins);
+ remaining = after_cycles;
+
+ while (remaining >= 4) {
+ prog.add_inst(all_nops());
+ remaining -= 4;
+ }
+
+ return remaining;
+}
+
+
+
+typedef uint32_t SMC_REG;
+
+struct OutOfSoftMCRegsException : public std::exception {
+ const char * what () const throw () {
+ return "No more SoftMC registers to allocate.";
+ }
+};
+
+static uint32_t label_counter = 0;
+std::string createSMCLabel(const std::string& name) {
+ return name + std::to_string(label_counter++);
+}
+
+class SoftMCRegAllocator {
+
+ public:
+ SoftMCRegAllocator(uint32_t num_regs, const std::vector<uint32_t>& reserved_regs) {
+ free_regs.reserve(num_regs);
+
+ for(uint32_t i = 0; i < num_regs; i++) {
+ if(std::find(reserved_regs.begin(), reserved_regs.end(), i) == reserved_regs.end())
+ free_regs.emplace_back(i);
+ }
+ }
+
+ SMC_REG allocate_SMC_REG() {
+ if(free_regs.size() == 0)
+ throw OutOfSoftMCRegsException();
+
+ SMC_REG ret_reg = *(free_regs.begin());
+ free_regs.erase(free_regs.begin());
+ return ret_reg;
+ }
+
+ void free_SMC_REG(const SMC_REG r) {
+ // make sure r is not in the free list
+ auto it = std::find(free_regs.begin(), free_regs.end(), r);
+ assert(it == free_regs.end());
+
+ free_regs.push_back(r);
+ }
+
+ uint num_free_regs() const {
+ return free_regs.size();
+ }
+
+ private:
+ std::vector<uint32_t> free_regs;
+};
+
+
+typedef uint PhysicalRowID;
+typedef uint LogicalRowID;
+
+typedef enum LogPhysRowIDScheme {
+ SEQUENTIAL,
+ SAMSUNG,
+ MAX
+} LogPhysRowIDScheme;
+
+LogPhysRowIDScheme logical_physical_conversion_scheme = LogPhysRowIDScheme::SEQUENTIAL;
+
+PhysicalRowID to_physical_row_id(uint logical_row_id) {
+
+ switch(logical_physical_conversion_scheme) {
+ case LogPhysRowIDScheme::SEQUENTIAL: {
+ return logical_row_id;
+ break;
+ }
+ case LogPhysRowIDScheme::SAMSUNG: {
+ if(logical_row_id & 0x8) {
+ PhysicalRowID phys_row_id = logical_row_id & 0xFFFFFFF9;
+ phys_row_id |= (~logical_row_id & 0x00000006); // set bit pos 3 and 2
+
+ return phys_row_id;
+ } else {
+ return logical_row_id;
+ }
+ break;
+ }
+ default: {
+ std::cout << "ERROR: unimplemented logical to physical row id conversion scheme!" << std::endl;
+ exit(1);
+ }
+ }
+}
+
+LogicalRowID to_logical_row_id(uint physical_row_id) {
+ switch(logical_physical_conversion_scheme) {
+ case LogPhysRowIDScheme::SEQUENTIAL: {
+ return physical_row_id;
+ break;
+ }
+ case LogPhysRowIDScheme::SAMSUNG: {
+ if(physical_row_id & 0x8) {
+ PhysicalRowID log_row_id = physical_row_id & 0xFFFFFFF9;
+ log_row_id |= (~physical_row_id & 0x00000006); // set bit pos 3 and 2
+
+ return log_row_id;
+ } else {
+ return physical_row_id;
+ }
+ break;
+ }
+ default: {
+ std::cout << "ERROR: unimplemented physical to logical row id conversion scheme!" << std::endl;
+ exit(1);
+ }
+ }
+
+ return 0;
+}
diff --git a/sources/apps/case_studies/cs3_bitwise/Makefile b/sources/apps/case_studies/cs3_bitwise/Makefile
new file mode 100644
index 0000000..953fe34
--- /dev/null
+++ b/sources/apps/case_studies/cs3_bitwise/Makefile
@@ -0,0 +1,33 @@
+program_NAME := TEST
+program_CXX_SRCS := test.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/case_studies/cs3_bitwise/README.md b/sources/apps/case_studies/cs3_bitwise/README.md
new file mode 100644
index 0000000..1db9c54
--- /dev/null
+++ b/sources/apps/case_studies/cs3_bitwise/README.md
@@ -0,0 +1,23 @@
+## Case Study #3: In-DRAM Bitwise Operations
+
+### Instructions
+
+1. run `make` to compile the DRAM Bender program
+2. execute `run_tests.sh` to generate data under `results` directory
+
+### Data format
+
+`run_tests.sh` creates one result file for each iteration of an AND and an OR experiment. For example, `AND-log1.csv` contains the results for the first iteration of an AND experiment.
+
+A line in this file corresponds to a tested DRAM segment and contains the following comma separated information (taken from test.cpp, line 299):
+
+```
+row: The address of the first row in the tested segment
+op_type: "AND" or "OR"
+dp1: Value stored in the first operand
+dp2: Value stored in the second operand
+t1: Distance between the first ACT and the first PRE command
+t2: Distance between the first PRE and the second ACT command
+platext: Placement of the operands (see lines 244-264 in test.cpp)
+errors: Number of bit errors in the output
+``` \ No newline at end of file
diff --git a/sources/apps/case_studies/cs3_bitwise/run_tests.sh b/sources/apps/case_studies/cs3_bitwise/run_tests.sh
new file mode 100644
index 0000000..21c8fb5
--- /dev/null
+++ b/sources/apps/case_studies/cs3_bitwise/run_tests.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+mkdir -p results
+
+for i in {1..10}
+do
+ sudo ./TEST 1 "results/AND-log$i.csv" > /dev/null
+done
+
+for i in {1..10}
+do
+ sudo ./TEST 0 "results/OR-log$i.csv" > /dev/null
+done
diff --git a/sources/apps/case_studies/cs3_bitwise/test.cpp b/sources/apps/case_studies/cs3_bitwise/test.cpp
new file mode 100644
index 0000000..2b71f66
--- /dev/null
+++ b/sources/apps/case_studies/cs3_bitwise/test.cpp
@@ -0,0 +1,309 @@
+#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 <bitset>
+
+using namespace std;
+
+#define buffer_size 8192*8
+
+#define NUM_BANKS 1 //16
+#define NUM_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 CONSTANT 8
+#define OP1 12
+#define OP2 13
+
+#define BAR 3
+#define CAR 4
+#define RAR 5
+#define SRC 6
+#define DST 7
+
+#define INIT_LOOP 9
+
+#define TEMP1 10
+#define NUM_ROWS_REG 11
+
+
+/**
+ * @return an instruction formed by NOPs
+ */
+Inst all_nops()
+{
+ return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+}
+
+SoftMCPlatform platform;
+
+/**
+ * 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)
+{
+ 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, no_rows>1), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ ret.add_inst(SMC_SLEEP(4));
+ for(int i = 0 ; i < 128 ; 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_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;
+}
+
+Program writeRowSlow(unsigned int _BAR, unsigned int _RAR, unsigned int _CAR, unsigned int _PATTERN_REG, unsigned int _TEMP1, string label)
+{
+ Program prog;
+
+ for (int i = 0 ; i < 16 ; i++)
+ prog.add_inst(SMC_LDWD(_PATTERN_REG, i));
+
+ prog.add_inst(SMC_LI(1024, TEMP1));
+
+ prog.add_inst(SMC_LI(0, _CAR));
+ prog.add_inst(SMC_ACT(_BAR, 0, _RAR, 0), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_label("WRS:BEGIN" + label);
+ prog.add_inst(SMC_WRITE(_BAR, 0, _CAR, 1, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_branch(prog.BR_TYPE::BL, _CAR, TEMP1, "WRS:BEGIN" + label);
+ prog.add_inst(SMC_PRE(_BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_SLEEP(3));
+
+ return prog;
+}
+
+Program AMBITTest(bool andOp, unsigned int op1, unsigned int op2, unsigned int t1, unsigned int t2, int op1Placement, int op2Placement, int constantPlacement)
+{
+ Program prog;
+
+ prog.add_inst(SMC_LI(8, CASR));
+ prog.add_inst(SMC_LI(0, BASR));
+ prog.add_inst(SMC_LI(1, RASR));
+ prog.add_inst(SMC_LI(1, BAR));
+ prog.add_inst(SMC_LI(0, RAR));
+ prog.add_inst(SMC_LI(NUM_ROWS, NUM_ROWS_REG));
+ prog.add_label("SEGMENT_BEGIN");
+ for(int i = 0 ; i < 4 ; i++)
+ {
+ if(i == op1Placement)
+ {
+ prog.add_inst(SMC_LI(op1, OP1));
+ prog.add_below(writeRowSlow(BAR, RAR, CAR, OP1, TEMP1, "one"));
+ }
+ else if (i == op2Placement)
+ {
+ prog.add_inst(SMC_LI(op2, OP2));
+ prog.add_below(writeRowSlow(BAR, RAR, CAR, OP2, TEMP1, "two"));
+ }
+ else if (i == constantPlacement)
+ {
+ prog.add_inst(SMC_LI(andOp ? 0x00000000 : 0xffffffff, CONSTANT));
+ prog.add_below(writeRowSlow(BAR, RAR, CAR, CONSTANT, TEMP1, "three"));
+ }
+ else
+ {
+ prog.add_inst(SMC_LI(0x00000000, CONSTANT));
+ prog.add_below(writeRowSlow(BAR, RAR, CAR, CONSTANT, TEMP1, "four"));
+ }
+ prog.add_inst(SMC_ADDI(RAR, 1, RAR));
+ }
+
+ prog.add_inst(SMC_SUBI(RAR, 3, SRC));
+ prog.add_inst(SMC_SUBI(RAR, 2, DST));
+ prog.add_below(genActPreActSequence(t1, t2, SRC, DST, BAR));
+
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+ prog.add_inst(SMC_PRE(BAR, 0, 0), SMC_NOP(), SMC_NOP(), SMC_NOP());
+
+ //prog.dump_registers();
+
+ prog.add_below(genReadRange(SRC, 3, BAR));
+ prog.add_branch(prog.BR_TYPE::BL, RAR, NUM_ROWS_REG, "SEGMENT_BEGIN");
+ prog.add_inst(SMC_END());
+
+ return prog;
+}
+
+int main(int argc, char * argv[])
+{
+ if(platform.init() != SOFTMC_SUCCESS){
+ cerr << "Could not initialize SoftMC Platform" << endl;
+ }
+
+ platform.reset_fpga();
+
+ if (argc != 3)
+ {
+ cout << "Give me two arguments" << endl;
+ exit(0);
+ }
+ bool andOp = false;
+
+ if (atoi(argv[1]))
+ andOp = true;
+ else
+ andOp = false;
+
+ srand(time(NULL));
+
+ ofstream fileOutput;
+ fileOutput.open(argv[2]);
+ fileOutput << "row,operation,op1,op2,t1,t2,op1-placement,op2-placement,constant-placement,bit-flips" << endl;
+
+ for(int i_data = 0 ; i_data < 4 ; i_data++)
+ {
+ unsigned int dp1;
+ unsigned int dp2;
+
+ if (i_data == 0)
+ {
+ dp1 = 0x00000000;
+ dp2 = 0x00000000;
+ }
+ else if (i_data == 1)
+ {
+ dp1 = 0x00000000;
+ dp2 = 0xffffffff;
+ }
+ else if (i_data == 2)
+ {
+ dp1 = 0xffffffff;
+ dp2 = 0x00000000;
+ }
+ else if (i_data == 3)
+ {
+ dp1 = 0xffffffff;
+ dp2 = 0xffffffff;
+ }
+
+ unsigned int expected = andOp ? (dp1 & dp2) : (dp1 | dp2);
+
+ for (int t1 = 0 ; t1 < 10 ; t1++)
+ {
+ for (int t2 = 0 ; t2 < 10 ; t2++)
+ {
+ for (int pla = 0 ; pla < 3 ; pla++)
+ {
+ string platext;
+ if (pla == 0)
+ {
+ cout << "Begin with " << (andOp ? "AND" : "OR") << " T1:" << t1 << " T2:" << t2 << " OP1:" << 0 << " OP2:" << 1 << " C:" << 2 << endl;
+ Program prog = AMBITTest(andOp, dp1, dp2, t1, t2, 0, 1, 2);
+ platext = "0,1,2";
+ platform.execute(prog);
+ }
+ else if (pla == 1)
+ {
+ cout << "Begin with T1:" << t1 << " T2:" << t2 << " OP1:" << 0 << " OP2:" << 2 << " C:" << 1 << endl;
+ Program prog = AMBITTest(andOp, dp1, dp2, t1, t2, 0, 2, 1);
+ platext = "0,2,1";
+ platform.execute(prog);
+ }
+ else if (pla == 2)
+ {
+ cout << "Begin with T1:" << t1 << " T2:" << t2 << " OP1:" << 1 << " OP2:" << 2 << " C:" << 0 << endl;
+ Program prog = AMBITTest(andOp, dp1, dp2, t1, t2, 1, 2, 0);
+ platext = "1,2,0";
+ platform.execute(prog);
+ }
+
+ //platform.readRegisterDump();
+ //exit(0);
+
+ for (int row = 0 ; row < NUM_ROWS ; row += 4)
+ {
+ uint8_t rd_rows[3][8192];
+
+ for(int i = 0 ; i < 3 ; i++) // Read three rows each main iteration
+ platform.receiveData((void*)rd_rows[i], 8192);
+
+ uint32_t* readData1 = ((uint32_t*) rd_rows[0]);
+ uint32_t* readData2 = ((uint32_t*) rd_rows[1]);
+ uint32_t* readData3 = ((uint32_t*) rd_rows[2]);
+ unsigned long long errors = 0;
+ bool noTRA = false;
+ for(int i = 0 ; i < 8192/4 ; i++)
+ {
+ unsigned int differences;
+ if (readData1[i] == readData2[i] && readData2[i] == readData3[i])
+ differences = __builtin_popcount(readData1[i]^expected);
+ else{ // if !TRA, assume errors
+ noTRA = true;
+ break;
+ }
+ errors += differences;
+ }
+ if(noTRA)
+ {
+ fileOutput << row << "," << (andOp ? "AND" : "OR") << "," << dp1 << "," << dp2 << "," << t1 << "," << t2 << "," << platext << "," << -1 << endl;
+ cout << "Row:" << row << " No TRA " << endl;
+ }
+ else
+ {
+ fileOutput << row << "," << (andOp ? "AND" : "OR") << "," << dp1 << "," << dp2 << "," << t1 << "," << t2 << "," << platext << "," << errors << endl;
+ cout << "Row:" << row << " Errors:" << errors << endl;
+ }
+ }
+ }
+ }
+ }
+ }
+ fileOutput.close();
+ printf("\nTest Finished\n");
+}