aboutsummaryrefslogtreecommitdiffstats
path: root/sources/apps/Smalltest
diff options
context:
space:
mode:
authorAtaberk <olgunataberk@gmail.com>2022-09-25 17:22:03 +0200
committerAtaberk <olgunataberk@gmail.com>2022-09-25 17:22:03 +0200
commitdc0b3db1b4f1895a07e5fe280ee3790e87f97b9f (patch)
treeb47203aa281bdd959def4451c84d310cd9cf2e12 /sources/apps/Smalltest
downloaddram-bender-dc0b3db1b4f1895a07e5fe280ee3790e87f97b9f.tar.gz
Initial commit
Diffstat (limited to 'sources/apps/Smalltest')
-rw-r--r--sources/apps/Smalltest/.gitignore1
-rwxr-xr-xsources/apps/Smalltest/Makefile32
-rw-r--r--sources/apps/Smalltest/read_write.cpp293
-rw-r--r--sources/apps/Smalltest/read_write.smc170
4 files changed, 496 insertions, 0 deletions
diff --git a/sources/apps/Smalltest/.gitignore b/sources/apps/Smalltest/.gitignore
new file mode 100644
index 0000000..57855ab
--- /dev/null
+++ b/sources/apps/Smalltest/.gitignore
@@ -0,0 +1 @@
+SoftMC_rdwr
diff --git a/sources/apps/Smalltest/Makefile b/sources/apps/Smalltest/Makefile
new file mode 100755
index 0000000..c7498df
--- /dev/null
+++ b/sources/apps/Smalltest/Makefile
@@ -0,0 +1,32 @@
+program_NAME := SoftMC_rdwr
+program_CXX_SRCS := read_write.cpp $(wildcard ../../api/*.c) $(wildcard ../../api/*.cpp)
+program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
+program_CXX_OBJS := ${program_CXX_OBJS:.c=.o}
+program_OBJS := $(program_CXX_OBJS)
+program_INCLUDE_DIRS := ../../api ../../../boost-lib
+program_LIBRARY_DIRS :=
+program_LIBRARIES :=
+CPPFLAGS += -g -std=c++11 -pthread -O3
+
+CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
+LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
+LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
+
+CC=g++
+
+.PHONY: all clean distclean
+
+all: $(program_NAME)
+
+$(program_NAME): $(program_OBJS)
+ $(CC) $(CPPFLAGS) $(program_OBJS) -o $(program_NAME) $(LDFLAGS)
+
+clean:
+ @- $(RM) $(program_NAME)
+ @- $(RM) $(program_OBJS)
+
+parser:
+ $(MAKE) -C ../../api/lexyacc
+ cp ../../api/lexyacc/smc_parser .
+
+distclean: clean
diff --git a/sources/apps/Smalltest/read_write.cpp b/sources/apps/Smalltest/read_write.cpp
new file mode 100644
index 0000000..608b17a
--- /dev/null
+++ b/sources/apps/Smalltest/read_write.cpp
@@ -0,0 +1,293 @@
+#include "instruction.h"
+#include "prog.h"
+#include "platform.h"
+#include <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <cstring>
+#include <list>
+
+using namespace std;
+
+#define USE_SMC_FILE 0
+
+#define NUM_BANKS 16
+#define NUM_ROWS 1024*32
+
+#define NUM_ROWS_REG 8
+#define NUM_BANKS_REG 11
+// Stride register ids are fixed and should not be changed
+// CASR should always be reg 0
+// BASR should always be reg 1
+// RASR should always be reg 2
+#define CASR 0
+#define BASR 1
+#define RASR 2
+
+#define PATTERN_REG 12
+
+#define BAR 7
+#define RAR 6
+#define CAR 4
+
+#define NUM_COLS_REG 14
+#define LOOP_COLS 13
+
+#define TEMP_PATTERN_REG 15
+
+/**
+ * @return an instruction formed by NOPs
+ */
+Inst all_nops()
+{
+ return __pack_mininsts(SMC_NOP(), SMC_NOP(), SMC_NOP(), SMC_NOP());
+}
+
+int main()
+{
+ SoftMCPlatform platform;
+ int err;
+ uint32_t wr_pattern;
+ // buffer allocated for reading data from the board
+ char* buf = (char*) malloc(sizeof(char)*32*1024);
+
+ // Demo using the smc file as program input
+ if(USE_SMC_FILE)
+ {
+ // Load demo smc program from file using
+ // program's constructor
+ Program program("read_write.smc");
+ wr_pattern = 0x1a2b3c4d;
+ printf("Program Ready\n");
+
+ // Initialize the platform, opens file descriptors for the board PCI-E interface.
+ if((err = platform.init()) != SOFTMC_SUCCESS){
+ cerr << "Could not initialize SoftMC Platform: " << err << endl;
+ }
+ // reset the board to hopefully restore the board's state
+ platform.reset_fpga();
+ // Transfer the program to the FPGA board
+ platform.execute(program);
+ printf("Sent instructions\n");
+ }
+ else
+ {
+
+ // Initialize the platform, opens file descriptors for the board PCI-E interface.
+ if((err = platform.init()) != SOFTMC_SUCCESS){
+ cerr << "Could not initialize SoftMC Platform: " << err << endl;
+ }
+ // reset the board to hopefully restore the board's state
+ platform.reset_fpga();
+
+ Program program;
+ /* SoftMC programs are formed sequentially by adding
+ * instructions to the program one by one. Instructions
+ * can be added to the program using add_inst().
+ */
+
+ program.add_inst(SMC_LI(NUM_ROWS, NUM_ROWS_REG)); // load NUM_ROWS into NUM_ROWS_REG
+ program.add_inst(SMC_LI(NUM_BANKS, NUM_BANKS_REG)); // load NUM_BANKS into NUM_BANKS_REG
+
+ // Stride registers are used to increment the row,bank,column registers without
+ // using regular (non-DDR) instructions. This way the DRAM array can be traversed much faster
+
+ program.add_inst(SMC_LI(8, CASR)); // Load 8 into CASR since each READ reads 8 columns
+ program.add_inst(SMC_LI(1, BASR)); // Load 1 into BASR
+ program.add_inst(SMC_LI(1, RASR)); // Load 1 into RASR
+
+ // Initialize PRNG, this test will randomly generate
+ // the first data to write into DRAM, it will modify
+ // the data by cyclic shifting and multiplying it with itself
+ // during runtime (this will be further explained down below).
+ srand(time(NULL)+getpid());
+ uint16_t rand1 = (uint16_t) rand();
+ wr_pattern = rand1 << 16;
+ wr_pattern |= ((uint16_t)rand());
+ printf("wr_pattern: %x\n", wr_pattern);
+
+ // Load WR data into pattern register whose content
+ // will be replicated among all words in the wide register
+ // Wide register is a 512-bit register, its content will
+ // be written to DRAM with SMC_WR commands.
+ program.add_inst(SMC_LI(wr_pattern, PATTERN_REG));
+ for(int i = 0 ; i < 16 ; i++)
+ program.add_inst(SMC_LDWD(PATTERN_REG,i));
+
+ program.add_inst(SMC_LI(0, BAR)); // Initialize BAR (bank address register) with 0
+
+ // add_label is used to add a label that can be used as a branch target to the program
+ program.add_label("BANK_BEGIN");
+
+ program.add_inst(SMC_LI(0, RAR)); // Initialize RAR with 0
+
+ program.add_label("ROW_BEGIN");
+
+ program.add_inst(SMC_LI(0, CAR)); // Initialize CAR with 0
+
+ // Four DRAM commands are issued at the same time
+ // to DRAM by SoftMC.
+
+ // PREcharge bank BAR and wait for tRP (11 NOPs, 11 SoftMC cycles)
+ program.add_inst(
+ SMC_PRE(BAR, 0, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+
+ // ACT & wait for tRCD
+ program.add_inst(
+ SMC_ACT(BAR, 0, RAR, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+
+ // We are now going to loop over all 512-bits in the row
+ // Since each row is 2^13 bytes we need to WR 128 times
+ program.add_inst(SMC_LI(128,NUM_COLS_REG)); // Load COL_SIZE register
+ program.add_inst(SMC_LI(0,LOOP_COLS)); // Load loop variable
+
+ /*
+ * Try to write a different pattern to each cache line
+ * in DRAM.
+ */
+ program.add_label("WR_BEGIN");
+
+ // Write to a whole row, increment CAR per WR
+ program.add_inst(
+ SMC_WRITE(BAR, 0, CAR, 1, 0, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+
+ // Reload wide reg with the new data pattern
+ program.add_inst(SMC_SRC(PATTERN_REG,PATTERN_REG));
+ for(int i = 0 ; i < 16 ; i++)
+ program.add_inst(SMC_LDWD(PATTERN_REG,i));
+
+ program.add_inst(SMC_ADDI(LOOP_COLS,1,LOOP_COLS));
+ // add a branch lower instruction which will jump to WR_BEGIN
+ // as long as LOOP_COLS<NUM_COLS, to iterate over the whole row
+ program.add_branch(program.BR_TYPE::BL,LOOP_COLS,NUM_COLS_REG, "WR_BEGIN");
+ // END "WR_BEGIN" LOOP
+
+ // Add more randomness to the PATTERN_REG by multiplying it by 3
+ // This happens when a row is written to
+ program.add_inst(SMC_MV(PATTERN_REG,TEMP_PATTERN_REG));
+ program.add_inst(SMC_ADD(PATTERN_REG,TEMP_PATTERN_REG,PATTERN_REG));
+ program.add_inst(SMC_ADD(PATTERN_REG,TEMP_PATTERN_REG,PATTERN_REG));
+ for(int i = 0 ; i < 16 ; i++)
+ program.add_inst(SMC_LDWD(PATTERN_REG,i));
+
+ // Wait for t(write-precharge)
+ // & precharge the open bank
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+ program.add_inst(
+ SMC_PRE(BAR, 0, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+
+ program.add_inst(SMC_LI(0, CAR)); // reload CAR we are now going to read the whole row
+
+ // PRE & wait for tRP
+ program.add_inst(
+ SMC_PRE(BAR, 0, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+
+ // ACT & wait for tRCD
+ program.add_inst(
+ SMC_ACT(BAR, 0, RAR, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+
+ // Read from a whole row
+ // Essentially this can be imagined as an unrolled read whole row loop
+ for(int i = 0 ; i < 128 ; i++){
+ program.add_inst(
+ SMC_READ(BAR, 0, CAR, 1, 0, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+ program.add_inst(all_nops());
+ }
+
+ // Wait for t(read-precharge)
+ // & precharge the open bank
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+ program.add_inst(
+ SMC_PRE(BAR, 0, 0),
+ SMC_NOP(), SMC_NOP(), SMC_NOP()
+ );
+
+ // Increment row address by one since we are finished with this row
+ program.add_inst(SMC_ADDI(RAR,1,RAR));
+ program.add_branch(program.BR_TYPE::BL,RAR,NUM_ROWS_REG, "ROW_BEGIN");
+ program.add_inst(SMC_ADDI(BAR,1,BAR));
+ program.add_branch(program.BR_TYPE::BL,BAR,NUM_BANKS_REG,"BANK_BEGIN");
+
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+ program.add_inst(all_nops());
+
+ program.dump_registers();
+
+ // Tells SoftMC that the user program has ended
+ program.add_inst(SMC_END());
+
+ // Transfer the program to the FPGA board
+ platform.execute(program);
+ printf("Program Ready\n");
+ program.pretty_print();
+ printf("Sent instructions\n");
+ }
+
+ // Read count
+ int rc = 0;
+
+ uint32_t pattern = wr_pattern;
+ uint64_t err_count = 0;
+ // Below loop reads continuously from the FPGA board
+ // since we know in what order we are issuing our reads
+ // we know what physical address they are reading
+ while(1)
+ {
+ platform.receiveData(buf, 8*1024); // read one row each iteration
+ for(int j = 0 ; j < 128 ; j++){
+ // printf("Whole pattern for cacheline %d: %x\n", j, pattern);
+ for (int k = 0 ; k < 64 ; k++){ // each byte in cache line
+ uint8_t mini_patt = pattern >> ((uint32_t)(k%4)*8);
+ if(mini_patt != (uint8_t)buf[j*64 + k]){
+ err_count++;
+ fprintf(stderr,"t1: Pattern mismatch! Bank: %d Row: %d CacheLine: %d Byte: %d Expect: %x Read: %x\n",
+ rc/(1024*32), rc%(1024*32), j, k, mini_patt, (uint8_t)buf[j*64 + k]);
+ //fprintf(stderr,"%d %d %d %x\n",
+ // rc/(1024*32), rc%(1024*32), j*64 + k, mini_patt^(uint8_t)buf[j*64 + k]);
+ }
+ }
+
+ //shift pattern at each row iteration
+ uint32_t imd = pattern >> (uint32_t)1;
+ uint32_t imd2 = pattern << (uint32_t)31;
+ pattern = imd | imd2;
+ }
+ pattern = pattern*(uint32_t)3;
+ rc++;
+ if(rc % (1024*32) == 0)
+ printf("Bank %d finished!\n", rc/1024/32);
+ if(rc == 1024*32*16)
+ break;
+ }
+ printf("%ld out of %ld bytes have errors, last pattern: 0x%x\n",
+ err_count, (uint64_t)NUM_BANKS*NUM_ROWS*8192, pattern);
+ platform.readRegisterDump();
+}
diff --git a/sources/apps/Smalltest/read_write.smc b/sources/apps/Smalltest/read_write.smc
new file mode 100644
index 0000000..c4bfd5f
--- /dev/null
+++ b/sources/apps/Smalltest/read_write.smc
@@ -0,0 +1,170 @@
+// Initialize register ids
+// Similar to #define
+casr = 0
+basr = 1
+rasr = 2
+bar = 7
+rar = 6
+car = 4
+pattern_reg = 12
+no_row_reg = 8
+no_bank_reg = 11
+no_cols_reg = 14
+loop_cols_reg = 13
+temp_pattern_reg = 15
+
+// Begin writing the program
+LI no_row_reg 32768 // Write 2^15 to no_row_Reg
+LI no_bank_reg 16 // write 16 to no_bank_reg
+
+// Set stride registers (not required if you
+// are not going to increment address registers
+// with ddr commands)
+LI casr 8 // set column address stride to 8
+LI basr 1 // set bas to 1
+LI rasr 1 // set ras to 1
+
+// Init pattern register, we are going to fill
+// dram with some random pattern.
+LI pattern_reg 0x1a2b3c4d
+
+// Load the data register with the pattern
+// second argument here is the word offset
+// we are writing to in the data register
+// e.g. LDWD 0 pattern reg fills the first four bytes
+
+LDWD 0 pattern_reg
+LDWD 1 pattern_reg
+LDWD 2 pattern_reg
+LDWD 3 pattern_reg
+LDWD 4 pattern_reg
+LDWD 5 pattern_reg
+LDWD 6 pattern_reg
+LDWD 7 pattern_reg
+LDWD 8 pattern_reg
+LDWD 9 pattern_reg
+LDWD 10 pattern_reg
+LDWD 11 pattern_reg
+LDWD 12 pattern_reg
+LDWD 13 pattern_reg
+LDWD 14 pattern_reg
+LDWD 15 pattern_reg
+
+LI bar 0 // Initialize bank address register
+
+BANK_BEGIN: // Add label to loop over banks
+LI rar 0 // Reload rar per bank loop
+
+ROW_BEGIN: // Add label to loop over rows
+LI car 0 // Reload car per row loop
+
+PRE bar // PREcharge bar, don't increment, no precharge-all
+WAIT 11 // Insert seven cycles of NOPs
+
+ACT bar rar // ACTivate bar, rar
+WAIT 11
+
+// Each write will write a different pattern
+// "car++" indicates that we will increment
+// car by casr value.
+
+LI no_cols_reg 128
+LI loop_cols_reg 0
+
+WR_BEGIN:
+
+WR bar car++
+WAIT 3
+
+// Cyclic shift pattern register to add "randomness"
+SRC pattern_reg pattern_reg
+
+// Reload the wide data register
+LDWD 0 pattern_reg
+LDWD 1 pattern_reg
+LDWD 2 pattern_reg
+LDWD 3 pattern_reg
+LDWD 4 pattern_reg
+LDWD 5 pattern_reg
+LDWD 6 pattern_reg
+LDWD 7 pattern_reg
+LDWD 8 pattern_reg
+LDWD 9 pattern_reg
+LDWD 10 pattern_reg
+LDWD 11 pattern_reg
+LDWD 12 pattern_reg
+LDWD 13 pattern_reg
+LDWD 14 pattern_reg
+LDWD 15 pattern_reg
+
+// increment loop variable and iterate
+ADDI loop_cols_reg loop_cols_reg 1
+BL WR_BEGIN loop_cols_reg no_cols_reg
+
+// multiply pattern_reg by 3
+MOV temp_pattern_reg pattern_reg
+ADD pattern_reg pattern_reg temp_pattern_reg
+ADD pattern_reg pattern_reg temp_pattern_reg
+
+// Reload the wide data register
+LDWD 0 pattern_reg
+LDWD 1 pattern_reg
+LDWD 2 pattern_reg
+LDWD 3 pattern_reg
+LDWD 4 pattern_reg
+LDWD 5 pattern_reg
+LDWD 6 pattern_reg
+LDWD 7 pattern_reg
+LDWD 8 pattern_reg
+LDWD 9 pattern_reg
+LDWD 10 pattern_reg
+LDWD 11 pattern_reg
+LDWD 12 pattern_reg
+LDWD 13 pattern_reg
+LDWD 14 pattern_reg
+LDWD 15 pattern_reg
+
+WAIT 8
+PRE bar
+WAIT 3
+
+// Reload car, we are now going to read from DRAM
+LI car 0
+
+// Precharge the open bank
+PRE bar
+WAIT 11
+
+ACT bar rar
+WAIT 11
+
+// This is a basic primitive that can be used
+// to replicate instructions-commands
+// this block replicates the RD command 128 times
+// and adds it to the program
+times 128 {
+ RD bar car++
+ WAIT 7
+}
+
+WAIT 8
+PRE bar
+WAIT 3
+
+// Increment rar per row loop
+ADDI rar rar 1
+// if rar < no_row_reg, execute the "row loop" once more
+BL ROW_BEGIN rar no_row_reg
+
+ADDI bar bar 1
+BL BANK_BEGIN bar no_bank_reg
+
+WAIT 16
+
+// Tell softmc that the program has ended
+// This is important!
+END
+
+// Tell the parser the program definition has ended
+// This is even more important!!
+ENDPROGRAM