From e1842c8da6a8a922317b93b11e646c516d9e84ac Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 11:16:28 -0500 Subject: [PATCH 01/55] Broken commit. Trying to get exe2memfile.pl to work correctly with non 0x8000_0000 starting addresses. --- wally-pipelined/bin/exe2memfile.pl | 26 ++++++++++++------- .../config/busybear/wally-config.vh | 1 + .../config/coremark/wally-config.vh | 1 + .../config/coremark_bare/wally-config.vh | 1 + wally-pipelined/config/rv32ic/wally-config.vh | 1 + wally-pipelined/config/rv64ic/wally-config.vh | 1 + .../config/rv64icfd/wally-config.vh | 1 + .../testbench/testbench-imperas.sv | 3 +-- 8 files changed, 23 insertions(+), 12 deletions(-) diff --git a/wally-pipelined/bin/exe2memfile.pl b/wally-pipelined/bin/exe2memfile.pl index 79b975c7..010e985d 100755 --- a/wally-pipelined/bin/exe2memfile.pl +++ b/wally-pipelined/bin/exe2memfile.pl @@ -43,43 +43,48 @@ for(my $i=0; $i<=$#ARGV; $i++) { my $address; # initialize to all zeros; + # *** need to fix the zeroing range. Not always 64K for (my $i=0; $i < 65536*4; $i++) { $memfilebytes[$i] = "00"; } while() { if ($mode == 0) { # Parse code - # print("Examining $_\n"); - if (/^\s*(\S\S\S\S\S\S\S\S):\s+(\S+)\s+/) { +# print("Examining $_\n"); + if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { $address = &fixadr($1); my $instr = $2; my $len = length($instr); for (my $i=0; $i<$len/2; $i++) { $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); } - # print ("address $address $instr\n"); - } - if (/Disassembly of section .data:/) { $mode = 1;} + print ("address $address $instr\n"); + } + if (/Disassembly of section .data:/) { $mode = 1;} } elsif ($mode == 1) { # Parse data segment - if (/^\s*(\S\S\S\S\S\S\S\S):\s+(.*)/) { + if (/^\s*(\S{1,16}):\s+(.*)/) { $address = &fixadr($1); - # print "addresss $address maxaddress $maxaddress\n"; - if ($address > $maxaddress) { $maxaddress = $address; } +# print "addresss $address maxaddress $maxaddress\n"; + if ($address > $maxaddress) { $maxaddress = $address; } my $line = $2; # merge chunks with spaces + # *** might need to change $line =~ s/(\S)\s(\S)/$1$2/g; # strip off comments $line =~ /^(\S*)/; $payload = $1; &emitData($address, $payload); } - if (/Disassembly of section .riscv.attributes:/) { $mode = 2; } + if (/Disassembly of section .comment:/) { $mode = 2; } + } elsif ($mode == 2) { # parse the comment section + if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } } } close(FILE); $maxaddress += 32; # pad some zeros at the end # print to memory file + # *** this is a problem if ($fname =~ /rv32/) { open(MEMFILE, ">$memfile") || die("Can't write $memfile"); for (my $i=0; $i<= $maxaddress; $i = $i + 4) { @@ -133,7 +138,8 @@ sub emitData { sub fixadr { # strip off leading 8 from address and convert to decimal + # if the leading 8 is not present don't remove. my $adr = shift; if ($adr =~ s/^8/0/) { return hex($adr); } - else { die("address $adr lacks leading 8\n"); } + else { return hex($adr) } } diff --git a/wally-pipelined/config/busybear/wally-config.vh b/wally-pipelined/config/busybear/wally-config.vh index 3a619598..cc3693f8 100644 --- a/wally-pipelined/config/busybear/wally-config.vh +++ b/wally-pipelined/config/busybear/wally-config.vh @@ -99,3 +99,4 @@ `define TWO_BIT_PRELOAD "../config/busybear/twoBitPredictor.txt" `define BTB_PRELOAD "../config/busybear/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/coremark/wally-config.vh b/wally-pipelined/config/coremark/wally-config.vh index 5f0714ae..74497064 100644 --- a/wally-pipelined/config/coremark/wally-config.vh +++ b/wally-pipelined/config/coremark/wally-config.vh @@ -101,3 +101,4 @@ `define TWO_BIT_PRELOAD "../config/coremark/twoBitPredictor.txt" `define BTB_PRELOAD "../config/coremark/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/coremark_bare/wally-config.vh b/wally-pipelined/config/coremark_bare/wally-config.vh index 8f2512f3..ce958ffd 100644 --- a/wally-pipelined/config/coremark_bare/wally-config.vh +++ b/wally-pipelined/config/coremark_bare/wally-config.vh @@ -97,3 +97,4 @@ `define TWO_BIT_PRELOAD "../config/coremark_bare/twoBitPredictor.txt" `define BTB_PRELOAD "../config/coremark_bare/BTBPredictor.txt" +`define TESTSBP 0 diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index 5ee1d170..fadbe36c 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -95,3 +95,4 @@ `define TWO_BIT_PRELOAD "../config/rv32ic/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv32ic/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index c3f9849a..b27a5e1c 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -98,3 +98,4 @@ `define TWO_BIT_PRELOAD "../config/rv64ic/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64ic/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/rv64icfd/wally-config.vh b/wally-pipelined/config/rv64icfd/wally-config.vh index 9b3dae29..853b8685 100644 --- a/wally-pipelined/config/rv64icfd/wally-config.vh +++ b/wally-pipelined/config/rv64icfd/wally-config.vh @@ -98,3 +98,4 @@ `define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 2f6f0efb..f62abdb4 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -28,7 +28,6 @@ module testbench(); parameter DEBUG = 0; - parameter TESTSBP = 0; logic clk; logic reset; @@ -337,7 +336,7 @@ string tests32i[] = { // pick tests based on modes supported initial if (`XLEN == 64) begin // RV64 - if(TESTSBP) begin + if(`TESTSBP) begin tests = testsBP64; end else begin tests = {tests64i}; From 2b0f7cdd4215072bd101f0d5ea65922155390b27 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 11:53:39 -0500 Subject: [PATCH 02/55] Temporary exe2memfile0.pl script to support starting addresses of 0. --- wally-pipelined/bin/exe2memfile.pl | 2 +- wally-pipelined/bin/exe2memfile0.pl | 144 +++ .../config/rv64BP/BTBPredictor.txt | 1024 +++++++++++++++++ .../config/rv64BP/twoBitPredictor.txt | 1024 +++++++++++++++++ wally-pipelined/config/rv64BP/wally-config.vh | 99 ++ .../config/rv64BP/wally-constants.vh | 31 + 6 files changed, 2323 insertions(+), 1 deletion(-) create mode 100755 wally-pipelined/bin/exe2memfile0.pl create mode 100644 wally-pipelined/config/rv64BP/BTBPredictor.txt create mode 100644 wally-pipelined/config/rv64BP/twoBitPredictor.txt create mode 100644 wally-pipelined/config/rv64BP/wally-config.vh create mode 100644 wally-pipelined/config/rv64BP/wally-constants.vh diff --git a/wally-pipelined/bin/exe2memfile.pl b/wally-pipelined/bin/exe2memfile.pl index 010e985d..51af9ed6 100755 --- a/wally-pipelined/bin/exe2memfile.pl +++ b/wally-pipelined/bin/exe2memfile.pl @@ -58,7 +58,7 @@ for(my $i=0; $i<=$#ARGV; $i++) { for (my $i=0; $i<$len/2; $i++) { $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); } - print ("address $address $instr\n"); +# print ("address $address $instr\n"); } if (/Disassembly of section .data:/) { $mode = 1;} } elsif ($mode == 1) { # Parse data segment diff --git a/wally-pipelined/bin/exe2memfile0.pl b/wally-pipelined/bin/exe2memfile0.pl new file mode 100755 index 00000000..975d38d2 --- /dev/null +++ b/wally-pipelined/bin/exe2memfile0.pl @@ -0,0 +1,144 @@ +#!/usr/bin/perl -w + +# exe2memfile.pl +# David_Harris@hmc.edu 26 November 2020 +# Converts an executable file to a series of 32-bit hex instructions +# to read into a Verilog simulation with $readmemh + +use File::stat; +use IO::Handle; + +if ($#ARGV == -1) { + die("Usage: $0 executable_file"); +} + +# array to hold contents of memory file +my @memfilebytes = (0)*16384*4; +my $maxaddress = 0; + +STDOUT->autoflush(1); +# *** Ross Thompson I think there is a bug here needs to be +1 +print ("Processing $#ARGV memfiles: "); +my $frac = $#ARGV/10; +for(my $i=0; $i<=$#ARGV; $i++) { + if ($i < 10 || $i % $frac == 0) { print ("$i ") }; + my $fname = $ARGV[$i]; +# print "fname = $fname"; + my $ofile = $fname.".objdump"; + my $memfile = $fname.".memfile"; + + my $needsprocessing = 0; + if (!-e $memfile) { $needsprocessing = 1; } # create memfile if it doesn't exist + else { + my $osb = stat($ofile) || die("Can't stat $ofile"); + my $msb = stat($memfile) || die("Can't stat $memfile"); + my $otime = $osb->mtime; + my $mtime = $msb->mtime; + if ($otime > $mtime) { $needsprocessing = 1; } # is memfile out of date? + } + + if ($needsprocessing == 1) { + open(FILE, $ofile) || die("Can't read $ofile"); + my $mode = 0; # parse for code + my $address; + + # initialize to all zeros; + # *** need to fix the zeroing range. Not always 64K + for (my $i=0; $i < 65536*4; $i++) { + $memfilebytes[$i] = "00"; + } + + while() { + if ($mode == 0) { # Parse code +# print("Examining $_\n"); + if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { + $address = &fixadr($1); + my $instr = $2; + my $len = length($instr); + for (my $i=0; $i<$len/2; $i++) { + $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); + } +# print ("address $address $instr\n"); + } + if (/Disassembly of section .data:/) { $mode = 1;} + } elsif ($mode == 1) { # Parse data segment + if (/^\s*(\S{1,16}):\s+(.*)/) { + $address = &fixadr($1); +# print "addresss $address maxaddress $maxaddress\n"; + if ($address > $maxaddress) { $maxaddress = $address; } + my $line = $2; + # merge chunks with spaces + # *** might need to change + $line =~ s/(\S)\s(\S)/$1$2/g; + # strip off comments + $line =~ /^(\S*)/; + $payload = $1; + &emitData($address, $payload); + } + if (/Disassembly of section .comment:/) { $mode = 2; } + } elsif ($mode == 2) { # parse the comment section + if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } + } + } + close(FILE); + $maxaddress += 32; # pad some zeros at the end + + # print to memory file + # *** this is a problem + if ($fname =~ /rv32/) { + open(MEMFILE, ">$memfile") || die("Can't write $memfile"); + for (my $i=0; $i<= $maxaddress; $i = $i + 4) { + for ($j=3; $j>=0; $j--) { + print MEMFILE "$memfilebytes[$i+$j]"; + } + print MEMFILE "\n"; + } + close(MEMFILE); + } else { + open(MEMFILE, ">$memfile") || die("Can't write $memfile"); + for (my $i=0; $i<= $maxaddress; $i = $i + 8) { + for ($j=7; $j>=0; $j--) { + print MEMFILE "$memfilebytes[$i+$j]"; + } + print MEMFILE "\n"; + } + close(MEMFILE); + } + } +} +print("\n"); + +sub emitData { + # print the data portion of the ELF into a memroy file, including 0s for empty stuff + # deal with endianness + my $address = shift; + my $payload = shift; + +# print("Emitting data. address = $address payload = $payload\n"); + + my $len = length($payload); + if ($len <= 8) { + # print word or halfword + for(my $i=0; $i<$len/2; $i++) { + my $adr = $address+$i; + my $b = substr($payload, $len-2-2*$i, 2); + $memfilebytes[$adr] = $b; +# print(" $adr $b\n"); + } + } elsif ($len == 12) { + # weird case of three halfwords on line + &emitData($address, substr($payload, 0, 4)); + &emitData($address+2, substr($payload, 4, 4)); + &emitData($address+4, substr($payload, 8, 4)); + } else { + &emitData($address, substr($payload, 0, 8)); + &emitData($address+4, substr($payload, 8, $len-8)); + } +} + +sub fixadr { + # strip off leading 8 from address and convert to decimal + # if the leading 8 is not present don't remove. + my $adr = shift; + return hex($adr); +} diff --git a/wally-pipelined/config/rv64BP/BTBPredictor.txt b/wally-pipelined/config/rv64BP/BTBPredictor.txt new file mode 100644 index 00000000..b761147c --- /dev/null +++ b/wally-pipelined/config/rv64BP/BTBPredictor.txt @@ -0,0 +1,1024 @@ +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 diff --git a/wally-pipelined/config/rv64BP/twoBitPredictor.txt b/wally-pipelined/config/rv64BP/twoBitPredictor.txt new file mode 100644 index 00000000..ff57bd47 --- /dev/null +++ b/wally-pipelined/config/rv64BP/twoBitPredictor.txt @@ -0,0 +1,1024 @@ +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh new file mode 100644 index 00000000..5ea56c02 --- /dev/null +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -0,0 +1,99 @@ +////////////////////////////////////////// +// wally-config.vh +// +// Written: David_Harris@hmc.edu 4 January 2021 +// Modified: Brett Mathis +// +// Purpose: Specify which features are configured +// Macros to determine which modes are supported based on MISA +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +// RV32 or RV64: XLEN = 32 or 64 +`define XLEN 64 + +//`define MISA (32'h00000104) +`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20) +`define A_SUPPORTED ((`MISA >> 0) % 2 == 1) +`define C_SUPPORTED ((`MISA >> 2) % 2 == 1) +`define D_SUPPORTED ((`MISA >> 3) % 2 == 1) +`define F_SUPPORTED ((`MISA >> 5) % 2 == 1) +`define M_SUPPORTED ((`MISA >> 12) % 2 == 1) +`define S_SUPPORTED ((`MISA >> 18) % 2 == 1) +`define U_SUPPORTED ((`MISA >> 20) % 2 == 1) +`define ZCSR_SUPPORTED 1 +`define COUNTERS 31 +`define ZCOUNTERS_SUPPORTED 1 +// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21 +//`define N_SUPPORTED ((MISA >> 13) % 2 == 1) +`define N_SUPPORTED 0 + +`define M_MODE (2'b11) +`define S_MODE (2'b01) +`define U_MODE (2'b00) + +// Microarchitectural Features +`define UARCH_PIPELINED 1 +`define UARCH_SUPERSCALR 0 +`define UARCH_SINGLECYCLE 0 +`define MEM_DCACHE 0 +`define MEM_DTIM 1 +`define MEM_ICACHE 0 +`define MEM_VIRTMEM 0 + +// Address space +`define RESET_VECTOR 64'h0000000000000000 + +// Bus Interface width +`define AHBW 64 + +// Peripheral Addresses +// Peripheral memory space extends from BASE to BASE+RANGE +// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits + +`define BOOTTIMBASE 32'h00080000 +`define BOOTTIMRANGE 32'h00003FFF +`define TIMBASE 32'h00000000 +`define TIMRANGE 32'h0007FFFF +`define CLINTBASE 32'h02000000 +`define CLINTRANGE 32'h0000FFFF +`define GPIOBASE 32'h10012000 +`define GPIORANGE 32'h000000FF +`define UARTBASE 32'h10000000 +`define UARTRANGE 32'h00000007 + +// Test modes + +// Tie GPIO outputs back to inputs +`define GPIO_LOOPBACK_TEST 0 + +// Busybear special CSR config to match OVPSim +`define OVPSIM_CSR_CONFIG 0 + +// Hardware configuration +`define UART_PRESCALE 1 + +/* verilator lint_off STMTDLY */ +/* verilator lint_off WIDTH */ +/* verilator lint_off ASSIGNDLY */ +/* verilator lint_off PINCONNECTEMPTY */ + +`define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" +`define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" +`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 1 diff --git a/wally-pipelined/config/rv64BP/wally-constants.vh b/wally-pipelined/config/rv64BP/wally-constants.vh new file mode 100644 index 00000000..55fb4e94 --- /dev/null +++ b/wally-pipelined/config/rv64BP/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv39) +`define VPN_BITS 27 +`define PPN_BITS 44 +`define PA_BITS 56 From 9e61481414e3e7ffefe6037a0100ae9bcbf327b2 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 12:01:57 -0500 Subject: [PATCH 03/55] Added first benchmark. --- wally-pipelined/testbench/testbench-imperas.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index f62abdb4..8a244428 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -316,7 +316,8 @@ string tests32i[] = { }; string testsBP64[] = '{ - "rv64BP/reg-test", "10000" + "rv64BP/reg-test", "10000", + "rv64BP/sieve", "1000000" }; string tests[]; string ProgramAddrMapFile, ProgramLabelMapFile; From 6a050219d40c809ebf3fd3b166f863433698ac4d Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 12:12:16 -0500 Subject: [PATCH 04/55] updated the branch predictor config. --- wally-pipelined/config/rv64BP/wally-config.vh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh index 5ea56c02..bd053750 100644 --- a/wally-pipelined/config/rv64BP/wally-config.vh +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -76,6 +76,8 @@ `define GPIORANGE 32'h000000FF `define UARTBASE 32'h10000000 `define UARTRANGE 32'h00000007 +`define PLICBASE 32'h0C000000 +`define PLICRANGE 32'h03FFFFFF // Test modes From 5edc90b1c22a5ad8f430f69d2f8796576836705c Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 13:54:29 -0500 Subject: [PATCH 05/55] added a whole bunch of interseting test code for branches which does not work. --- testsBP/crt0/Makefile | 23 ++ testsBP/crt0/isr.s | 213 +++++++++++++++ testsBP/crt0/start.s | 60 +++++ testsBP/linker.x | 244 ++++++++++++++++++ testsBP/makefile.inc | 92 +++++++ testsBP/sieve/Makefile | 15 ++ testsBP/sieve/sieve.c | 101 ++++++++ testsBP/simple/Makefile | 15 ++ testsBP/simple/fail.s | 11 + testsBP/simple/header.h | 6 + testsBP/simple/main.c | 10 + testsBP/simple/sample.s | 52 ++++ wally-pipelined/bin/exe2memfile0.pl | 1 + .../testbench/testbench-imperas.sv | 2 +- 14 files changed, 844 insertions(+), 1 deletion(-) create mode 100644 testsBP/crt0/Makefile create mode 100644 testsBP/crt0/isr.s create mode 100644 testsBP/crt0/start.s create mode 100644 testsBP/linker.x create mode 100644 testsBP/makefile.inc create mode 100644 testsBP/sieve/Makefile create mode 100644 testsBP/sieve/sieve.c create mode 100644 testsBP/simple/Makefile create mode 100644 testsBP/simple/fail.s create mode 100644 testsBP/simple/header.h create mode 100644 testsBP/simple/main.c create mode 100644 testsBP/simple/sample.s diff --git a/testsBP/crt0/Makefile b/testsBP/crt0/Makefile new file mode 100644 index 00000000..97b83faf --- /dev/null +++ b/testsBP/crt0/Makefile @@ -0,0 +1,23 @@ +TARGETDIR := bin +TARGET := $(TARGETDIR)/start +ROOT := .. +LIBRARY_DIRS := +LIBRARY_FILES := +LINK_FLAGS := -nostartfiles + +AFLAGS =-march=rv64ifd -W +CFLAGS =-march=rv64ifd -mcmodel=medany +AS=riscv64-unknown-elf-as +CC=riscv64-unknown-elf-gcc +AR=riscv64-unknown-elf-ar + +all: libcrt0.a + +%.o: %.s + ${AS} ${AFLAGS} -c $< -o $@ + +libcrt0.a: start.o + ${AR} -r $@ $^ + +clean: + rm -rf *.a *.o diff --git a/testsBP/crt0/isr.s b/testsBP/crt0/isr.s new file mode 100644 index 00000000..789d2d62 --- /dev/null +++ b/testsBP/crt0/isr.s @@ -0,0 +1,213 @@ +.section .text +.global __trap_handler +.type __trap_handler, @function + +__trap_handler: + # save the context of the cpu to the top of the current stack + addi sp, sp, -124 + sw x1, 0x0(sp) + sw x2, 0x4(sp) + sw x3, 0x8(sp) + sw x4, 0xC(sp) + sw x5, 0x10(sp) + sw x6, 0x14(sp) + sw x7, 0x18(sp) + sw x8, 0x1C(sp) + sw x9, 0x20(sp) + sw x10, 0x24(sp) + sw x11, 0x28(sp) + sw x12, 0x2C(sp) + sw x13, 0x30(sp) + sw x14, 0x34(sp) + sw x15, 0x38(sp) + sw x16, 0x3C(sp) + sw x17, 0x40(sp) + sw x18, 0x44(sp) + sw x19, 0x48(sp) + sw x20, 0x4C(sp) + sw x21, 0x50(sp) + sw x22, 0x54(sp) + sw x23, 0x58(sp) + sw x24, 0x5C(sp) + sw x25, 0x60(sp) + sw x26, 0x64(sp) + sw x27, 0x68(sp) + sw x28, 0x6C(sp) + sw x29, 0x70(sp) + sw x30, 0x74(sp) + sw x31, 0x78(sp) + + # figure out what caused the trap. + csrrw t0, mcause, x0 + # mcause is {int, 31 bit exception code} + # for this implementation only the lowest 4 bits are used + srli t1, t0, 31 # interrupt flag + andi t2, t0, 0xF # 4 bit cause + + slli t1, t1, 5 # shift int flag + or t1, t1, t2 # combine + slli t1, t1, 2 # multiply by 4 + la t3, exception_table + add t4, t3, t1 + lw t5, 0(t4) + jr t5, 0 # jump to specific ISR + # specific ISR is expected to set epc + +restore_st: + # restore register from stack on exit. + + lw x1, 0x0(sp) + lw x2, 0x4(sp) + lw x3, 0x8(sp) + lw x4, 0xC(sp) + lw x5, 0x10(sp) + lw x6, 0x14(sp) + lw x7, 0x18(sp) + lw x8, 0x1C(sp) + lw x9, 0x20(sp) + lw x10, 0x24(sp) + lw x11, 0x28(sp) + lw x12, 0x2C(sp) + lw x13, 0x30(sp) + lw x14, 0x34(sp) + lw x15, 0x38(sp) + lw x16, 0x3C(sp) + lw x17, 0x40(sp) + lw x18, 0x44(sp) + lw x19, 0x48(sp) + lw x20, 0x4C(sp) + lw x21, 0x50(sp) + lw x22, 0x54(sp) + lw x23, 0x58(sp) + lw x24, 0x5C(sp) + lw x25, 0x60(sp) + lw x26, 0x64(sp) + lw x27, 0x68(sp) + lw x28, 0x6C(sp) + lw x29, 0x70(sp) + lw x30, 0x74(sp) + lw x31, 0x78(sp) + + addi sp, sp, 124 + + mret + +.section .text +.type trap_instr_addr_misalign, @function +trap_instr_addr_misalign: + # fatal error, report error and halt + addi sp, sp, 4 + sw ra, 0(sp) + jal fail + lw ra, 0(sp) + la t0, restore_st + jr t0, 0 + +.section .text +.type trap_m_ecall, @function +trap_m_ecall: + addi sp, sp, -4 + sw ra, 0(sp) + # select which system call based on a7. + # for this example we will just define the following. + # not standard with linux or anything. + # 0: execute a call back function + # 1: decrease privilege by 1 (m=>s, s=>u, u=>u) + # 2: increase privilege by 1 (m=>m, s=>m, u=>s) + + # check a7 + li t0, 1 + beq a7, t0, trap_m_decrease_privilege + li t0, 2 + beq a7, t0, trap_m_increase_privilege + + # call call back function if not zero + la t1, isr_m_ecall_cb_fp + lw t0, 0(t1) + beq t0, x0, trap_m_ecall_skip_cb + jalr ra, t0, 0 +trap_m_ecall_skip_cb: + # modify the mepc + csrrw t0, mepc, x0 + addi t0, t0, 4 + csrrw x0, mepc, t0 + lw ra, 0(sp) + addi sp, sp, 4 + la t0, restore_st + jr t0, 0 + +trap_m_decrease_privilege: + # read the mstatus register + csrrw t0, mstatus, x0 + # 11 => 01, and 01 => 00. + # this is accomplished by clearing bit 12 and taking the old + # bit 12 as the new bit 11. + li t3, 0x00001800 + and t1, t0, t3 # isolates the bits 12 and 11. + # shift right by 1. + srli t2, t1, 1 + and t2, t2, t3 # this will clear bit 10. + li t3, ~0x00001800 + and t4, t0, t3 + or t0, t2, t4 + csrrw x0, mstatus, t0 + j trap_m_ecall_skip_cb + +trap_m_increase_privilege: + # read the mstatus register + csrrw t0, mstatus, x0 + # 11 => 01, and 01 => 00. + # this is accomplished by setting bit 11 and taking the old + # bit 11 as the new bit 12. + li t3, 0x00000800 + li t4, ~0x00000800 + and t1, t0, t3 + slli t2, t1, 1 # shift left by 1. + or t2, t2, t3 # bit 11 is always set. + and t1, t0, t5 + or t0, t1, t2 + csrrw x0, mstatus, t0 + j trap_m_ecall_skip_cb + +.data +exception_table: + .int trap_instr_addr_misalign + .int trap_instr_addr_misalign #trap_instr_access_fault + .int trap_instr_addr_misalign #trap_illegal_instr + .int trap_instr_addr_misalign #trap_breakpoint + .int trap_instr_addr_misalign #trap_load_addr_misalign + .int trap_instr_addr_misalign #trap_load_access_fault + .int trap_instr_addr_misalign #trap_store_addr_misalign + .int trap_instr_addr_misalign #trap_store_access_fault + .int trap_m_ecall + .int trap_m_ecall + .int restore_st + .int trap_m_ecall + .int trap_instr_addr_misalign #trap_instr_page_fault + .int trap_instr_addr_misalign #trap_load_page_fault + .int restore_st + .int trap_instr_addr_misalign #trap_store_page_fault +#.data +#interrupt_table: + .int trap_instr_addr_misalign #trap_u_software + .int trap_instr_addr_misalign #trap_s_software + .int restore_st + .int trap_instr_addr_misalign #trap_m_software + .int trap_instr_addr_misalign #trap_u_timer + .int trap_instr_addr_misalign #trap_s_timer + .int restore_st + .int trap_instr_addr_misalign #trap_m_timer + .int trap_instr_addr_misalign #trap_u_external + .int trap_instr_addr_misalign #trap_s_external + .int restore_st + .int trap_instr_addr_misalign #trap_m_external + .int restore_st + .int restore_st + .int restore_st + .int restore_st + + +.section .data +.global isr_m_ecall_cb_fp +isr_m_ecall_cb_fp: + .int 0 diff --git a/testsBP/crt0/start.s b/testsBP/crt0/start.s new file mode 100644 index 00000000..17543581 --- /dev/null +++ b/testsBP/crt0/start.s @@ -0,0 +1,60 @@ +.section .init +.global _start +.type _start, @function + +_start: + # Initialize global pointer + .option push + .option norelax + 1:auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) + .option pop + + li x1, 0 + li x2, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + + + + # set the stack pointer to the top of memory + # 0x8000_0000 + 64K - 8 bytes + li sp, 0x0000FFF8 + + jal ra, main + jal ra, _halt + +.section .text +.global _halt +.type _halt, @function +_halt: + li gp, 1 + li a0, 0 + ecall + j _halt diff --git a/testsBP/linker.x b/testsBP/linker.x new file mode 100644 index 00000000..f448109c --- /dev/null +++ b/testsBP/linker.x @@ -0,0 +1,244 @@ +OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", + "elf64-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(_start) +SEARCH_DIR("/opt/riscv/riscv64-unknown-elf/lib"); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + /* init segment to ensure we get a consistent start routine*/ + . = 0x0000000000000000; + . = ALIGN(0x0); + .init : { + *(.init) + } + _start_end = .; + + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0)); . = SEGMENT_START("text-segment", _start_end); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf64.em. */ + *(.gnu.warning) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : + { + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : + { + PROVIDE_HIDDEN (__tdata_start = .); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + . = DATA_SEGMENT_RELRO_END (0, .); + .data : + { + __DATA_BEGIN__ = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + __SDATA_BEGIN__ = .; + *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + .sbss : + { + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we do not + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(64 / 8); + __BSS_END__ = .; + __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, + MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800)); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/testsBP/makefile.inc b/testsBP/makefile.inc new file mode 100644 index 00000000..af0b03bc --- /dev/null +++ b/testsBP/makefile.inc @@ -0,0 +1,92 @@ +CEXT := c +CPPEXT := cpp +AEXT := s +SEXT := S +SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\) +OBJEXT := o +DEPEXT := d +SRCDIR := . +BUILDDIR := OBJ +LINKER := ${ROOT}/linker.x + +SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort) +OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) + +#Default Make +all: directories $(TARGET).memfile + +#Remake +remake: clean all + +#Make the Directories +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + + +#Needed for building additional library projects +ifdef LIBRARY_DIRS +LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%} +INC+=${LIBRARY_DIRS:%=-I%} + +${LIBRARY_DIRS}: + make -C $@ -j 1 + +.PHONY: $(LIBRARY_DIRS) $(TARGET) +endif + + +#Pull in dependency info for *existing* .o files +-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) + +#Link +$(TARGET): $(OBJECTS) $(LIBRARY_DIRS) + $(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER} + + +#Compile +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# gcc won't output dependencies for assembly files for some reason +# most asm files don't have dependencies so the echo will work for now. +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +# C++ +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# convert to hex +$(TARGET).memfile: $(TARGET) + @echo 'Making object dump file.' + @riscv64-unknown-elf-objdump -D $< > $<.objdump + @echo 'Making memory file' + exe2memfile0.pl $< + extractFunctionRadix.sh $<.objdump diff --git a/testsBP/sieve/Makefile b/testsBP/sieve/Makefile new file mode 100644 index 00000000..9dcaab8d --- /dev/null +++ b/testsBP/sieve/Makefile @@ -0,0 +1,15 @@ +TARGETDIR := sieve +TARGET := $(TARGETDIR)/$(TARGETDIR).elf +ROOT := .. +LIBRARY_DIRS := ${ROOT}/crt0 +LIBRARY_FILES := crt0 +LINK_FLAGS := -nostartfiles -Wl,-Map=$(TARGET).map + +CFLAGS =-march=rv64ifd -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align +CC=riscv64-unknown-elf-gcc +DA=riscv64-unknown-elf-objdump -d + + +include $(ROOT)/makefile.inc + + diff --git a/testsBP/sieve/sieve.c b/testsBP/sieve/sieve.c new file mode 100644 index 00000000..949d9fde --- /dev/null +++ b/testsBP/sieve/sieve.c @@ -0,0 +1,101 @@ +/* + * Filename: + * + * sieve.c + * + * Description: + * + * The Sieve of Eratosthenes benchmark, from Byte Magazine + * early 1980s, when a PC would do well to run this in 10 + * seconds. This version really does count prime numbers + * but omits the numbers 1, 3 and all even numbers. The + * expected count is 1899. + * + */ + +#include +#include + +#define SIZE 8190 + +//#define SIZE 8388608 +double time_diff(struct timeval x , struct timeval y); + +int sieve () { + + unsigned char flags [SIZE + 1]; + int iter; + int count; + + for (iter = 1; iter <= 10; iter++) + { + int i, prime, k; + + count = 0; + + for (i = 0; i <= SIZE; i++) + flags [i] = 1; + + for (i = 0; i <= SIZE; i++) + { + if (flags [i]) + { + prime = i + i + 3; + k = i + prime; + + while (k <= SIZE) + { + flags [k] = 0; + k += prime; + } + + count++; + } + } + } + + return count; +} + +int main () { + + int ans; + + struct timeval before , after; + gettimeofday(&before , NULL); + + ans = sieve (); + gettimeofday(&after , NULL); + if (ans != 1899) + printf ("Sieve result wrong, ans = %d, expected 1899", ans); + + printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); + + + printf("Round 2\n"); + gettimeofday(&before , NULL); + + ans = sieve (); + gettimeofday(&after , NULL); + if (ans != 1899) + printf ("Sieve result wrong, ans = %d, expected 1899", ans); + + printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); + + return 0; + +} + + +double time_diff(struct timeval x , struct timeval y) +{ + double x_ms , y_ms , diff; + + x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec; + y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec; + + diff = (double)y_ms - (double)x_ms; + + return diff; +} + diff --git a/testsBP/simple/Makefile b/testsBP/simple/Makefile new file mode 100644 index 00000000..aa350755 --- /dev/null +++ b/testsBP/simple/Makefile @@ -0,0 +1,15 @@ +TARGETDIR := simple +TARGET := $(TARGETDIR)/$(TARGETDIR).elf +ROOT := .. +LIBRARY_DIRS := ${ROOT}/crt0 +LIBRARY_FILES := crt0 +LINK_FLAGS := -nostartfiles -Wl,-Map=$(TARGET).map + +CFLAGS =-march=rv64ifd -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align +CC=riscv64-unknown-elf-gcc +DA=riscv64-unknown-elf-objdump -d + + +include $(ROOT)/makefile.inc + + diff --git a/testsBP/simple/fail.s b/testsBP/simple/fail.s new file mode 100644 index 00000000..552604fe --- /dev/null +++ b/testsBP/simple/fail.s @@ -0,0 +1,11 @@ +# Ross Thompson +# March 17, 2021 +# Oklahoma State University + +.section .text +.global fail +.type fail, @function +fail: + li gp, 1 + li a0, -1 + ecall diff --git a/testsBP/simple/header.h b/testsBP/simple/header.h new file mode 100644 index 00000000..b5268fbf --- /dev/null +++ b/testsBP/simple/header.h @@ -0,0 +1,6 @@ +#ifndef __header +#define __header + +int fail(); +int simple_csrbr_test(); +#endif diff --git a/testsBP/simple/main.c b/testsBP/simple/main.c new file mode 100644 index 00000000..047a52f8 --- /dev/null +++ b/testsBP/simple/main.c @@ -0,0 +1,10 @@ +#include "header.h" + +int main(){ + int res = simple_csrbr_test(); + if (res < 0) { + fail(); + return 0; + }else + return 0; +} diff --git a/testsBP/simple/sample.s b/testsBP/simple/sample.s new file mode 100644 index 00000000..399d3bd7 --- /dev/null +++ b/testsBP/simple/sample.s @@ -0,0 +1,52 @@ +.section .text +.global simple_csrbr_test +.type simple_csrbr_test, @function + +simple_csrbr_test: + + # step 1 enable the performance counters + # by default the hardware enables all performance counters + # however we will eventually want to manually enable incase + # some other code disables thems + + # step 2 read performance counters into general purpose registers + + csrrw t2, 0xB05, x0 # t2 = BR COUNT (perf count 5) + csrrw t3, 0xB04, x0 # t3 = BRMP COUNT (perf count 4) + + # step 3 simple loop to show the counters are updated. + li t0, 0 # this is the loop counter + li t1, 100 # this is the loop end condition + + # for(t1 = 0; t1 < t0; t1++); + +loop: + addi t0, t0, 1 + blt t0, t1, loop + +loop_done: + + # step 2 read performance counters into general purpose registers + + csrrw t4, 0xB05, x0 # t4 = BR COUNT (perf count 5) + csrrw t5, 0xB04, x0 # t5 = BRMP COUNT (perf count 4) + + sub t2, t4, t2 # this is the number of branch instructions committed. + sub t3, t5, t3 # this is the number of branch mispredictions committed. + + # now check if the branch count equals 100 and if the branch + bne t4, t2, fail + # *** come back to t3 + + +pass: + li a0, 0 + ret + +fail: + li a0, -1 + ret + +.data +sample_data: +.int 0 diff --git a/wally-pipelined/bin/exe2memfile0.pl b/wally-pipelined/bin/exe2memfile0.pl index 975d38d2..8fbea6f8 100755 --- a/wally-pipelined/bin/exe2memfile0.pl +++ b/wally-pipelined/bin/exe2memfile0.pl @@ -49,6 +49,7 @@ for(my $i=0; $i<=$#ARGV; $i++) { } while() { + # *** this mode stuff does not work if a section is missing or reordered. if ($mode == 0) { # Parse code # print("Examining $_\n"); if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 8a244428..4627cff3 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -316,7 +316,7 @@ string tests32i[] = { }; string testsBP64[] = '{ - "rv64BP/reg-test", "10000", + "rv64BP/simple", "10000", "rv64BP/sieve", "1000000" }; string tests[]; From 174557ae8937bf65f16b7a2492ffc1be0df71b4d Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 14:04:58 -0500 Subject: [PATCH 06/55] Simulation definitely shows the branch predictor counters and branch predictor don't work. :( --- wally-pipelined/regression/wave.do | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 379c7ab4..11029465 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -82,7 +82,6 @@ add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/PCLinkW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW @@ -141,8 +140,12 @@ add wave -noupdate -group {function radix debug} /testbench/functionRadix/functi add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/HPMCOUNTER +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {3758805 ns} 0} +WaveRestoreCursors {{Cursor 2} {23169 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -158,4 +161,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {1644110 ns} {15262484 ns} +WaveRestoreZoom {0 ns} {491274 ns} From 95dbc5f1fa59edf09b96384b52a441345310fc20 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 16:53:48 -0500 Subject: [PATCH 07/55] fixed a whole bunch of bugs with the branch predictor. Still an issue with how PCNextF is not updated because the CPU is stalled. --- wally-pipelined/regression/wave.do | 114 ++++++++++++++---------- wally-pipelined/src/ifu/BTBPredictor.sv | 2 +- wally-pipelined/src/ifu/bpred.sv | 8 +- wally-pipelined/src/ifu/gshare.sv | 21 ++++- wally-pipelined/src/ifu/ifu.sv | 2 +- 5 files changed, 92 insertions(+), 55 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 11029465..76c8b2f4 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -8,51 +8,70 @@ add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/fun add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD -add wave -noupdate -group Bpred -expand -group direction -divider Update -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group Bpred -group BTB -divider Update -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget -add wave -noupdate -group Bpred -group BTB -divider Lookup -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid -add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallE +add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallM +add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallW +add wave -noupdate -expand -group Bpred -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF +add wave -noupdate -expand -group Bpred -group direction -divider Lookup +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction +add wave -noupdate -expand -group Bpred -group direction -divider Update +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN +add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction +add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding +add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF +add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD +add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} -divider pcs +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE +add wave -noupdate -expand -group Bpred -expand -group BTB -divider Update +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -expand -group Bpred -expand -group BTB -divider Lookup +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid +add wave -noupdate -expand -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE @@ -120,6 +139,7 @@ add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALURe add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCNextF add wave -noupdate -expand -group PCS /testbench/dut/hart/PCF add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE @@ -145,7 +165,7 @@ add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/pri add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {23169 ns} 0} +WaveRestoreCursors {{Cursor 2} {5407 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -161,4 +181,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {0 ns} {491274 ns} +WaveRestoreZoom {5204 ns} {5476 ns} diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index d7848e4b..3e2557c7 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -91,7 +91,7 @@ module BTBPredictor .WA1(UpdatePCIndex), .WD1({UpdateInstrClass, UpdateTarget}), .WEN1(UpdateEN), - .BitWEN1({4'b0000, {`XLEN{1'b1}}})); // *** definitely not right. + .BitWEN1({4'b1111, {`XLEN{1'b1}}})); // *** definitely not right. endmodule diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index 38d95948..145f9946 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -74,7 +74,7 @@ module bpred .Prediction(BPPredF), // update .UpdatePC(PCE), - .UpdateEN(InstrClassE[0]), + .UpdateEN(InstrClassE[0] & ~StallE), .UpdatePrediction(UpdateBPPredE)); end else if (`BPTYPE == "BPGLOBAL") begin:Predictor @@ -86,7 +86,7 @@ module bpred .Prediction(BPPredF), // update .UpdatePC(PCE), - .UpdateEN(InstrClassE[0]), + .UpdateEN(InstrClassE[0] & ~StallE), .PCSrcE(PCSrcE), .UpdatePrediction(UpdateBPPredE)); end else if (`BPTYPE == "BPGSHARE") begin:Predictor @@ -98,7 +98,7 @@ module bpred .Prediction(BPPredF), // update .UpdatePC(PCE), - .UpdateEN(InstrClassE[0]), + .UpdateEN(InstrClassE[0] & ~StallE), .PCSrcE(PCSrcE), .UpdatePrediction(UpdateBPPredE)); end @@ -126,7 +126,7 @@ module bpred .InstrClass(BPInstrClassF), .Valid(BTBValidF), // update - .UpdateEN(InstrClassE[2] | InstrClassE[1] | InstrClassE[0]), + .UpdateEN((InstrClassE[2] | InstrClassE[1] | InstrClassE[0]) & ~StallE), .UpdatePC(PCE), .UpdateTarget(PCTargetE), .UpdateInstrClass(InstrClassE)); diff --git a/wally-pipelined/src/ifu/gshare.sv b/wally-pipelined/src/ifu/gshare.sv index a1c5bbc7..0f82b1da 100644 --- a/wally-pipelined/src/ifu/gshare.sv +++ b/wally-pipelined/src/ifu/gshare.sv @@ -43,7 +43,7 @@ module gsharePredictor ); logic [k-1:0] GHRF, GHRD, GHRE; - logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE; + //logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE; logic [k-1:0] LookUpPCIndex, UpdatePCIndex; logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF; @@ -66,7 +66,7 @@ module gsharePredictor .reset(reset), .RA1(LookUpPCIndex), .RD1(PredictionMemory), - .REN1(1'b1), + .REN1(~StallF), .WA1(UpdatePCIndex), .WD1(UpdatePrediction), .WEN1(UpdateEN), @@ -92,6 +92,7 @@ module gsharePredictor assign Prediction = DoForwardingF ? UpdatePredictionF : PredictionMemory; //pipeline for GHR +/* -----\/----- EXCLUDED -----\/----- flopenrc #(k) LookUpDReg(.clk(clk), .reset(reset), .en(~StallD), @@ -105,5 +106,21 @@ module gsharePredictor .clear(FlushE), .d(LookUpPCIndexD), .q(LookUpPCIndexE)); + -----/\----- EXCLUDED -----/\----- */ + + flopenrc #(k) GHRRegD(.clk(clk), + .reset(reset), + .en(~StallD), + .clear(FlushD), + .d(GHRF), + .q(GHRD)); + + flopenrc #(k) GHRRegE(.clk(clk), + .reset(reset), + .en(~StallE), + .clear(FlushE), + .d(GHRD), + .q(GHRE)); + endmodule diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index bad52a94..e8987564 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -122,7 +122,7 @@ module ifu ( .reset(reset), .StallF(StallF), .StallD(StallD), - .StallE(1'b0), // *** may need this eventually + .StallE(StallE), .FlushF(FlushF), .FlushD(FlushD), .FlushE(FlushE), From 49348d734b5d4ea314de1d7ce00e059e0200ae1e Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 20:06:45 -0500 Subject: [PATCH 08/55] fixed issue with BTB's valid bit not updating. There is still a problem is valid not ocurring in the correct clock cycle. --- wally-pipelined/regression/wave.do | 97 ++++++++++++++----------- wally-pipelined/src/ifu/BTBPredictor.sv | 26 +++++-- wally-pipelined/src/ifu/bpred.sv | 1 + 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 76c8b2f4..43baff54 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -38,21 +38,24 @@ add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbe add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallE add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallM add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallW -add wave -noupdate -expand -group Bpred -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF -add wave -noupdate -expand -group Bpred -group direction -divider Lookup -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction -add wave -noupdate -expand -group Bpred -group direction -divider Update -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN -add wave -noupdate -expand -group Bpred -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction -add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding -add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF -add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD -add wave -noupdate -expand -group Bpred -group direction -expand -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE +add wave -noupdate -expand -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF +add wave -noupdate -expand -group Bpred -expand -group direction -divider Lookup +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/BPPredF +add wave -noupdate -expand -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/BPPredPCF +add wave -noupdate -expand -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/SelBPPredF +add wave -noupdate -expand -group Bpred -expand -group direction -divider Update +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE @@ -62,11 +65,17 @@ add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut add wave -noupdate -expand -group Bpred -expand -group {bp wrong} -divider pcs add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/memory +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/WA1 +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/WEN1 +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/RA1 +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/RD1 add wave -noupdate -expand -group Bpred -expand -group BTB -divider Update add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ add wave -noupdate -expand -group Bpred -expand -group BTB -divider Lookup add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass @@ -91,31 +100,31 @@ add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/result -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/flags -add wave -noupdate -expand -group alu -divider internals -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/overflow -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/carry -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/zero -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rf +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/a +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/b +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/result +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/flags +add wave -noupdate -group alu -divider internals +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/overflow +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/carry +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/zero +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM @@ -145,6 +154,9 @@ add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE add wave -noupdate -expand -group PCS /testbench/dut/hart/PCM add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCW +add wave -noupdate -expand -group PCS -expand -group pcnextmux /testbench/dut/hart/ifu/PCNextF +add wave -noupdate -expand -group PCS -expand -group pcnextmux /testbench/dut/hart/ifu/PCNext0F +add wave -noupdate -expand -group PCS -expand -group pcnextmux /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr add wave -noupdate -group {function radix debug} -radix unsigned /testbench/functionRadix/function_radix/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/reset @@ -164,8 +176,9 @@ add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/pri add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW +add wave -noupdate /testbench/dut/hart/ifu/SelBPPredF TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {5407 ns} 0} +WaveRestoreCursors {{Cursor 2} {5208 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -181,4 +194,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {5204 ns} {5476 ns} +WaveRestoreZoom {4927 ns} {5489 ns} diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index 3e2557c7..9b459e61 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -33,6 +33,7 @@ module BTBPredictor ) (input logic clk, input logic reset, + input logic StallF, StallD, StallE, FlushF, FlushD, FlushE, input logic [`XLEN-1:0] LookUpPC, output logic [`XLEN-1:0] TargetPC, output logic [3:0] InstrClass, @@ -58,7 +59,7 @@ module BTBPredictor flopenr #(Depth) UpdatePCIndexReg(.clk(clk), .reset(reset), - .en(1'b1), + .en(~StallE), .d(UpdatePCIndex), .q(UpdatePCIndexQ)); @@ -66,18 +67,33 @@ module BTBPredictor always_ff @ (posedge clk) begin if (reset) begin ValidBits <= #1 {TotalDepth{1'b0}}; - end else if (UpdateEN) begin + end else + if (UpdateEN) begin ValidBits[UpdatePCIndexQ] <= #1 1'b1; end end + assign Valid = ValidBits[LookUpPCIndexQ]; + +/* -----\/----- EXCLUDED -----\/----- + + regfile2p1r1w #(10, 1) validMem(.clk(clk), + .reset(reset), + .RA1(LookUpPCIndexQ), + .RD1(Valid), + .REN1(1'b1), + .WA1(UpdatePCIndexQ), + .WD1(1'b1), + .WEN1(UpdateEN)); + -----/\----- EXCLUDED -----/\----- */ + flopenr #(Depth) LookupPCIndexReg(.clk(clk), .reset(reset), - .en(1'b1), + .en(~StallF), .d(LookUpPCIndex), .q(LookUpPCIndexQ)); - assign Valid = ValidBits[LookUpPCIndexQ]; + // the BTB contains the target address. // Another optimization may be using a PC relative address. @@ -87,7 +103,7 @@ module BTBPredictor .reset(reset), .RA1(LookUpPCIndex), .RD1({{InstrClass, TargetPC}}), - .REN1(1'b1), + .REN1(~StallF), .WA1(UpdatePCIndex), .WD1({UpdateInstrClass, UpdateTarget}), .WEN1(UpdateEN), diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index 145f9946..b0b902c8 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -121,6 +121,7 @@ module bpred BTBPredictor TargetPredictor(.clk(clk), .reset(reset), + .*, // Stalls and flushes .LookUpPC(PCNextF), .TargetPC(BTBPredPCF), .InstrClass(BPInstrClassF), From 4fb7a1e0a62825c0cef51732d66b80e406f4b3da Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 20:20:23 -0500 Subject: [PATCH 09/55] Fixed the valid bit issue. Now the branch predictor is actually predicting instructions. --- wally-pipelined/src/ifu/BTBPredictor.sv | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index 9b459e61..104d8dc7 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -48,6 +48,8 @@ module BTBPredictor localparam TotalDepth = 2 ** Depth; logic [TotalDepth-1:0] ValidBits; logic [Depth-1:0] LookUpPCIndex, UpdatePCIndex, LookUpPCIndexQ, UpdatePCIndexQ; + logic UpdateENQ; + // hashing function for indexing the PC // We have Depth bits to index, but XLEN bits as the input. @@ -68,7 +70,7 @@ module BTBPredictor if (reset) begin ValidBits <= #1 {TotalDepth{1'b0}}; end else - if (UpdateEN) begin + if (UpdateENQ) begin ValidBits[UpdatePCIndexQ] <= #1 1'b1; end end @@ -86,6 +88,12 @@ module BTBPredictor .WEN1(UpdateEN)); -----/\----- EXCLUDED -----/\----- */ + flopenr #() UpdateENReg(.clk(clk), + .reset(reset), + .en(~StallF), + .d(UpdateEN), + .q(UpdateENQ)); + flopenr #(Depth) LookupPCIndexReg(.clk(clk), .reset(reset), From 84ad1353e4461fd5a8cffd08794a20c975e1d629 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 21:49:16 -0500 Subject: [PATCH 10/55] Fixed a bunch of bugs with the RAS. --- wally-pipelined/regression/wave.do | 94 +++++++++++++------------ wally-pipelined/src/ifu/BTBPredictor.sv | 5 +- wally-pipelined/src/ifu/RAsPredictor.sv | 6 +- wally-pipelined/src/ifu/bpred.sv | 13 ++-- wally-pipelined/src/ifu/gshare.sv | 8 ++- 5 files changed, 68 insertions(+), 58 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 43baff54..58dd4405 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -8,36 +8,36 @@ add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/fun add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD -add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallE -add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallM -add wave -noupdate -expand -group HDU -expand -group Stall /testbench/dut/hart/ifu/StallW +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW add wave -noupdate -expand -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF add wave -noupdate -expand -group Bpred -expand -group direction -divider Lookup add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC @@ -56,20 +56,15 @@ add wave -noupdate -expand -group Bpred -expand -group direction -group other /t add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} -divider pcs -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD -add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/memory -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/WA1 -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/WEN1 -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/RA1 -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/validMem/RD1 +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -expand -group Bpred -group {bp wrong} -divider pcs +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD +add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE add wave -noupdate -expand -group Bpred -expand -group BTB -divider Update add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC @@ -81,6 +76,13 @@ add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/i add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid add wave -noupdate -expand -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ +add wave -noupdate -expand -group Bpred -expand -group RAS -expand /testbench/dut/hart/ifu/bpred/RASPredictor/memory +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE @@ -178,7 +180,7 @@ add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/pri add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW add wave -noupdate /testbench/dut/hart/ifu/SelBPPredF TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {5208 ns} 0} +WaveRestoreCursors {{Cursor 6} {12508605 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -194,4 +196,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {4927 ns} {5489 ns} +WaveRestoreZoom {0 ns} {16338232 ns} diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index 104d8dc7..f9d84dee 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -42,7 +42,8 @@ module BTBPredictor input logic UpdateEN, input logic [`XLEN-1:0] UpdatePC, input logic [`XLEN-1:0] UpdateTarget, - input logic [3:0] UpdateInstrClass + input logic [3:0] UpdateInstrClass, + input logic UpdateInvalid ); localparam TotalDepth = 2 ** Depth; @@ -71,7 +72,7 @@ module BTBPredictor ValidBits <= #1 {TotalDepth{1'b0}}; end else if (UpdateENQ) begin - ValidBits[UpdatePCIndexQ] <= #1 1'b1; + ValidBits[UpdatePCIndexQ] <= #1 ~ UpdateInvalid; end end assign Valid = ValidBits[LookUpPCIndexQ]; diff --git a/wally-pipelined/src/ifu/RAsPredictor.sv b/wally-pipelined/src/ifu/RAsPredictor.sv index 9090878d..3b975e91 100644 --- a/wally-pipelined/src/ifu/RAsPredictor.sv +++ b/wally-pipelined/src/ifu/RAsPredictor.sv @@ -42,9 +42,9 @@ module RASPredictor logic CounterEn; localparam Depth = $clog2(StackSize); - logic [StackSize-1:0] PtrD, PtrQ, PtrP1, PtrM1; - logic [StackSize-1:0] [`XLEN-1:0] memory; - integer index; + logic [Depth-1:0] PtrD, PtrQ, PtrP1, PtrM1; + logic [Depth-1:0] [`XLEN-1:0] memory; + integer index; assign CounterEn = pop | push | incr; diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index b0b902c8..a96d4353 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -61,6 +61,8 @@ module bpred logic FallThroughWrongE; logic PredictionDirWrongE; logic PredictionPCWrongE; + logic PredictionInstrClassWrongE; + logic [`XLEN-1:0] CorrectPCE; @@ -119,6 +121,7 @@ module bpred // Part 2 Branch target address prediction // *** For now the BTB will house the direct and indirect targets + // *** getting to many false positivies from the BTB, we need a partial TAG to reduce this. BTBPredictor TargetPredictor(.clk(clk), .reset(reset), .*, // Stalls and flushes @@ -127,9 +130,10 @@ module bpred .InstrClass(BPInstrClassF), .Valid(BTBValidF), // update - .UpdateEN((InstrClassE[2] | InstrClassE[1] | InstrClassE[0]) & ~StallE), + .UpdateEN((|InstrClassE | (PredictionInstrClassWrongE)) & ~StallE), .UpdatePC(PCE), .UpdateTarget(PCTargetE), + .UpdateInvalid(PredictionInstrClassWrongE), .UpdateInstrClass(InstrClassE)); // need to forward when updating to the same address as reading. @@ -140,9 +144,9 @@ module bpred // *** need to add the logic to restore RAS on flushes. We will use incr for this. RASPredictor RASPredictor(.clk(clk), .reset(reset), - .pop(BPInstrClassF[3]), + .pop(BPInstrClassF[3] & ~StallF), .popPC(RASPCF), - .push(InstrClassE[3]), + .push(InstrClassE[3] & ~StallE), .incr(1'b0), .pushPC(PCLinkE)); @@ -189,7 +193,8 @@ module bpred assign FallThroughWrongE = PCLinkE != PCD; assign PredictionDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0]; assign PredictionPCWrongE = PCSrcE ? TargetWrongE : FallThroughWrongE; - assign BPPredWrongE = (PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE); + assign PredictionInstrClassWrongE = InstrClassE != BPInstrClassE; + assign BPPredWrongE = ((PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE)) | PredictionInstrClassWrongE; // Update predictors diff --git a/wally-pipelined/src/ifu/gshare.sv b/wally-pipelined/src/ifu/gshare.sv index 0f82b1da..8af54145 100644 --- a/wally-pipelined/src/ifu/gshare.sv +++ b/wally-pipelined/src/ifu/gshare.sv @@ -42,22 +42,24 @@ module gsharePredictor ); - logic [k-1:0] GHRF, GHRD, GHRE; + logic [k-1:0] GHRF, GHRD, GHRE, GHRENext; //logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE; logic [k-1:0] LookUpPCIndex, UpdatePCIndex; logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF; logic [1:0] UpdatePredictionF; + + assign GHRENext = {PCSrcE, GHRE[k-1:1]}; flopenr #(k) GlobalHistoryRegister(.clk(clk), .reset(reset), .en(UpdateEN), - .d({PCSrcE, GHRF[k-1:1] }), + .d(GHRENext), .q(GHRF)); // for gshare xor the PC with the GHR - assign UpdatePCIndex = GHRE ^ UpdatePC[k:1]; + assign UpdatePCIndex = GHRENext ^ UpdatePC[k:1]; assign LookUpPCIndex = GHRF ^ LookUpPC[k:1]; // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT // GHR referes to the address that the past k branches points to in the prediction stage From 1c6e37120ed4cd74570c3b7563e34d34e5a16695 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 23 Mar 2021 23:00:44 -0500 Subject: [PATCH 11/55] Fixed RAS errors. Still some room for improvement with the BTB and RAS. --- wally-pipelined/regression/wave.do | 92 +++++++++++++------------ wally-pipelined/src/ifu/RAsPredictor.sv | 6 +- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 58dd4405..e2c35517 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -8,36 +8,36 @@ add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/fun add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW add wave -noupdate -expand -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF add wave -noupdate -expand -group Bpred -expand -group direction -divider Lookup add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC @@ -81,12 +81,12 @@ add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/i add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ -add wave -noupdate -expand -group Bpred -expand -group RAS -expand /testbench/dut/hart/ifu/bpred/RASPredictor/memory +add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC -add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF -add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM +add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF +add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE +add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNextF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCPlus2or4F @@ -128,10 +128,10 @@ add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM -add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM +add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM +add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM +add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E @@ -174,13 +174,15 @@ add wave -noupdate -group {function radix debug} /testbench/functionRadix/functi add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/HPMCOUNTER -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/HPMCOUNTER +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW add wave -noupdate /testbench/dut/hart/ifu/SelBPPredF +add wave -noupdate /testbench/dut/hart/ifu/bpred/BPInstrClassF +add wave -noupdate /testbench/dut/hart/ifu/bpred/StallF TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 6} {12508605 ns} 0} +WaveRestoreCursors {{Cursor 7} {2193752 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -196,4 +198,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {0 ns} {16338232 ns} +WaveRestoreZoom {0 ns} {16331317 ns} diff --git a/wally-pipelined/src/ifu/RAsPredictor.sv b/wally-pipelined/src/ifu/RAsPredictor.sv index 3b975e91..166ff911 100644 --- a/wally-pipelined/src/ifu/RAsPredictor.sv +++ b/wally-pipelined/src/ifu/RAsPredictor.sv @@ -42,9 +42,9 @@ module RASPredictor logic CounterEn; localparam Depth = $clog2(StackSize); - logic [Depth-1:0] PtrD, PtrQ, PtrP1, PtrM1; - logic [Depth-1:0] [`XLEN-1:0] memory; - integer index; + logic [Depth-1:0] PtrD, PtrQ, PtrP1, PtrM1; + logic [StackSize-1:0] [`XLEN-1:0] memory; + integer index; assign CounterEn = pop | push | incr; From efa8ad4e1771faffe4672a73741c8722abc208f7 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 24 Mar 2021 09:22:21 -0500 Subject: [PATCH 12/55] Edited sieve to work with wally. It was using the time of day to compute runspeed; however this functionality does not yet work in the wally software stack. --- testsBP/sieve/sieve.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/testsBP/sieve/sieve.c b/testsBP/sieve/sieve.c index 949d9fde..e8207404 100644 --- a/testsBP/sieve/sieve.c +++ b/testsBP/sieve/sieve.c @@ -61,26 +61,26 @@ int main () { int ans; - struct timeval before , after; - gettimeofday(&before , NULL); + //struct timeval before , after; + //gettimeofday(&before , NULL); ans = sieve (); - gettimeofday(&after , NULL); + //gettimeofday(&after , NULL); if (ans != 1899) printf ("Sieve result wrong, ans = %d, expected 1899", ans); - printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); + //printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); printf("Round 2\n"); - gettimeofday(&before , NULL); + //gettimeofday(&before , NULL); ans = sieve (); - gettimeofday(&after , NULL); + //gettimeofday(&after , NULL); if (ans != 1899) printf ("Sieve result wrong, ans = %d, expected 1899", ans); - printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); + //printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); return 0; From d74b6eb69c3daa2eda9b7b684e1873af721d1f21 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 24 Mar 2021 10:30:19 -0500 Subject: [PATCH 13/55] Updated the .gitignore to reject all the extra compiled objects for the branchmarks. --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 8692d6bc..fd480fa5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,9 @@ wlft* /imperas-riscv-tests/FunctionRadix_32.addr /imperas-riscv-tests/FunctionRadix_64.addr /imperas-riscv-tests/ProgramMap.txt +*.o +*.d +testsBP/*/*/*.elf* +testsBP/*/OBJ/* +testsBP/*/*.a + From 11109e5a885e1866b698ed62347c4084551406c8 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 24 Mar 2021 13:03:43 -0500 Subject: [PATCH 14/55] Updated the function radix to have a new name FunctionName and it now pervents false transisions from the current function name when the PCD is flushed. --- wally-pipelined/regression/wave.do | 214 +++++++++--------- wally-pipelined/testbench/function_radix.sv | 29 ++- .../testbench/testbench-imperas.sv | 9 +- 3 files changed, 130 insertions(+), 122 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index e2c35517..3ab0f95c 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -4,85 +4,85 @@ add wave -noupdate /testbench/clk add wave -noupdate /testbench/reset add wave -noupdate /testbench/test add wave -noupdate -radix ascii /testbench/memfilename -add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/function_radix/FunctionName +add wave -noupdate -expand -group {Execution Stage} /testbench/FunctionName/FunctionName/FunctionName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM -add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW -add wave -noupdate -expand -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF -add wave -noupdate -expand -group Bpred -expand -group direction -divider Lookup -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/BPPredF -add wave -noupdate -expand -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/BPPredPCF -add wave -noupdate -expand -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/SelBPPredF -add wave -noupdate -expand -group Bpred -expand -group direction -divider Update -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN -add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction -add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding -add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF -add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD -add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -expand -group Bpred -group {bp wrong} -divider pcs -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD -add wave -noupdate -expand -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE -add wave -noupdate -expand -group Bpred -expand -group BTB -divider Update -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ -add wave -noupdate -expand -group Bpred -expand -group BTB -divider Lookup -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass -add wave -noupdate -expand -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid -add wave -noupdate -expand -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory -add wave -noupdate -expand -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM +add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW +add wave -noupdate -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF +add wave -noupdate -group Bpred -expand -group direction -divider Lookup +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/BPPredF +add wave -noupdate -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/BPPredPCF +add wave -noupdate -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/SelBPPredF +add wave -noupdate -group Bpred -expand -group direction -divider Update +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -group Bpred -group {bp wrong} -divider pcs +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE +add wave -noupdate -group Bpred -expand -group BTB -divider Update +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ +add wave -noupdate -group Bpred -expand -group BTB -divider Lookup +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid +add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE @@ -150,39 +150,35 @@ add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALURe add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM -add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCNextF -add wave -noupdate -expand -group PCS /testbench/dut/hart/PCF -add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD -add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE -add wave -noupdate -expand -group PCS /testbench/dut/hart/PCM -add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCW -add wave -noupdate -expand -group PCS -expand -group pcnextmux /testbench/dut/hart/ifu/PCNextF -add wave -noupdate -expand -group PCS -expand -group pcnextmux /testbench/dut/hart/ifu/PCNext0F -add wave -noupdate -expand -group PCS -expand -group pcnextmux /testbench/dut/hart/ifu/PCNext1F -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr -add wave -noupdate -group {function radix debug} -radix unsigned /testbench/functionRadix/function_radix/ProgramAddrIndex -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/reset -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapLineCount -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapLine -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapFP -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapFile -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapLineCount -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapLine -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapFP -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapFile -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/pc -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName -add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/HPMCOUNTER -add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH -add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN -add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW -add wave -noupdate /testbench/dut/hart/ifu/SelBPPredF -add wave -noupdate /testbench/dut/hart/ifu/bpred/BPInstrClassF -add wave -noupdate /testbench/dut/hart/ifu/bpred/StallF +add wave -noupdate -group PCS /testbench/dut/hart/ifu/PCNextF +add wave -noupdate -group PCS /testbench/dut/hart/PCF +add wave -noupdate -group PCS /testbench/dut/hart/ifu/PCD +add wave -noupdate -group PCS /testbench/dut/hart/PCE +add wave -noupdate -group PCS /testbench/dut/hart/PCM +add wave -noupdate -group PCS /testbench/dut/hart/ifu/PCW +add wave -noupdate -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNextF +add wave -noupdate -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNext0F +add wave -noupdate -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNext1F +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr +add wave -noupdate -group {function radix debug} -radix unsigned /testbench/FunctionName/FunctionName/ProgramAddrIndex +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/reset +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapLineCount +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapLine +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapFP +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapFile +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapLineCount +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapLine +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapFP +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapFile +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrIndex +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionName +add wave -noupdate -expand -group {performance counters} -expand /testbench/dut/hart/priv/csr/genblk1/counters/HPMCOUNTER +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 7} {2193752 ns} 0} +WaveRestoreCursors {{Cursor 7} {8084 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -198,4 +194,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {0 ns} {16331317 ns} +WaveRestoreZoom {6397 ns} {21325 ns} diff --git a/wally-pipelined/testbench/function_radix.sv b/wally-pipelined/testbench/function_radix.sv index e6bd479f..20e2ff13 100644 --- a/wally-pipelined/testbench/function_radix.sv +++ b/wally-pipelined/testbench/function_radix.sv @@ -27,9 +27,10 @@ `include "wally-config.vh" -module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); +module FunctionName(reset, clk, ProgramAddrMapFile, ProgramLabelMapFile); input logic reset; + input logic clk; input string ProgramAddrMapFile; input string ProgramLabelMapFile; @@ -38,13 +39,23 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); string FunctionName; - logic [`XLEN-1:0] pc, FunctionAddr; + logic [`XLEN-1:0] PCF, PCD, PCE, FunctionAddr; + logic StallD, StallE, FlushD, FlushE; integer ProgramAddrIndex; - // *** I should look into the system verilog objects instead of signal spy. - initial begin - $init_signal_spy("/testbench/dut/hart/PCE", "/testbench/functionRadix/function_radix/pc"); - end + assign PCF = testbench.dut.hart.PCF; + assign StallD = testbench.dut.hart.StallD; + assign StallE = testbench.dut.hart.StallE; + assign FlushD = testbench.dut.hart.FlushD; + assign FlushE = testbench.dut.hart.FlushE; + + // copy from ifu + // when the F and D stages are flushed we need to ensure the PCE is held so that the function name does not + // erroneously change. + flopenrc #(`XLEN) PCDReg(clk, reset, 1'b0, ~StallD, FlushE & FlushD ? PCE : PCF, PCD); + flopenr #(`XLEN) PCEReg(clk, reset, ~StallE, FlushE ? PCE : PCD, PCE); + + task automatic bin_search_min; input logic [`XLEN-1:0] pc; @@ -74,7 +85,7 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); end else if( array[mid] > pc) begin right = mid -1; end else begin - $display("Critical Error in function radix. PC, %x not found.", pc); + $display("Critical Error in FunctionName. PC, %x not found.", pc); return; //$stop(); end @@ -141,8 +152,8 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); end - always @(pc) begin - bin_search_min(pc, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex); + always @(PCE) begin + bin_search_min(PCE, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex); end diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 4627cff3..c9c5919a 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -476,10 +476,11 @@ string tests32i[] = { end // always @ (negedge clk) // track the current function or global label - if (DEBUG == 1) begin : functionRadix - function_radix function_radix(.reset(reset), - .ProgramAddrMapFile(ProgramAddrMapFile), - .ProgramLabelMapFile(ProgramLabelMapFile)); + if (DEBUG == 1) begin : FunctionName + FunctionName FunctionName(.reset(reset), + .clk(clk), + .ProgramAddrMapFile(ProgramAddrMapFile), + .ProgramLabelMapFile(ProgramLabelMapFile)); end // initialize the branch predictor From a99c0502e59461979133c36efeb2fef9d85261d0 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 24 Mar 2021 15:56:55 -0500 Subject: [PATCH 15/55] Fixed bugs with the csr interacting with StallW. StallW is required to pervent updating a csr. Now have a working branch predictor and performance counters to track the number of commited branches and mispredictions. --- testsBP/simple/sample.s | 19 ++- wally-pipelined/regression/wave.do | 141 ++++++++++--------- wally-pipelined/src/ieu/datapath.sv | 3 - wally-pipelined/src/privileged/csr.sv | 2 +- wally-pipelined/src/privileged/csrc.sv | 17 +-- wally-pipelined/src/privileged/csri.sv | 9 +- wally-pipelined/src/privileged/csrm.sv | 27 ++-- wally-pipelined/src/privileged/csrn.sv | 13 +- wally-pipelined/src/privileged/csrs.sv | 17 +-- wally-pipelined/src/privileged/csru.sv | 9 +- wally-pipelined/src/privileged/privileged.sv | 2 +- 11 files changed, 137 insertions(+), 122 deletions(-) diff --git a/testsBP/simple/sample.s b/testsBP/simple/sample.s index 399d3bd7..1c707cba 100644 --- a/testsBP/simple/sample.s +++ b/testsBP/simple/sample.s @@ -7,7 +7,13 @@ simple_csrbr_test: # step 1 enable the performance counters # by default the hardware enables all performance counters # however we will eventually want to manually enable incase - # some other code disables thems + # some other code disables them + + # br count is counter 5 + # br mp count is counter 4 + li t0, 0x30 + + csrrc x0, 0x320, t0 # clear bits 4 and 5 of inhibit register. # step 2 read performance counters into general purpose registers @@ -35,17 +41,20 @@ loop_done: sub t3, t5, t3 # this is the number of branch mispredictions committed. # now check if the branch count equals 100 and if the branch - bne t4, t2, fail - # *** come back to t3 - + bne t4, t2, fail + li t5, 3 + bne t3, t5, fail pass: li a0, 0 +done: + li t0, 0x30 + csrrs x0, 0x320, t0 # set bits 4 and 5 ret fail: li a0, -1 - ret + j done .data sample_data: diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 3ab0f95c..ede2da62 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -8,36 +8,36 @@ add wave -noupdate -expand -group {Execution Stage} /testbench/FunctionName/Func add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -group HDU -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW add wave -noupdate -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF add wave -noupdate -group Bpred -expand -group direction -divider Lookup add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC @@ -83,10 +83,10 @@ add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE +add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNextF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCPlus2or4F @@ -96,37 +96,37 @@ add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -group {Decode Stage} /testbench/InstrDName -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rf -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/a -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/b -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/result -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/flags -add wave -noupdate -group alu -divider internals -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/overflow -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/carry -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/zero -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -expand -group {Decode Stage} /testbench/InstrDName +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/result +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/flags +add wave -noupdate -expand -group alu -divider internals +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/overflow +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/carry +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/zero +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM @@ -173,12 +173,15 @@ add wave -noupdate -group {function radix debug} /testbench/FunctionName/Functio add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionName -add wave -noupdate -expand -group {performance counters} -expand /testbench/dut/hart/priv/csr/genblk1/counters/HPMCOUNTER -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MHPMCOUNTERH add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/genblk1/HPMCOUNTER_REGW +add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate /testbench/dut/hart/priv/csr/genblk1/counters/CSRCReadValM TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 7} {8084 ns} 0} +WaveRestoreCursors {{Cursor 7} {13518 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -194,4 +197,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {6397 ns} {21325 ns} +WaveRestoreZoom {13489 ns} {13607 ns} diff --git a/wally-pipelined/src/ieu/datapath.sv b/wally-pipelined/src/ieu/datapath.sv index adcd4f6d..f94e665e 100644 --- a/wally-pipelined/src/ieu/datapath.sv +++ b/wally-pipelined/src/ieu/datapath.sv @@ -115,9 +115,6 @@ module datapath ( flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW); flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW); - // *** something is not right here. Before the merge I found an issue with the jal instruction not writing - // the link address through the alu. - // not sure what changed. // handle Store Conditional result if atomic extension supported generate if (`A_SUPPORTED) diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index 0c38b688..79e81303 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -28,7 +28,7 @@ module csr ( input logic clk, reset, - input logic FlushW, StallW, + input logic FlushW, StallD, StallE, StallM, StallW, input logic [31:0] InstrM, input logic [`XLEN-1:0] PCM, SrcAM, input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM, diff --git a/wally-pipelined/src/privileged/csrc.sv b/wally-pipelined/src/privileged/csrc.sv index dbf21e91..ba90a48a 100644 --- a/wally-pipelined/src/privileged/csrc.sv +++ b/wally-pipelined/src/privileged/csrc.sv @@ -29,8 +29,9 @@ module csrc ( input logic clk, reset, + input logic StallD, StallE, StallM, StallW, input logic InstrValidW, LoadStallD, CSRMWriteM, BPPredWrongM, - input logic [3:0] InstrClassM, + input logic [3:0] InstrClassM, input logic [11:0] CSRAdrM, input logic [1:0] PrivilegeModeW, input logic [`XLEN-1:0] CSRWriteValM, @@ -61,10 +62,10 @@ module csrc ( logic [`COUNTERS:0] MCOUNTEN; assign MCOUNTEN[0] = 1'b1; assign MCOUNTEN[1] = 1'b0; - assign MCOUNTEN[2] = InstrValidW; - assign MCOUNTEN[3] = LoadStallD; - assign MCOUNTEN[4] = BPPredWrongM; - assign MCOUNTEN[5] = InstrClassM[0]; + assign MCOUNTEN[2] = InstrValidW & ~StallW; + assign MCOUNTEN[3] = LoadStallD & ~StallD; + assign MCOUNTEN[4] = BPPredWrongM & ~StallM; + assign MCOUNTEN[5] = InstrClassM[0] & ~StallM; assign MCOUNTEN[`COUNTERS:6] = 0; genvar j; @@ -91,7 +92,7 @@ module csrc ( // Write / update counters // Only the Machine mode versions of the counter CSRs are writable if (`XLEN==64) begin // 64-bit counters - flopr #(64) HPMCOUNTERreg_j(clk, reset, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j]); + flopenr #(64) HPMCOUNTERreg_j(clk, reset, ~StallW, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j]); end else begin // 32-bit low and high counters logic [`COUNTERS:0] WriteHPMCOUNTERHM; @@ -102,8 +103,8 @@ module csrc ( assign NextHPMCOUNTERHM[j] = WriteHPMCOUNTERHM[j] ? CSRWriteValM : HPMCOUNTERPlusM[j][63:32]; // Counter CSRs - flopr #(32) HPMCOUNTERreg_j(clk, reset, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j][31:0]); - flopr #(32) HPMCOUNTERHreg_j(clk, reset, NextHPMCOUNTERHM[j], HPMCOUNTER_REGW[j][63:32]); + flopenr #(32) HPMCOUNTERreg_j(clk, reset, ~StallW, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j][31:0]); + flopenr #(32) HPMCOUNTERHreg_j(clk, reset, ~StallW, NextHPMCOUNTERHM[j], HPMCOUNTER_REGW[j][63:32]); end end // end for diff --git a/wally-pipelined/src/privileged/csri.sv b/wally-pipelined/src/privileged/csri.sv index ee84c222..55e11b6e 100644 --- a/wally-pipelined/src/privileged/csri.sv +++ b/wally-pipelined/src/privileged/csri.sv @@ -33,6 +33,7 @@ module csri #(parameter SIE = 12'h104, SIP = 12'h144) ( input logic clk, reset, + input logic StallW, input logic CSRMWriteM, CSRSWriteM, input logic [11:0] CSRAdrM, input logic ExtIntM, TimerIntM, SwIntM, @@ -59,10 +60,10 @@ module csri #(parameter end // Interrupt Write Enables - assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP); - assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE); - assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP); - assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE); + assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP) && ~StallW; + assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE) && ~StallW; + assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP) && ~StallW; + assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE) && ~StallW; // Interrupt Pending and Enable Registers // MEIP, MTIP, MSIP are read-only diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index 44a840dd..dc990c2e 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -62,6 +62,7 @@ module csrm #(parameter DSCRATCH0 = 12'h7B2, DSCRATCH1 = 12'h7B3) ( input logic clk, reset, + input logic StallW, input logic CSRMWriteM, MTrapM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW, @@ -93,19 +94,19 @@ module csrm #(parameter assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISAbits}; // Write machine Mode CSRs - assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS); - assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC); - assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG); - assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG); - assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH); - assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)); - assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)); - assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)); - assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)); - assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)); - assign WritePMPADDR0M = (CSRMWriteM && (CSRAdrM == PMPADDR0)); - assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN); - assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT); + assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS) && ~StallW; + assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC) && ~StallW; + assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG) && ~StallW; + assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG) && ~StallW; + assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH) && ~StallW; + assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)) && ~StallW; + assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)) && ~StallW; + assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)) && ~StallW; + assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)) && ~StallW; + assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)) && ~StallW; + assign WritePMPADDR0M = (CSRMWriteM && (CSRAdrM == PMPADDR0)) && ~StallW; + assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN) && ~StallW; + assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT) && ~StallW; // CSRs flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, `XLEN'b0, MTVEC_REGW); //busybear: changed reset value to 0 diff --git a/wally-pipelined/src/privileged/csrn.sv b/wally-pipelined/src/privileged/csrn.sv index a3b3178b..2aa44bdf 100644 --- a/wally-pipelined/src/privileged/csrn.sv +++ b/wally-pipelined/src/privileged/csrn.sv @@ -36,6 +36,7 @@ module csrn #(parameter UTVAL = 12'h043, UIP = 12'h044) ( input logic clk, reset, + input logic StallW, input logic CSRNWriteM, UTrapM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, USTATUS_REGW, @@ -56,11 +57,11 @@ module csrn #(parameter logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW; // Write enables - assign WriteUSTATUSM = CSRNWriteM && (CSRAdrM == USTATUS); - assign WriteUTVECM = CSRNWriteM && (CSRAdrM == UTVEC); - assign WriteUEPCM = UTrapM | (CSRNWriteM && (CSRAdrM == UEPC)); - assign WriteUCAUSEM = UTrapM | (CSRNWriteM && (CSRAdrM == UCAUSE)); - assign WriteUTVALM = UTrapM | (CSRNWriteM && (CSRAdrM == UTVAL)); + assign WriteUSTATUSM = CSRNWriteM && (CSRAdrM == USTATUS) && ~StallW; + assign WriteUTVECM = CSRNWriteM && (CSRAdrM == UTVEC) && ~StallW; + assign WriteUEPCM = UTrapM | (CSRNWriteM && (CSRAdrM == UEPC)) && ~StallW; + assign WriteUCAUSEM = UTrapM | (CSRNWriteM && (CSRAdrM == UCAUSE)) && ~StallW; + assign WriteUTVALM = UTrapM | (CSRNWriteM && (CSRAdrM == UTVAL)) && ~StallW; // CSRs flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, CSRWriteValM, `RESET_VECTOR, UTVEC_REGW); @@ -95,4 +96,4 @@ module csrn #(parameter assign IllegalCSRNAccessM = 1; end endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/wally-pipelined/src/privileged/csrs.sv b/wally-pipelined/src/privileged/csrs.sv index ede8274a..c53f98d5 100644 --- a/wally-pipelined/src/privileged/csrs.sv +++ b/wally-pipelined/src/privileged/csrs.sv @@ -41,6 +41,7 @@ module csrs #(parameter SIP= 12'h144, SATP = 12'h180) ( input logic clk, reset, + input logic StallW, input logic CSRSWriteM, STrapM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW, @@ -66,14 +67,14 @@ module csrs #(parameter logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW; - assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS); - assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC); - assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH); - assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC)); - assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE)); - assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL)); - assign WriteSATPM = STrapM | (CSRSWriteM && (CSRAdrM == SATP)); - assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN); + assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW; + assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW; + assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH) && ~StallW; + assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC)) && ~StallW; + assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE)) && ~StallW; + assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL)) && ~StallW; + assign WriteSATPM = STrapM | (CSRSWriteM && (CSRAdrM == SATP)) && ~StallW; + assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW; // CSRs flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, zero, STVEC_REGW); //busybear: change reset to 0 diff --git a/wally-pipelined/src/privileged/csru.sv b/wally-pipelined/src/privileged/csru.sv index 0fad64bf..ad309594 100644 --- a/wally-pipelined/src/privileged/csru.sv +++ b/wally-pipelined/src/privileged/csru.sv @@ -32,6 +32,7 @@ module csru #(parameter FRM = 12'h002, FCSR = 12'h003) ( input logic clk, reset, + input logic StallW, input logic CSRUWriteM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] CSRWriteValM, @@ -50,9 +51,9 @@ module csru #(parameter logic [4:0] NextFFLAGSM; // Write enables - assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR); - assign WriteFFLAGSM = CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM ; - assign WriteFRMM = CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM; + assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR) && ~StallW; + assign WriteFFLAGSM = (CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM) && ~StallW; + assign WriteFRMM = (CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM) && ~StallW; // Write Values assign NextFRMM = WriteFCSRM ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; @@ -81,4 +82,4 @@ module csru #(parameter assign IllegalCSRUAccessM = 1; end endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 8a6854e9..f863b7fa 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -48,7 +48,7 @@ module privileged ( output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, output logic [2:0] FRM_REGW, - input logic FlushD, FlushE, FlushM, StallD, StallW + input logic FlushD, FlushE, FlushM, StallD, StallE, StallM, StallW ); logic [1:0] NextPrivilegeModeM; From ebd6b931c6a64b7c8b6636d9a7601d1067d85bbf Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 24 Mar 2021 13:39:45 -0400 Subject: [PATCH 16/55] Fix bug in cache line --- wally-pipelined/src/cache/line.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wally-pipelined/src/cache/line.sv b/wally-pipelined/src/cache/line.sv index e498d073..6fe848e5 100644 --- a/wally-pipelined/src/cache/line.sv +++ b/wally-pipelined/src/cache/line.sv @@ -62,7 +62,7 @@ module rocacheline #(parameter LINESIZE = 256, parameter TAGSIZE = 32, parameter always_comb begin - assign DataWord = DataLinesOut[WordSelect[OFFSETSIZE-1:$clog2(WORDSIZE)]]; + assign DataWord = DataLinesOut[WordSelect[OFFSETSIZE-1:$clog2(WORDSIZE/8)]]; end endmodule From ad0d77e9e1ca92449c13b7dd9bc4d3575e43258a Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 24 Mar 2021 13:40:08 -0400 Subject: [PATCH 17/55] Begin rewrite of icache module to use a direct-mapped scheme --- wally-pipelined/src/ifu/icache.sv | 147 ++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 4208c355..17c8bf1e 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -48,6 +48,153 @@ module icache( output logic [31:0] InstrRawD ); + // Configuration parameters + // TODO Move these to a config file + localparam integer ICACHELINESIZE = 256; + localparam integer ICACHENUMLINES = 512; + + // Input signals to cache memory + logic FlushMem; + logic [`XLEN-1:12] ICacheMemReadUpperPAdr; + logic [11:0] ICacheMemReadLowerAdr; + logic ICacheMemWriteEnable; + logic [ICACHELINESIZE-1:0] ICacheMemWriteData; + logic [`XLEN-1:0] ICacheMemWritePAdr; + // Output signals from cache memory + logic [`XLEN-1:0] ICacheMemReadData; + logic ICacheMemReadValid; + + rodirectmappedmem #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES)) cachemem( + .*, + .flush(FlushMem), + .ReadUpperPAdr(ICacheMemReadUpperPAdr), + .ReadLowerAdr(ICacheMemReadLowerAdr), + .WriteEnable(ICacheMemWriteEnable), + .WriteLine(ICacheMemWriteData), + .WritePAdr(ICacheMemWritePAdr), + .DataWord(ICacheMemReadData), + .DataValid(ICacheMemReadValid) + ); + + icachecontroller #(.LINESIZE(ICACHELINESIZE)) controller(.*); +endmodule + +module icachecontroller #(parameter LINESIZE = 256) ( + // Inputs from pipeline + input logic clk, reset, + input logic StallF, StallD, + input logic FlushD, + + // Input the address to read + // The upper bits of the physical pc + input logic [`XLEN-1:12] UpperPCPF, + // The lower bits of the virtual pc + input logic [11:0] LowerPCF, + + // Signals to/from cache memory + // The read coming out of it + input logic [`XLEN-1:0] ICacheMemReadData, + input logic ICacheMemReadValid, + // The address at which we want to search the cache memory + output logic [`XLEN-1:12] ICacheMemReadUpperPAdr, + output logic [11:0] ICacheMemReadLowerAdr, + // Load data into the cache + output logic ICacheMemWriteEnable, + output logic [LINESIZE-1:0] ICacheMemWriteData, + output logic [`XLEN-1:0] ICacheMemWritePAdr, + + // Outputs to rest of ifu + // High if the instruction in the fetch stage is compressed + output logic CompressedF, + // The instruction that was requested + // If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros + output logic [31:0] InstrRawD, + + // Outputs to pipeline control stuff + output logic ICacheStallF, + + // Signals to/from ahblite interface + // A read containing the requested data + input logic [`XLEN-1:0] InstrInF, + // The read we request from main memory + output logic [`XLEN-1:0] InstrPAdrF, + output logic InstrReadF +); + + logic [31:0] AlignedInstrRawF, AlignedInstrRawD; + logic FlushDLastCycle; + const logic [31:0] NOP = 32'h13; + + // TODO allow compressed instructions + // (start with noncompressed only to get something working) + assign CompressedF = 1'b0; + + // Handle happy path (data in cache, reads aligned) + always_comb begin + assign ICacheMemReadLowerAdr = LowerPCF; + assign ICacheMemReadUpperPAdr = UpperPCPF; + end + + generate + if (`XLEN == 32) begin + assign AlignedInstrRawF = ICacheMemReadData; + end else begin + assign AlignedInstrRawF = LowerPCF[2] ? ICacheMemReadData[63:32] : ICacheMemReadData[31:0]; + end + endgenerate + + flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD); + flopr #(1) FlushDLastCycleFlop(clk, reset, FlushD | (FlushDLastCycle & StallF), FlushDLastCycle); + mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, FlushDLastCycle, InstrRawD); + + // Handle cache faults + + localparam integer WORDSPERLINE = LINESIZE/`XLEN; + localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); + + logic FetchState; + logic [$clog2(WORDSPERLINE)-1:0] FetchWordNum; + logic [`XLEN-1:0] LineAlignedPCPF; + + flopr #(1) FetchStateFlop(clk, reset, 1'b0, FetchState); + flopr #($clog2(WORDSPERLINE)) FetchWordNumFlop(clk, reset, {$clog2(WORDSPERLINE){1'b0}}, FetchWordNum); + + genvar i; + generate + for (i=0; i < WORDSPERLINE; i++) begin + flopenr #(32) flop(clk, reset, FetchState & (i == FetchWordNum), InstrInF, ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]); + end + endgenerate + + always_comb begin + assign InstrReadF = FetchState; + assign LineAlignedPCPF = {UpperPCPF, LowerPCF[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; + assign InstrPAdrF = LineAlignedPCPF + i*`XLEN; + end +endmodule + +module oldicache( + // Basic pipeline stuff + input logic clk, reset, + input logic StallF, StallD, + input logic FlushD, + // Upper bits of physical address for PC + input logic [`XLEN-1:12] UpperPCPF, + // Lower 12 bits of virtual PC address, since it's faster this way + input logic [11:0] LowerPCF, + // Data read in from the ebu unit + input logic [`XLEN-1:0] InstrInF, + // Read requested from the ebu unit + output logic [`XLEN-1:0] InstrPAdrF, + output logic InstrReadF, + // High if the instruction currently in the fetch stage is compressed + output logic CompressedF, + // High if the icache is requesting a stall + output logic ICacheStallF, + // The raw (not decompressed) instruction that was requested + // If the next instruction is compressed, the upper 16 bits may be anything + output logic [31:0] InstrRawD +); logic DelayF, DelaySideF, FlushDLastCyclen, DelayD; logic [1:0] InstrDMuxChoice; logic [15:0] MisalignedHalfInstrF, MisalignedHalfInstrD; From ba95557c449f9566e05ac2de7243b736792cf4d5 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 24 Mar 2021 13:58:43 -0400 Subject: [PATCH 18/55] More progress on icache controller --- wally-pipelined/src/ifu/icache.sv | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 17c8bf1e..c0f04286 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -150,14 +150,15 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Handle cache faults localparam integer WORDSPERLINE = LINESIZE/`XLEN; + localparam integer LOGWPL = $clog2(WORDSPERLINE); localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); - logic FetchState; - logic [$clog2(WORDSPERLINE)-1:0] FetchWordNum; + logic FetchState, EndFetchState, BeginFetchState; + logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; logic [`XLEN-1:0] LineAlignedPCPF; - flopr #(1) FetchStateFlop(clk, reset, 1'b0, FetchState); - flopr #($clog2(WORDSPERLINE)) FetchWordNumFlop(clk, reset, {$clog2(WORDSPERLINE){1'b0}}, FetchWordNum); + flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState); + flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum); genvar i; generate @@ -166,10 +167,23 @@ module icachecontroller #(parameter LINESIZE = 256) ( end endgenerate + // Machinery to request the correct addresses from main memory always_comb begin assign InstrReadF = FetchState; assign LineAlignedPCPF = {UpperPCPF, LowerPCF[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; - assign InstrPAdrF = LineAlignedPCPF + i*`XLEN; + assign InstrPAdrF = LineAlignedPCPF + FetchWordNum*`XLEN; + assign NextFetchWordNum = FetchState ? FetchWordNum+1 : {LOGWPL+1{1'b0}}; + end + + // Write to cache memory when we have the line here + always_comb begin + assign BeginFetchState = 1'b0; + assign EndFetchState = FetchWordNum == {1'b1, {LOGWPL{1'b0}}}; + end + + // Stall the pipeline while loading a new line from memory + always_comb begin + assign ICacheStallF = FetchState | ~ICacheMemReadValid; end endmodule From 602271ff7b91a6eda837f07196b571ceff887f32 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 24 Mar 2021 16:56:44 -0400 Subject: [PATCH 19/55] rv64i linear control flow now working --- wally-pipelined/regression/wally-pipelined.do | 2 +- .../regression/wave-dos/ahb-waves.do | 8 -- .../regression/wave-dos/cache-waves.do | 82 +++++++++++++++++++ .../regression/wave-dos/default-waves.do | 5 -- wally-pipelined/src/cache/line.sv | 4 +- wally-pipelined/src/ebu/ahblite.sv | 2 + wally-pipelined/src/hazard/hazard.sv | 4 +- wally-pipelined/src/ifu/icache.sv | 22 +++-- wally-pipelined/src/ifu/ifu.sv | 1 + .../src/wally/wallypipelinedhart.sv | 2 +- .../testbench/testbench-imperas.sv | 3 +- 11 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 wally-pipelined/regression/wave-dos/cache-waves.do diff --git a/wally-pipelined/regression/wally-pipelined.do b/wally-pipelined/regression/wally-pipelined.do index a5041005..5f1b1406 100644 --- a/wally-pipelined/regression/wally-pipelined.do +++ b/wally-pipelined/regression/wally-pipelined.do @@ -42,7 +42,7 @@ vsim workopt view wave -- display input and output signals as hexidecimal values -do ./wave-dos/ahb-waves.do +do ./wave-dos/cache-waves.do -- Set Wave Output Items TreeUpdate [SetDefaultTree] diff --git a/wally-pipelined/regression/wave-dos/ahb-waves.do b/wally-pipelined/regression/wave-dos/ahb-waves.do index f043d779..c3a38563 100644 --- a/wally-pipelined/regression/wave-dos/ahb-waves.do +++ b/wally-pipelined/regression/wave-dos/ahb-waves.do @@ -19,16 +19,8 @@ add wave -divider add wave -hex /testbench/dut/hart/ifu/PCF add wave -hex /testbench/dut/hart/ifu/PCD add wave -hex /testbench/dut/hart/ifu/InstrD - add wave /testbench/InstrDName add wave -hex /testbench/dut/hart/ifu/ic/InstrRawD -add wave -hex /testbench/dut/hart/ifu/ic/AlignedInstrD -add wave -divider -add wave -hex /testbench/dut/hart/ifu/ic/InstrPAdrF -add wave /testbench/dut/hart/ifu/ic/DelayF -add wave /testbench/dut/hart/ifu/ic/DelaySideF -add wave /testbench/dut/hart/ifu/ic/DelayD -add wave -hex /testbench/dut/hart/ifu/ic/MisalignedHalfInstrD add wave -divider add wave -hex /testbench/dut/hart/ifu/PCE diff --git a/wally-pipelined/regression/wave-dos/cache-waves.do b/wally-pipelined/regression/wave-dos/cache-waves.do new file mode 100644 index 00000000..e39d40a0 --- /dev/null +++ b/wally-pipelined/regression/wave-dos/cache-waves.do @@ -0,0 +1,82 @@ +add wave /testbench/clk +add wave /testbench/reset +add wave -divider + +#add wave /testbench/dut/hart/ebu/IReadF +add wave /testbench/dut/hart/DataStall +add wave /testbench/dut/hart/InstrStall +add wave /testbench/dut/hart/StallF +add wave /testbench/dut/hart/StallD +add wave /testbench/dut/hart/StallE +add wave /testbench/dut/hart/StallM +add wave /testbench/dut/hart/StallW +add wave /testbench/dut/hart/FlushD +add wave /testbench/dut/hart/FlushE +add wave /testbench/dut/hart/FlushM +add wave /testbench/dut/hart/FlushW + +add wave -divider +add wave -hex /testbench/dut/hart/ifu/PCF +add wave -hex /testbench/dut/hart/ifu/PCD +add wave -hex /testbench/dut/hart/ifu/InstrD + +add wave /testbench/InstrDName +add wave -hex /testbench/dut/hart/ifu/ic/InstrRawD +add wave -hex /testbench/dut/hart/ifu/ic/controller/AlignedInstrRawD +add wave -divider +add wave -hex /testbench/dut/hart/ifu/ic/controller/FetchState +add wave -hex /testbench/dut/hart/ifu/ic/controller/FetchWordNum +add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWriteEnable +add wave -hex /testbench/dut/hart/ifu/ic/InstrPAdrF +add wave -hex /testbench/dut/hart/ifu/ic/InstrAckF +add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWriteData +add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWritePAdr +add wave -divider + +add wave -hex /testbench/dut/hart/ifu/PCE +add wave -hex /testbench/dut/hart/ifu/InstrE +add wave /testbench/InstrEName +add wave -hex /testbench/dut/hart/ieu/dp/SrcAE +add wave -hex /testbench/dut/hart/ieu/dp/SrcBE +add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE +#add wave /testbench/dut/hart/ieu/dp/PCSrcE +add wave -divider + +add wave -hex /testbench/dut/hart/ifu/PCM +add wave -hex /testbench/dut/hart/ifu/InstrM +add wave /testbench/InstrMName +add wave /testbench/dut/uncore/dtim/memwrite +add wave -hex /testbench/dut/uncore/HADDR +add wave -hex /testbench/dut/uncore/HWDATA +add wave -divider + +add wave -hex /testbench/dut/hart/ebu/MemReadM +add wave -hex /testbench/dut/hart/ebu/InstrReadF +add wave -hex /testbench/dut/hart/ebu/BusState +add wave -hex /testbench/dut/hart/ebu/NextBusState +add wave -hex /testbench/dut/hart/ebu/HADDR +add wave -hex /testbench/dut/hart/ebu/HREADY +add wave -hex /testbench/dut/hart/ebu/HTRANS +add wave -hex /testbench/dut/hart/ebu/HRDATA +add wave -hex /testbench/dut/hart/ebu/HWRITE +add wave -hex /testbench/dut/hart/ebu/HWDATA +add wave -hex /testbench/dut/hart/ebu/CaptureDataM +add wave -hex /testbench/dut/hart/ebu/InstrStall +add wave -divider + +add wave -hex /testbench/dut/uncore/dtim/* +add wave -divider + +add wave -hex /testbench/dut/hart/ifu/PCW +add wave -hex /testbench/dut/hart/ifu/InstrW +add wave /testbench/InstrWName +add wave /testbench/dut/hart/ieu/dp/RegWriteW +add wave -hex /testbench/dut/hart/ebu/ReadDataW +add wave -hex /testbench/dut/hart/ieu/dp/ResultW +add wave -hex /testbench/dut/hart/ieu/dp/RdW +add wave -divider + +add wave -hex /testbench/dut/uncore/dtim/* +add wave -divider + +add wave -hex -r /testbench/* diff --git a/wally-pipelined/regression/wave-dos/default-waves.do b/wally-pipelined/regression/wave-dos/default-waves.do index 4b645651..ef4e30c6 100644 --- a/wally-pipelined/regression/wave-dos/default-waves.do +++ b/wally-pipelined/regression/wave-dos/default-waves.do @@ -23,11 +23,6 @@ add wave -hex /testbench/dut/hart/ifu/PCD add wave -hex /testbench/dut/hart/ifu/InstrD add wave /testbench/InstrDName add wave -hex /testbench/dut/hart/ifu/ic/InstrRawD -add wave -hex /testbench/dut/hart/ifu/ic/AlignedInstrD -add wave /testbench/dut/hart/ifu/ic/DelayF -add wave /testbench/dut/hart/ifu/ic/DelaySideF -add wave /testbench/dut/hart/ifu/ic/DelayD -add wave -hex /testbench/dut/hart/ifu/ic/MisalignedHalfInstrD add wave -divider add wave -hex /testbench/dut/hart/ifu/PCE add wave -hex /testbench/dut/hart/ifu/InstrE diff --git a/wally-pipelined/src/cache/line.sv b/wally-pipelined/src/cache/line.sv index 6fe848e5..d90cd206 100644 --- a/wally-pipelined/src/cache/line.sv +++ b/wally-pipelined/src/cache/line.sv @@ -55,8 +55,8 @@ module rocacheline #(parameter LINESIZE = 256, parameter TAGSIZE = 32, parameter genvar i; generate for (i=0; i < NUMWORDS; i++) begin - assign DataLinesIn[i] = WriteData[NUMWORDS*i+WORDSIZE-1:NUMWORDS*i]; - flopenr #(LINESIZE) LineFlop(clk, reset, WriteEnable, DataLinesIn[i], DataLinesOut[i]); + assign DataLinesIn[i] = WriteData[WORDSIZE*(i+1)-1:WORDSIZE*i]; + flopenr #(WORDSIZE) LineFlop(clk, reset, WriteEnable, DataLinesIn[i], DataLinesOut[i]); end endgenerate diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 90ef018b..58a28747 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -41,6 +41,7 @@ module ahblite ( input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram input logic InstrReadF, output logic [`XLEN-1:0] InstrRData, + output logic InstrAckF, // Signals from Data Cache input logic [`XLEN-1:0] MemPAdrM, input logic MemReadM, MemWriteM, @@ -171,6 +172,7 @@ module ahblite ( assign #1 MMUReady = (NextBusState == MMUIDLE); assign InstrRData = HRDATA; + assign InstrAckF = (BusState == INSTRREAD) && (NextBusState != INSTRREAD) || (BusState == INSTRREADC) && (NextBusState != INSTRREADC); assign MMUReadPTE = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || diff --git a/wally-pipelined/src/hazard/hazard.sv b/wally-pipelined/src/hazard/hazard.sv index 9542020d..ecd3c366 100644 --- a/wally-pipelined/src/hazard/hazard.sv +++ b/wally-pipelined/src/hazard/hazard.sv @@ -53,12 +53,12 @@ module hazard( assign BranchFlushDE = BPPredWrongE | RetM | TrapM; - assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE); + assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE) | ICacheStallF; assign StallDCause = (LoadStallD | MulDivStallD | CSRRdStallD) & ~(BranchFlushDE); // stall in decode if instruction is a load/mul/csr dependent on previous // assign StallDCause = LoadStallD | MulDivStallD | CSRRdStallD; // stall in decode if instruction is a load/mul/csr dependent on previous assign StallECause = 0; assign StallMCause = 0; - assign StallWCause = DataStall | InstrStall; + assign StallWCause = DataStall; // Each stage stalls if the next stage is stalled or there is a cause to stall this stage. assign StallF = StallD | StallFCause; diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index c0f04286..df608a39 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -36,6 +36,7 @@ module icache( input logic [11:0] LowerPCF, // Data read in from the ebu unit input logic [`XLEN-1:0] InstrInF, + input logic InstrAckF, // Read requested from the ebu unit output logic [`XLEN-1:0] InstrPAdrF, output logic InstrReadF, @@ -77,6 +78,8 @@ module icache( ); icachecontroller #(.LINESIZE(ICACHELINESIZE)) controller(.*); + + assign FlushMem = 1'b0; endmodule module icachecontroller #(parameter LINESIZE = 256) ( @@ -116,6 +119,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Signals to/from ahblite interface // A read containing the requested data input logic [`XLEN-1:0] InstrInF, + input logic InstrAckF, // The read we request from main memory output logic [`XLEN-1:0] InstrPAdrF, output logic InstrReadF @@ -163,22 +167,28 @@ module icachecontroller #(parameter LINESIZE = 256) ( genvar i; generate for (i=0; i < WORDSPERLINE; i++) begin - flopenr #(32) flop(clk, reset, FetchState & (i == FetchWordNum), InstrInF, ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]); + flopenr #(`XLEN) flop(clk, reset, FetchState & (i == FetchWordNum), InstrInF, ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]); end endgenerate + // Enter the fetch state when we hit a cache fault + always_comb begin + assign BeginFetchState = ~ICacheMemReadValid & ~FetchState; + end + // Machinery to request the correct addresses from main memory always_comb begin - assign InstrReadF = FetchState; + assign InstrReadF = FetchState & ~EndFetchState; assign LineAlignedPCPF = {UpperPCPF, LowerPCF[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; - assign InstrPAdrF = LineAlignedPCPF + FetchWordNum*`XLEN; - assign NextFetchWordNum = FetchState ? FetchWordNum+1 : {LOGWPL+1{1'b0}}; + assign InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); + assign NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; end // Write to cache memory when we have the line here always_comb begin - assign BeginFetchState = 1'b0; - assign EndFetchState = FetchWordNum == {1'b1, {LOGWPL{1'b0}}}; + assign EndFetchState = FetchWordNum == {1'b1, {LOGWPL{1'b0}}} & FetchState; + assign ICacheMemWritePAdr = LineAlignedPCPF; + assign ICacheMemWriteEnable = EndFetchState; end // Stall the pipeline while loading a new line from memory diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index c68786e5..747a2b49 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -32,6 +32,7 @@ module ifu ( input logic FlushF, FlushD, FlushE, FlushM, FlushW, // Fetch input logic [`XLEN-1:0] InstrInF, + input logic InstrAckF, output logic [`XLEN-1:0] PCF, output logic [`XLEN-1:0] InstrPAdrF, output logic InstrReadF, diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index c858befd..49214b0d 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -112,7 +112,7 @@ module wallypipelinedhart ( logic [`XLEN-1:0] InstrRData; logic InstrReadF; logic DataStall, InstrStall; - logic InstrAckD, MemAckW; + logic InstrAckF, MemAckW; logic BPPredWrongE, BPPredWrongM; logic [3:0] InstrClassM; diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 8b128b17..37d9883e 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -370,7 +370,8 @@ string tests32i[] = { // Track names of instructions instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE, - dut.hart.ifu.ic.InstrF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE, + dut.hart.ifu.ic.controller.AlignedInstrRawF, + dut.hart.ifu.InstrD, dut.hart.ifu.InstrE, dut.hart.ifu.InstrM, dut.hart.ifu.InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); From 128278ea2799da37487e9e231dd29e9c6aa27898 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 24 Mar 2021 17:23:00 -0400 Subject: [PATCH 20/55] Working for all of rv64i now, but not compressed instructions --- wally-pipelined/src/hazard/hazard.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wally-pipelined/src/hazard/hazard.sv b/wally-pipelined/src/hazard/hazard.sv index ecd3c366..3768f0fc 100644 --- a/wally-pipelined/src/hazard/hazard.sv +++ b/wally-pipelined/src/hazard/hazard.sv @@ -53,12 +53,12 @@ module hazard( assign BranchFlushDE = BPPredWrongE | RetM | TrapM; - assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE) | ICacheStallF; + assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE); assign StallDCause = (LoadStallD | MulDivStallD | CSRRdStallD) & ~(BranchFlushDE); // stall in decode if instruction is a load/mul/csr dependent on previous // assign StallDCause = LoadStallD | MulDivStallD | CSRRdStallD; // stall in decode if instruction is a load/mul/csr dependent on previous assign StallECause = 0; assign StallMCause = 0; - assign StallWCause = DataStall; + assign StallWCause = DataStall | ICacheStallF; // Each stage stalls if the next stage is stalled or there is a cause to stall this stage. assign StallF = StallD | StallFCause; From ce6f102fc5b9f73126cfba3a1f558118f19c6874 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 25 Mar 2021 00:46:51 -0400 Subject: [PATCH 21/55] Clean up some stuff --- wally-pipelined/src/ebu/ahblite.sv | 5 ++--- wally-pipelined/src/hazard/hazard.sv | 2 +- wally-pipelined/src/wally/wallypipelinedhart.sv | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 58a28747..c0aa27db 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -71,7 +71,7 @@ module ahblite ( output logic [3:0] HSIZED, output logic HWRITED, // Stalls - output logic InstrStall,/*InstrUpdate, */DataStall + output logic /*InstrUpdate, */DataStall // *** add a chip-level ready signal as part of handshake ); @@ -135,8 +135,7 @@ module ahblite ( // stall signals assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || - (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) || - (NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE); + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); // *** Could get finer grained stalling if we distinguish between MMU // instruction address translation and data address translation assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) || diff --git a/wally-pipelined/src/hazard/hazard.sv b/wally-pipelined/src/hazard/hazard.sv index 3768f0fc..c225a4e8 100644 --- a/wally-pipelined/src/hazard/hazard.sv +++ b/wally-pipelined/src/hazard/hazard.sv @@ -29,7 +29,7 @@ module hazard( // Detect hazards input logic BPPredWrongE, CSRWritePendingDEM, RetM, TrapM, input logic LoadStallD, MulDivStallD, CSRRdStallD, - input logic InstrStall, DataStall, ICacheStallF, + input logic DataStall, ICacheStallF, // Stall & flush outputs output logic StallF, StallD, StallE, StallM, StallW, output logic FlushF, FlushD, FlushE, FlushM, FlushW diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 49214b0d..0c079ba1 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -111,7 +111,7 @@ module wallypipelinedhart ( logic [`XLEN-1:0] InstrPAdrF; logic [`XLEN-1:0] InstrRData; logic InstrReadF; - logic DataStall, InstrStall; + logic DataStall; logic InstrAckF, MemAckW; logic BPPredWrongE, BPPredWrongM; From 0290568a5227b4fba3cf20aae9b4981b99b0b4f3 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 25 Mar 2021 13:18:30 -0400 Subject: [PATCH 22/55] Make cache output NOP after a reset --- wally-pipelined/regression/wave-dos/ahb-waves.do | 2 +- wally-pipelined/regression/wave-dos/cache-waves.do | 2 +- wally-pipelined/regression/wave-dos/default-waves.do | 2 +- wally-pipelined/src/ifu/icache.sv | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wally-pipelined/regression/wave-dos/ahb-waves.do b/wally-pipelined/regression/wave-dos/ahb-waves.do index c3a38563..c542f584 100644 --- a/wally-pipelined/regression/wave-dos/ahb-waves.do +++ b/wally-pipelined/regression/wave-dos/ahb-waves.do @@ -4,7 +4,7 @@ add wave -divider #add wave /testbench/dut/hart/ebu/IReadF add wave /testbench/dut/hart/DataStall -add wave /testbench/dut/hart/InstrStall +add wave /testbench/dut/hart/ICacheStallF add wave /testbench/dut/hart/StallF add wave /testbench/dut/hart/StallD add wave /testbench/dut/hart/StallE diff --git a/wally-pipelined/regression/wave-dos/cache-waves.do b/wally-pipelined/regression/wave-dos/cache-waves.do index e39d40a0..bdd88a13 100644 --- a/wally-pipelined/regression/wave-dos/cache-waves.do +++ b/wally-pipelined/regression/wave-dos/cache-waves.do @@ -4,7 +4,7 @@ add wave -divider #add wave /testbench/dut/hart/ebu/IReadF add wave /testbench/dut/hart/DataStall -add wave /testbench/dut/hart/InstrStall +add wave /testbench/dut/hart/ICacheStallF add wave /testbench/dut/hart/StallF add wave /testbench/dut/hart/StallD add wave /testbench/dut/hart/StallE diff --git a/wally-pipelined/regression/wave-dos/default-waves.do b/wally-pipelined/regression/wave-dos/default-waves.do index ef4e30c6..3f81cfad 100644 --- a/wally-pipelined/regression/wave-dos/default-waves.do +++ b/wally-pipelined/regression/wave-dos/default-waves.do @@ -6,7 +6,7 @@ add wave /testbench/reset add wave -divider #add wave /testbench/dut/hart/ebu/IReadF add wave /testbench/dut/hart/DataStall -add wave /testbench/dut/hart/InstrStall +add wave /testbench/dut/hart/ICacheStallF add wave /testbench/dut/hart/StallF add wave /testbench/dut/hart/StallD add wave /testbench/dut/hart/StallE diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index df608a39..631a9bd6 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -126,7 +126,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( ); logic [31:0] AlignedInstrRawF, AlignedInstrRawD; - logic FlushDLastCycle; + logic FlushDLastCycleN; const logic [31:0] NOP = 32'h13; // TODO allow compressed instructions @@ -148,8 +148,8 @@ module icachecontroller #(parameter LINESIZE = 256) ( endgenerate flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD); - flopr #(1) FlushDLastCycleFlop(clk, reset, FlushD | (FlushDLastCycle & StallF), FlushDLastCycle); - mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, FlushDLastCycle, InstrRawD); + flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN); + mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD); // Handle cache faults From 3b4f0141f4a7782ef3fd4c4d580d43f8cfa9d88f Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 25 Mar 2021 14:43:10 -0400 Subject: [PATCH 23/55] Begin work on compressed instructions --- .../regression/wave-dos/ahb-waves.do | 1 - .../regression/wave-dos/cache-waves.do | 1 - wally-pipelined/src/ebu/ahblite.sv | 4 - wally-pipelined/src/ifu/icache.sv | 77 ++++++++++++++++--- .../testbench/testbench-imperas.sv | 2 +- 5 files changed, 69 insertions(+), 16 deletions(-) diff --git a/wally-pipelined/regression/wave-dos/ahb-waves.do b/wally-pipelined/regression/wave-dos/ahb-waves.do index c542f584..263693d7 100644 --- a/wally-pipelined/regression/wave-dos/ahb-waves.do +++ b/wally-pipelined/regression/wave-dos/ahb-waves.do @@ -51,7 +51,6 @@ add wave -hex /testbench/dut/hart/ebu/HRDATA add wave -hex /testbench/dut/hart/ebu/HWRITE add wave -hex /testbench/dut/hart/ebu/HWDATA add wave -hex /testbench/dut/hart/ebu/CaptureDataM -add wave -hex /testbench/dut/hart/ebu/InstrStall add wave -divider add wave -hex /testbench/dut/uncore/dtim/* diff --git a/wally-pipelined/regression/wave-dos/cache-waves.do b/wally-pipelined/regression/wave-dos/cache-waves.do index bdd88a13..20c7061b 100644 --- a/wally-pipelined/regression/wave-dos/cache-waves.do +++ b/wally-pipelined/regression/wave-dos/cache-waves.do @@ -61,7 +61,6 @@ add wave -hex /testbench/dut/hart/ebu/HRDATA add wave -hex /testbench/dut/hart/ebu/HWRITE add wave -hex /testbench/dut/hart/ebu/HWDATA add wave -hex /testbench/dut/hart/ebu/CaptureDataM -add wave -hex /testbench/dut/hart/ebu/InstrStall add wave -divider add wave -hex /testbench/dut/uncore/dtim/* diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index c0aa27db..73df76a3 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -136,10 +136,6 @@ module ahblite ( // stall signals assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); - // *** Could get finer grained stalling if we distinguish between MMU - // instruction address translation and data address translation - assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) || - (NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE); // bus outputs assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 631a9bd6..09fb84ae 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -127,11 +127,11 @@ module icachecontroller #(parameter LINESIZE = 256) ( logic [31:0] AlignedInstrRawF, AlignedInstrRawD; logic FlushDLastCycleN; + logic PCPMisalignedF; const logic [31:0] NOP = 32'h13; - // TODO allow compressed instructions - // (start with noncompressed only to get something working) - assign CompressedF = 1'b0; + // Detect if the instruction is compressed + assign CompressedF = AlignedInstrRawF[1:0] != 2'b11; // Handle happy path (data in cache, reads aligned) always_comb begin @@ -141,9 +141,13 @@ module icachecontroller #(parameter LINESIZE = 256) ( generate if (`XLEN == 32) begin - assign AlignedInstrRawF = ICacheMemReadData; + assign AlignedInstrRawF = LowerPCF[1] ? {16'b0, ICacheMemReadData[31:16]} : ICacheMemReadData; + assign PCPMisalignedF = LowerPCF[1] && ~CompressedF; end else begin - assign AlignedInstrRawF = LowerPCF[2] ? ICacheMemReadData[63:32] : ICacheMemReadData[31:0]; + assign AlignedInstrRawF = LowerPCF[2] + ? (LowerPCF[1] ? MisalignedInstrRawF : ICacheMemReadData[63:32]) + : (LowerPCF[1] ? ICacheMemReadData[47:16] : ICacheMemReadData[31:0]); + assign PCPMisalignedF = LowerPCF[2] && LowerPCF[1] && ~CompressedF; end endgenerate @@ -151,15 +155,70 @@ module icachecontroller #(parameter LINESIZE = 256) ( flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN); mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD); + // Stall for faults or misaligned reads + always_comb begin + assign ICacheStallF = FaultStall | MisalignedStall; + end + + // Handle misaligned, noncompressed reads + logic MisalignedState, NextMisalignedState; + logic MisalignedStall; + logic [15:0] MisalignedHalfInstrF; + logic [`XLEN:0] MisalignedInstrRawF; + + always_comb begin + assign MisalignedInstrRawF = {16'b0, ICacheMemReadData[63:48]}; + end + + flopenr #(16) MisalignedHalfInstrFlop(clk, reset, ~FaultStall & (PCPMisalignedF & MisalignedState), AlignedInstrRawF[15:0], MisalignedHalfInstrF); + flopenr #(1) MisalignedStateFlop(clk, reset, ~FaultStall, NextMisalignedState, MisalignedState); + + always_comb begin + assign MisalignedStall = PCPMisalignedF & MisalignedState; + assign NextMisalignedState = ~PCPMisalignedF | ~MisalignedState; + end + + // Pick the correct address to read + always_comb begin + if (~PCPMisalignedF) begin + assign ICacheMemReadUpperPAdr = UpperPCPF; + generate + if (`XLEN == 32) + assign ICacheMemReadLowerAdr = {LowerPCF[31:2], 2'b00}; + else + assign ICacheMemReadLowerAdr = {LowerPCF[31:3], 2'b000}; + endgenerate + end else begin + if (MisalignedState) begin + assign ICacheMemReadUpperPAdr = UpperPCPF; + generate + if (`XLEN == 32) + assign ICacheMemReadLowerAdr = {LowerPCF[31:2]+1, 2'b00}; + else + assign ICacheMemReadLowerAdr = {LowerPCF[31:3]+1, 2'b000}; + endgenerate + end else begin + assign ICacheMemReadUpperPAdr = UpperPCPF; + generate + if (`XLEN == 32) + assign ICacheMemReadLowerAdr = {LowerPCF[31:2], 2'b00}; + else + assign ICacheMemReadLowerAdr = {LowerPCF[31:3], 2'b000}; + endgenerate + end + end + end + // Handle cache faults localparam integer WORDSPERLINE = LINESIZE/`XLEN; localparam integer LOGWPL = $clog2(WORDSPERLINE); localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); - logic FetchState, EndFetchState, BeginFetchState; - logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; - logic [`XLEN-1:0] LineAlignedPCPF; + logic FetchState, EndFetchState, BeginFetchState; + logic FaultStall; + logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; + logic [`XLEN-1:0] LineAlignedPCPF; flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState); flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum); @@ -193,7 +252,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Stall the pipeline while loading a new line from memory always_comb begin - assign ICacheStallF = FetchState | ~ICacheMemReadValid; + assign FaultStall = FetchState | ~ICacheMemReadValid; end endmodule diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 37d9883e..b94c1b62 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -340,7 +340,7 @@ string tests32i[] = { tests = testsBP64; end else begin tests = {tests64i}; - if (`C_SUPPORTED) tests = {tests, tests64ic}; + if (`C_SUPPORTED) tests = {tests64ic, tests}; else tests = {tests, tests64iNOc}; if (`M_SUPPORTED) tests = {tests, tests64m}; if (`A_SUPPORTED) tests = {tests, tests64a}; From 5f4feb0ff12dae150ac3c782c7ed1d7304c96920 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 25 Mar 2021 15:42:17 -0400 Subject: [PATCH 24/55] Works for misaligned instructions not on line boundaries --- wally-pipelined/src/ifu/icache.sv | 79 +++++++++++++++---------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 09fb84ae..85ec4cd3 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -45,7 +45,7 @@ module icache( // High if the icache is requesting a stall output logic ICacheStallF, // The raw (not decompressed) instruction that was requested - // If the next instruction is compressed, the upper 16 bits may be anything + // If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros output logic [31:0] InstrRawD ); @@ -125,23 +125,25 @@ module icachecontroller #(parameter LINESIZE = 256) ( output logic InstrReadF ); + // Happy path signals logic [31:0] AlignedInstrRawF, AlignedInstrRawD; logic FlushDLastCycleN; logic PCPMisalignedF; const logic [31:0] NOP = 32'h13; + // Misaligned signals + logic [`XLEN:0] MisalignedInstrRawF; + logic MisalignedStall; + // Cache fault signals + logic FaultStall; // Detect if the instruction is compressed assign CompressedF = AlignedInstrRawF[1:0] != 2'b11; // Handle happy path (data in cache, reads aligned) - always_comb begin - assign ICacheMemReadLowerAdr = LowerPCF; - assign ICacheMemReadUpperPAdr = UpperPCPF; - end generate if (`XLEN == 32) begin - assign AlignedInstrRawF = LowerPCF[1] ? {16'b0, ICacheMemReadData[31:16]} : ICacheMemReadData; + assign AlignedInstrRawF = LowerPCF[1] ? MisalignedInstrRawF : ICacheMemReadData; assign PCPMisalignedF = LowerPCF[1] && ~CompressedF; end else begin assign AlignedInstrRawF = LowerPCF[2] @@ -160,54 +162,48 @@ module icachecontroller #(parameter LINESIZE = 256) ( assign ICacheStallF = FaultStall | MisalignedStall; end - // Handle misaligned, noncompressed reads - logic MisalignedState, NextMisalignedState; - logic MisalignedStall; - logic [15:0] MisalignedHalfInstrF; - logic [`XLEN:0] MisalignedInstrRawF; - always_comb begin - assign MisalignedInstrRawF = {16'b0, ICacheMemReadData[63:48]}; - end + // Handle misaligned, noncompressed reads + + logic MisalignedState, NextMisalignedState; + logic [15:0] MisalignedHalfInstrF; + logic [15:0] UpperHalfWord; flopenr #(16) MisalignedHalfInstrFlop(clk, reset, ~FaultStall & (PCPMisalignedF & MisalignedState), AlignedInstrRawF[15:0], MisalignedHalfInstrF); flopenr #(1) MisalignedStateFlop(clk, reset, ~FaultStall, NextMisalignedState, MisalignedState); + // When doing a misaligned read, swizzle the bits correctly + generate + if (`XLEN == 32) begin + assign UpperHalfWord = ICacheMemReadData[31:16]; + end else begin + assign UpperHalfWord = ICacheMemReadData[63:48]; + end + endgenerate + always_comb begin + if (MisalignedState) begin + assign MisalignedInstrRawF = {16'b0, UpperHalfWord}; + end else begin + assign MisalignedInstrRawF = {ICacheMemReadData[15:0], MisalignedHalfInstrF}; + end + end + + // Manage internal state and stall when necessary always_comb begin assign MisalignedStall = PCPMisalignedF & MisalignedState; assign NextMisalignedState = ~PCPMisalignedF | ~MisalignedState; end // Pick the correct address to read - always_comb begin - if (~PCPMisalignedF) begin - assign ICacheMemReadUpperPAdr = UpperPCPF; - generate - if (`XLEN == 32) - assign ICacheMemReadLowerAdr = {LowerPCF[31:2], 2'b00}; - else - assign ICacheMemReadLowerAdr = {LowerPCF[31:3], 2'b000}; - endgenerate + generate + if (`XLEN == 32) begin + assign ICacheMemReadLowerAdr = {LowerPCF[11:2] + (PCPMisalignedF & ~MisalignedState), 2'b00}; end else begin - if (MisalignedState) begin - assign ICacheMemReadUpperPAdr = UpperPCPF; - generate - if (`XLEN == 32) - assign ICacheMemReadLowerAdr = {LowerPCF[31:2]+1, 2'b00}; - else - assign ICacheMemReadLowerAdr = {LowerPCF[31:3]+1, 2'b000}; - endgenerate - end else begin - assign ICacheMemReadUpperPAdr = UpperPCPF; - generate - if (`XLEN == 32) - assign ICacheMemReadLowerAdr = {LowerPCF[31:2], 2'b00}; - else - assign ICacheMemReadLowerAdr = {LowerPCF[31:3], 2'b000}; - endgenerate - end + assign ICacheMemReadLowerAdr = {LowerPCF[11:3] + (PCPMisalignedF & ~MisalignedState), 3'b00}; end - end + endgenerate + assign ICacheMemReadUpperPAdr = UpperPCPF; + // Handle cache faults @@ -216,7 +212,6 @@ module icachecontroller #(parameter LINESIZE = 256) ( localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); logic FetchState, EndFetchState, BeginFetchState; - logic FaultStall; logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; logic [`XLEN-1:0] LineAlignedPCPF; From 32829bf7a1679811364f607ea7ed89a87869db0d Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 25 Mar 2021 15:46:35 -0400 Subject: [PATCH 25/55] Remove old icache --- wally-pipelined/src/ifu/icache.sv | 111 ------------------------------ 1 file changed, 111 deletions(-) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 85ec4cd3..046126d3 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -250,114 +250,3 @@ module icachecontroller #(parameter LINESIZE = 256) ( assign FaultStall = FetchState | ~ICacheMemReadValid; end endmodule - -module oldicache( - // Basic pipeline stuff - input logic clk, reset, - input logic StallF, StallD, - input logic FlushD, - // Upper bits of physical address for PC - input logic [`XLEN-1:12] UpperPCPF, - // Lower 12 bits of virtual PC address, since it's faster this way - input logic [11:0] LowerPCF, - // Data read in from the ebu unit - input logic [`XLEN-1:0] InstrInF, - // Read requested from the ebu unit - output logic [`XLEN-1:0] InstrPAdrF, - output logic InstrReadF, - // High if the instruction currently in the fetch stage is compressed - output logic CompressedF, - // High if the icache is requesting a stall - output logic ICacheStallF, - // The raw (not decompressed) instruction that was requested - // If the next instruction is compressed, the upper 16 bits may be anything - output logic [31:0] InstrRawD -); - logic DelayF, DelaySideF, FlushDLastCyclen, DelayD; - logic [1:0] InstrDMuxChoice; - logic [15:0] MisalignedHalfInstrF, MisalignedHalfInstrD; - logic [31:0] InstrF, AlignedInstrD; - // Buffer the last read, for ease of accessing it again - logic LastReadDataValidF; - logic [`XLEN-1:0] LastReadDataF, LastReadAdrF, InDataF; - - // instruction for NOP - logic [31:0] nop = 32'h00000013; - - // Temporary change to bridge the new interface to old behaviors - logic [`XLEN-1:0] PCPF; - assign PCPF = {UpperPCPF, LowerPCF}; - - // This flop doesn't stall if StallF is high because we should output a nop - // when FlushD happens, even if the pipeline is also stalled. - flopr #(1) flushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCyclen | ~StallF), FlushDLastCyclen); - - flopenr #(1) delayDFlop(clk, reset, ~StallF, DelayF & ~CompressedF, DelayD); - flopenrc#(1) delayStateFlop(clk, reset, FlushD, ~StallF, DelayF & ~DelaySideF, DelaySideF); - // This flop stores the first half of a misaligned instruction while waiting for the other half - flopenr #(16) halfInstrFlop(clk, reset, DelayF & ~StallF, MisalignedHalfInstrF, MisalignedHalfInstrD); - - // This flop is here to simulate pulling data out of the cache, which is edge-triggered - flopenr #(32) instrFlop(clk, reset, ~StallF, InstrF, AlignedInstrD); - - // These flops cache the previous read, to accelerate things - flopenr #(`XLEN) lastReadDataFlop(clk, reset, InstrReadF & ~StallF, InstrInF, LastReadDataF); - flopenr #(1) lastReadDataVFlop(clk, reset, InstrReadF & ~StallF, 1'b1, LastReadDataValidF); - flopenr #(`XLEN) lastReadAdrFlop(clk, reset, InstrReadF & ~StallF, InstrPAdrF, LastReadAdrF); - - // Decide which address needs to be fetched and sent out over InstrPAdrF - // If the requested address fits inside one read from memory, we fetch that - // address, adjusted to the bit width. Otherwise, we request the lower word - // and then the upper word, in that order. - generate - if (`XLEN == 32) begin - assign InstrPAdrF = PCPF[1] ? ((DelaySideF & ~CompressedF) ? {PCPF[31:2], 2'b00} : {PCPF[31:2], 2'b00}) : PCPF; - end else begin - assign InstrPAdrF = PCPF[2] ? (PCPF[1] ? ((DelaySideF & ~CompressedF) ? {PCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}) : {PCPF[63:3], 3'b000}) : {PCPF[63:3], 3'b000}; - end - endgenerate - - // Read from memory if we don't have the address we want - always_comb if (LastReadDataValidF & (InstrPAdrF == LastReadAdrF)) begin - assign InstrReadF = 0; - end else begin - assign InstrReadF = 1; - end - - // Pick from the memory input or from the previous read, as appropriate - mux2 #(`XLEN) inDataMux(LastReadDataF, InstrInF, InstrReadF, InDataF); - - // If the instruction fits in one memory read, then we put the right bits - // into InstrF. Otherwise, we activate DelayF to signal the rest of the - // machinery to swizzle bits. - generate - if (`XLEN == 32) begin - assign InstrF = PCPF[1] ? {16'b0, InDataF[31:16]} : InDataF; - assign DelayF = PCPF[1]; - assign MisalignedHalfInstrF = InDataF[31:16]; - end else begin - assign InstrF = PCPF[2] ? (PCPF[1] ? {16'b0, InDataF[63:48]} : InDataF[63:32]) : (PCPF[1] ? InDataF[47:16] : InDataF[31:0]); - assign DelayF = PCPF[1] && PCPF[2]; - assign MisalignedHalfInstrF = InDataF[63:48]; - end - endgenerate - // We will likely need to stall later, but stalls are handled by the rest of the pipeline for now - assign ICacheStallF = 0; - - // Detect if the instruction is compressed - assign CompressedF = InstrF[1:0] != 2'b11; - - // Pick the correct output, depending on whether we have to assemble this - // instruction from two reads or not. - // Output the requested instruction (we don't need to worry if the read is - // incomplete, since the pipeline stalls for us when it isn't), or a NOP for - // the cycle when the first of two reads comes in. - always_comb if (~FlushDLastCyclen) begin - assign InstrDMuxChoice = 2'b10; - end else if (DelayD & (MisalignedHalfInstrD[1:0] != 2'b11)) begin - assign InstrDMuxChoice = 2'b11; - end else begin - assign InstrDMuxChoice = {1'b0, DelayD}; - end - mux4 #(32) instrDMux (AlignedInstrD, {InstrInF[15:0], MisalignedHalfInstrD}, nop, {16'b0, MisalignedHalfInstrD}, InstrDMuxChoice, InstrRawD); -endmodule From 39bf2347bc6044496a0a4e978fff505ce0259cb7 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 25 Mar 2021 18:47:23 -0400 Subject: [PATCH 26/55] Fix error when reading an instruction that crosses a line boundary --- wally-pipelined/regression/wave-dos/cache-waves.do | 3 +++ wally-pipelined/src/ifu/icache.sv | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/wally-pipelined/regression/wave-dos/cache-waves.do b/wally-pipelined/regression/wave-dos/cache-waves.do index 20c7061b..c7b32e1e 100644 --- a/wally-pipelined/regression/wave-dos/cache-waves.do +++ b/wally-pipelined/regression/wave-dos/cache-waves.do @@ -31,8 +31,11 @@ add wave -hex /testbench/dut/hart/ifu/ic/InstrPAdrF add wave -hex /testbench/dut/hart/ifu/ic/InstrAckF add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWriteData add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWritePAdr +add wave -hex /testbench/dut/hart/ifu/ic/controller/MisalignedState +add wave -hex /testbench/dut/hart/ifu/ic/controller/MisalignedHalfInstrF add wave -divider + add wave -hex /testbench/dut/hart/ifu/PCE add wave -hex /testbench/dut/hart/ifu/InstrE add wave /testbench/InstrEName diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 046126d3..0d953760 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -233,7 +233,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Machinery to request the correct addresses from main memory always_comb begin assign InstrReadF = FetchState & ~EndFetchState; - assign LineAlignedPCPF = {UpperPCPF, LowerPCF[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; + assign LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; assign InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); assign NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; end From 2a308309e4733838c81277d7d44f7cc3a9e62f93 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 30 Mar 2021 13:57:40 -0500 Subject: [PATCH 27/55] fixed some bugs with the RAS. --- wally-pipelined/src/ifu/BTBPredictor.sv | 6 +++--- wally-pipelined/src/ifu/bpred.sv | 6 +++--- wally-pipelined/src/ifu/ifu.sv | 11 +++++----- .../testbench/testbench-busybear.sv | 20 +++++++++---------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index f9d84dee..b342c11b 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -36,7 +36,7 @@ module BTBPredictor input logic StallF, StallD, StallE, FlushF, FlushD, FlushE, input logic [`XLEN-1:0] LookUpPC, output logic [`XLEN-1:0] TargetPC, - output logic [3:0] InstrClass, + output logic [4:0] InstrClass, output logic Valid, // update input logic UpdateEN, @@ -108,7 +108,7 @@ module BTBPredictor // Another optimization may be using a PC relative address. // *** need to add forwarding. - SRAM2P1R1W #(Depth, `XLEN+4) memory(.clk(clk), + SRAM2P1R1W #(Depth, `XLEN+5) memory(.clk(clk), .reset(reset), .RA1(LookUpPCIndex), .RD1({{InstrClass, TargetPC}}), @@ -116,7 +116,7 @@ module BTBPredictor .WA1(UpdatePCIndex), .WD1({UpdateInstrClass, UpdateTarget}), .WEN1(UpdateEN), - .BitWEN1({4'b1111, {`XLEN{1'b1}}})); // *** definitely not right. + .BitWEN1({5'h1F, {`XLEN{1'b1}}})); // *** definitely not right. endmodule diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index a96d4353..ba9c688d 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -47,7 +47,7 @@ module bpred input logic [`XLEN-1:0] PCTargetE, // The branch destination if the branch is taken. input logic [`XLEN-1:0] PCD, // The address the branch predictor took. input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) - input logic [3:0] InstrClassE, + input logic [4:0] InstrClassE, // Report branch prediction status output logic BPPredWrongE ); @@ -55,7 +55,7 @@ module bpred logic BTBValidF; logic [1:0] BPPredF, BPPredD, BPPredE, UpdateBPPredE; - logic [3:0] BPInstrClassF, BPInstrClassD, BPInstrClassE; + logic [4:0] BPInstrClassF, BPInstrClassD, BPInstrClassE; logic [`XLEN-1:0] BTBPredPCF, RASPCF; logic TargetWrongE; logic FallThroughWrongE; @@ -146,7 +146,7 @@ module bpred .reset(reset), .pop(BPInstrClassF[3] & ~StallF), .popPC(RASPCF), - .push(InstrClassE[3] & ~StallE), + .push(InstrClassE[4] & ~StallE), .incr(1'b0), .pushPC(PCLinkE)); diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index e8987564..30e25bea 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -86,7 +86,7 @@ module ifu ( // branch predictor signals logic SelBPPredF; logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F; - logic [3:0] InstrClassD, InstrClassE; + logic [4:0] InstrClassD, InstrClassE; // *** put memory interface on here, InstrF becomes output @@ -173,8 +173,9 @@ module ifu ( // the branch predictor needs a compact decoding of the instruction class. // *** consider adding in the alternate return address x5 for returns. - assign InstrClassD[3] = InstrD[6:0] == 7'h67 && InstrD[19:15] == 5'h01; // return - assign InstrClassD[2] = InstrD[6:0] == 7'h67 && InstrD[19:15] != 5'h01; // jump register, but not return + assign InstrClassD[4] = (InstrD[6:0] & 7'h77) == 7'h67 && (InstrD[11:07] & 5'h1B) == 5'h01; // jal(r) must link to ra or r5 + assign InstrClassD[3] = InstrD[6:0] == 7'h67 && (InstrD[19:15] & 5'h1B) == 5'h01; // return must link to ra or r5 + assign InstrClassD[2] = InstrD[6:0] == 7'h67 && (InstrD[19:15] & 5'h1B) != 5'h01; // jump register, but not return assign InstrClassD[1] = InstrD[6:0] == 7'h6F; // jump assign InstrClassD[0] = InstrD[6:0] == 7'h63; // branch @@ -201,14 +202,14 @@ module ifu ( flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later - flopenrc #(4) InstrClassRegE(.clk(clk), + flopenrc #(5) InstrClassRegE(.clk(clk), .reset(reset), .en(~StallE), .clear(FlushE), .d(InstrClassD), .q(InstrClassE)); - flopenrc #(4) InstrClassRegM(.clk(clk), + flopenrc #(5) InstrClassRegM(.clk(clk), .reset(reset), .en(~StallM), .clear(FlushM), diff --git a/wally-pipelined/testbench/testbench-busybear.sv b/wally-pipelined/testbench/testbench-busybear.sv index 6f957efa..2b114e94 100644 --- a/wally-pipelined/testbench/testbench-busybear.sv +++ b/wally-pipelined/testbench/testbench-busybear.sv @@ -39,7 +39,7 @@ module testbench_busybear(); // read pc trace file integer data_file_PC, scan_file_PC; initial begin - data_file_PC = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r"); + data_file_PC = $fopen("../../../busybear_boot/parsedPC.txt", "r"); if (data_file_PC == 0) begin $display("file couldn't be opened"); $stop; @@ -48,7 +48,7 @@ module testbench_busybear(); integer data_file_PCW, scan_file_PCW; initial begin - data_file_PCW = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r"); + data_file_PCW = $fopen("../../../busybear_boot/parsedPC.txt", "r"); if (data_file_PCW == 0) begin $display("file couldn't be opened"); $stop; @@ -58,7 +58,7 @@ module testbench_busybear(); // read register trace file integer data_file_rf, scan_file_rf; initial begin - data_file_rf = $fopen("/courses/e190ax/busybear_boot/parsedRegs.txt", "r"); + data_file_rf = $fopen("../../../busybear_boot/parsedRegs.txt", "r"); if (data_file_rf == 0) begin $display("file couldn't be opened"); $stop; @@ -68,7 +68,7 @@ module testbench_busybear(); // read CSR trace file integer data_file_csr, scan_file_csr; initial begin - data_file_csr = $fopen("/courses/e190ax/busybear_boot/parsedCSRs.txt", "r"); + data_file_csr = $fopen("../../../busybear_boot/parsedCSRs.txt", "r"); if (data_file_csr == 0) begin $display("file couldn't be opened"); $stop; @@ -78,7 +78,7 @@ module testbench_busybear(); // read memreads trace file integer data_file_memR, scan_file_memR; initial begin - data_file_memR = $fopen("/courses/e190ax/busybear_boot/parsedMemRead.txt", "r"); + data_file_memR = $fopen("../../../busybear_boot/parsedMemRead.txt", "r"); if (data_file_memR == 0) begin $display("file couldn't be opened"); $stop; @@ -88,7 +88,7 @@ module testbench_busybear(); // read memwrite trace file integer data_file_memW, scan_file_memW; initial begin - data_file_memW = $fopen("/courses/e190ax/busybear_boot/parsedMemWrite.txt", "r"); + data_file_memW = $fopen("../../../busybear_boot/parsedMemWrite.txt", "r"); if (data_file_memW == 0) begin $display("file couldn't be opened"); $stop; @@ -97,10 +97,10 @@ module testbench_busybear(); // initial loading of memories initial begin - $readmemh("/courses/e190ax/busybear_boot/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3); - $readmemh("/courses/e190ax/busybear_boot/ram.txt", dut.uncore.dtim.RAM); - $readmemh("/courses/e190ax/busybear_boot/bootmem.txt", dut.imem.bootram, 'h1000 >> 3); - $readmemh("/courses/e190ax/busybear_boot/ram.txt", dut.imem.RAM); + $readmemh("../../../busybear_boot/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3); + $readmemh("../../../busybear_boot/ram.txt", dut.uncore.dtim.RAM); + $readmemh("../../../busybear_boot/bootmem.txt", dut.imem.bootram, 'h1000 >> 3); + $readmemh("../../../busybear_boot/ram.txt", dut.imem.RAM); $readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.Predictor.DirPredictor.PHT.memory); $readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.TargetPredictor.memory.memory); end From a64a37d702745a1fcd5e780e481a382823b8ea8e Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 30 Mar 2021 23:18:20 -0500 Subject: [PATCH 28/55] Merge of main with the new icache and the branch predictor. I believe there is a bug in the icache with unaligned memory access. The second part of the access is incorrectly relying on the PCF being the address of the next two bytes of the instruction. However this is not always the case as the branch predictor can get the wrong target address. The icache needs to generate the +2 address internally. --- .gitignore | 5 + testsBP/crt0/Makefile | 23 + testsBP/crt0/isr.s | 213 ++++ testsBP/crt0/start.s | 60 + testsBP/linker.x | 244 ++++ testsBP/makefile.inc | 92 ++ testsBP/sieve/Makefile | 15 + testsBP/sieve/sieve.c | 101 ++ testsBP/simple/Makefile | 15 + testsBP/simple/fail.s | 11 + testsBP/simple/header.h | 6 + testsBP/simple/main.c | 10 + testsBP/simple/sample.s | 61 + wally-pipelined/bin/exe2memfile.pl | 26 +- wally-pipelined/bin/exe2memfile0.pl | 145 +++ .../config/busybear/wally-config.vh | 1 + .../config/coremark/wally-config.vh | 1 + .../config/coremark_bare/wally-config.vh | 1 + wally-pipelined/config/rv32ic/wally-config.vh | 1 + .../config/rv64BP/BTBPredictor.txt | 1024 +++++++++++++++++ .../config/rv64BP/twoBitPredictor.txt | 1024 +++++++++++++++++ wally-pipelined/config/rv64BP/wally-config.vh | 101 ++ .../config/rv64BP/wally-constants.vh | 31 + wally-pipelined/config/rv64ic/wally-config.vh | 1 + .../config/rv64icfd/wally-config.vh | 1 + wally-pipelined/regression/wave.do | 161 ++- wally-pipelined/src/ieu/datapath.sv | 3 - wally-pipelined/src/ifu/BTBPredictor.sv | 45 +- wally-pipelined/src/ifu/RAsPredictor.sv | 2 +- wally-pipelined/src/ifu/bpred.sv | 24 +- wally-pipelined/src/ifu/gshare.sv | 29 +- wally-pipelined/src/ifu/ifu.sv | 13 +- wally-pipelined/src/privileged/csr.sv | 2 +- wally-pipelined/src/privileged/csrc.sv | 17 +- wally-pipelined/src/privileged/csri.sv | 9 +- wally-pipelined/src/privileged/csrm.sv | 57 +- wally-pipelined/src/privileged/csrn.sv | 13 +- wally-pipelined/src/privileged/csrs.sv | 17 +- wally-pipelined/src/privileged/csru.sv | 9 +- wally-pipelined/src/privileged/privileged.sv | 2 +- wally-pipelined/testbench/function_radix.sv | 29 +- .../testbench/testbench-busybear.sv | 20 +- .../testbench/testbench-imperas.sv | 17 +- 43 files changed, 3488 insertions(+), 194 deletions(-) create mode 100644 testsBP/crt0/Makefile create mode 100644 testsBP/crt0/isr.s create mode 100644 testsBP/crt0/start.s create mode 100644 testsBP/linker.x create mode 100644 testsBP/makefile.inc create mode 100644 testsBP/sieve/Makefile create mode 100644 testsBP/sieve/sieve.c create mode 100644 testsBP/simple/Makefile create mode 100644 testsBP/simple/fail.s create mode 100644 testsBP/simple/header.h create mode 100644 testsBP/simple/main.c create mode 100644 testsBP/simple/sample.s create mode 100755 wally-pipelined/bin/exe2memfile0.pl create mode 100644 wally-pipelined/config/rv64BP/BTBPredictor.txt create mode 100644 wally-pipelined/config/rv64BP/twoBitPredictor.txt create mode 100644 wally-pipelined/config/rv64BP/wally-config.vh create mode 100644 wally-pipelined/config/rv64BP/wally-constants.vh diff --git a/.gitignore b/.gitignore index db83fd6b..1cedda2a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,8 @@ wlft* /imperas-riscv-tests/FunctionRadix.addr /imperas-riscv-tests/ProgramMap.txt /wally-pipelined/busybear-testgen/gdbcombined.txt +*.o +*.d +testsBP/*/*/*.elf* +testsBP/*/OBJ/* +testsBP/*/*.a diff --git a/testsBP/crt0/Makefile b/testsBP/crt0/Makefile new file mode 100644 index 00000000..97b83faf --- /dev/null +++ b/testsBP/crt0/Makefile @@ -0,0 +1,23 @@ +TARGETDIR := bin +TARGET := $(TARGETDIR)/start +ROOT := .. +LIBRARY_DIRS := +LIBRARY_FILES := +LINK_FLAGS := -nostartfiles + +AFLAGS =-march=rv64ifd -W +CFLAGS =-march=rv64ifd -mcmodel=medany +AS=riscv64-unknown-elf-as +CC=riscv64-unknown-elf-gcc +AR=riscv64-unknown-elf-ar + +all: libcrt0.a + +%.o: %.s + ${AS} ${AFLAGS} -c $< -o $@ + +libcrt0.a: start.o + ${AR} -r $@ $^ + +clean: + rm -rf *.a *.o diff --git a/testsBP/crt0/isr.s b/testsBP/crt0/isr.s new file mode 100644 index 00000000..789d2d62 --- /dev/null +++ b/testsBP/crt0/isr.s @@ -0,0 +1,213 @@ +.section .text +.global __trap_handler +.type __trap_handler, @function + +__trap_handler: + # save the context of the cpu to the top of the current stack + addi sp, sp, -124 + sw x1, 0x0(sp) + sw x2, 0x4(sp) + sw x3, 0x8(sp) + sw x4, 0xC(sp) + sw x5, 0x10(sp) + sw x6, 0x14(sp) + sw x7, 0x18(sp) + sw x8, 0x1C(sp) + sw x9, 0x20(sp) + sw x10, 0x24(sp) + sw x11, 0x28(sp) + sw x12, 0x2C(sp) + sw x13, 0x30(sp) + sw x14, 0x34(sp) + sw x15, 0x38(sp) + sw x16, 0x3C(sp) + sw x17, 0x40(sp) + sw x18, 0x44(sp) + sw x19, 0x48(sp) + sw x20, 0x4C(sp) + sw x21, 0x50(sp) + sw x22, 0x54(sp) + sw x23, 0x58(sp) + sw x24, 0x5C(sp) + sw x25, 0x60(sp) + sw x26, 0x64(sp) + sw x27, 0x68(sp) + sw x28, 0x6C(sp) + sw x29, 0x70(sp) + sw x30, 0x74(sp) + sw x31, 0x78(sp) + + # figure out what caused the trap. + csrrw t0, mcause, x0 + # mcause is {int, 31 bit exception code} + # for this implementation only the lowest 4 bits are used + srli t1, t0, 31 # interrupt flag + andi t2, t0, 0xF # 4 bit cause + + slli t1, t1, 5 # shift int flag + or t1, t1, t2 # combine + slli t1, t1, 2 # multiply by 4 + la t3, exception_table + add t4, t3, t1 + lw t5, 0(t4) + jr t5, 0 # jump to specific ISR + # specific ISR is expected to set epc + +restore_st: + # restore register from stack on exit. + + lw x1, 0x0(sp) + lw x2, 0x4(sp) + lw x3, 0x8(sp) + lw x4, 0xC(sp) + lw x5, 0x10(sp) + lw x6, 0x14(sp) + lw x7, 0x18(sp) + lw x8, 0x1C(sp) + lw x9, 0x20(sp) + lw x10, 0x24(sp) + lw x11, 0x28(sp) + lw x12, 0x2C(sp) + lw x13, 0x30(sp) + lw x14, 0x34(sp) + lw x15, 0x38(sp) + lw x16, 0x3C(sp) + lw x17, 0x40(sp) + lw x18, 0x44(sp) + lw x19, 0x48(sp) + lw x20, 0x4C(sp) + lw x21, 0x50(sp) + lw x22, 0x54(sp) + lw x23, 0x58(sp) + lw x24, 0x5C(sp) + lw x25, 0x60(sp) + lw x26, 0x64(sp) + lw x27, 0x68(sp) + lw x28, 0x6C(sp) + lw x29, 0x70(sp) + lw x30, 0x74(sp) + lw x31, 0x78(sp) + + addi sp, sp, 124 + + mret + +.section .text +.type trap_instr_addr_misalign, @function +trap_instr_addr_misalign: + # fatal error, report error and halt + addi sp, sp, 4 + sw ra, 0(sp) + jal fail + lw ra, 0(sp) + la t0, restore_st + jr t0, 0 + +.section .text +.type trap_m_ecall, @function +trap_m_ecall: + addi sp, sp, -4 + sw ra, 0(sp) + # select which system call based on a7. + # for this example we will just define the following. + # not standard with linux or anything. + # 0: execute a call back function + # 1: decrease privilege by 1 (m=>s, s=>u, u=>u) + # 2: increase privilege by 1 (m=>m, s=>m, u=>s) + + # check a7 + li t0, 1 + beq a7, t0, trap_m_decrease_privilege + li t0, 2 + beq a7, t0, trap_m_increase_privilege + + # call call back function if not zero + la t1, isr_m_ecall_cb_fp + lw t0, 0(t1) + beq t0, x0, trap_m_ecall_skip_cb + jalr ra, t0, 0 +trap_m_ecall_skip_cb: + # modify the mepc + csrrw t0, mepc, x0 + addi t0, t0, 4 + csrrw x0, mepc, t0 + lw ra, 0(sp) + addi sp, sp, 4 + la t0, restore_st + jr t0, 0 + +trap_m_decrease_privilege: + # read the mstatus register + csrrw t0, mstatus, x0 + # 11 => 01, and 01 => 00. + # this is accomplished by clearing bit 12 and taking the old + # bit 12 as the new bit 11. + li t3, 0x00001800 + and t1, t0, t3 # isolates the bits 12 and 11. + # shift right by 1. + srli t2, t1, 1 + and t2, t2, t3 # this will clear bit 10. + li t3, ~0x00001800 + and t4, t0, t3 + or t0, t2, t4 + csrrw x0, mstatus, t0 + j trap_m_ecall_skip_cb + +trap_m_increase_privilege: + # read the mstatus register + csrrw t0, mstatus, x0 + # 11 => 01, and 01 => 00. + # this is accomplished by setting bit 11 and taking the old + # bit 11 as the new bit 12. + li t3, 0x00000800 + li t4, ~0x00000800 + and t1, t0, t3 + slli t2, t1, 1 # shift left by 1. + or t2, t2, t3 # bit 11 is always set. + and t1, t0, t5 + or t0, t1, t2 + csrrw x0, mstatus, t0 + j trap_m_ecall_skip_cb + +.data +exception_table: + .int trap_instr_addr_misalign + .int trap_instr_addr_misalign #trap_instr_access_fault + .int trap_instr_addr_misalign #trap_illegal_instr + .int trap_instr_addr_misalign #trap_breakpoint + .int trap_instr_addr_misalign #trap_load_addr_misalign + .int trap_instr_addr_misalign #trap_load_access_fault + .int trap_instr_addr_misalign #trap_store_addr_misalign + .int trap_instr_addr_misalign #trap_store_access_fault + .int trap_m_ecall + .int trap_m_ecall + .int restore_st + .int trap_m_ecall + .int trap_instr_addr_misalign #trap_instr_page_fault + .int trap_instr_addr_misalign #trap_load_page_fault + .int restore_st + .int trap_instr_addr_misalign #trap_store_page_fault +#.data +#interrupt_table: + .int trap_instr_addr_misalign #trap_u_software + .int trap_instr_addr_misalign #trap_s_software + .int restore_st + .int trap_instr_addr_misalign #trap_m_software + .int trap_instr_addr_misalign #trap_u_timer + .int trap_instr_addr_misalign #trap_s_timer + .int restore_st + .int trap_instr_addr_misalign #trap_m_timer + .int trap_instr_addr_misalign #trap_u_external + .int trap_instr_addr_misalign #trap_s_external + .int restore_st + .int trap_instr_addr_misalign #trap_m_external + .int restore_st + .int restore_st + .int restore_st + .int restore_st + + +.section .data +.global isr_m_ecall_cb_fp +isr_m_ecall_cb_fp: + .int 0 diff --git a/testsBP/crt0/start.s b/testsBP/crt0/start.s new file mode 100644 index 00000000..17543581 --- /dev/null +++ b/testsBP/crt0/start.s @@ -0,0 +1,60 @@ +.section .init +.global _start +.type _start, @function + +_start: + # Initialize global pointer + .option push + .option norelax + 1:auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) + .option pop + + li x1, 0 + li x2, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10, 0 + li x11, 0 + li x12, 0 + li x13, 0 + li x14, 0 + li x15, 0 + li x16, 0 + li x17, 0 + li x18, 0 + li x19, 0 + li x20, 0 + li x21, 0 + li x22, 0 + li x23, 0 + li x24, 0 + li x25, 0 + li x26, 0 + li x27, 0 + li x28, 0 + li x29, 0 + li x30, 0 + li x31, 0 + + + + # set the stack pointer to the top of memory + # 0x8000_0000 + 64K - 8 bytes + li sp, 0x0000FFF8 + + jal ra, main + jal ra, _halt + +.section .text +.global _halt +.type _halt, @function +_halt: + li gp, 1 + li a0, 0 + ecall + j _halt diff --git a/testsBP/linker.x b/testsBP/linker.x new file mode 100644 index 00000000..f448109c --- /dev/null +++ b/testsBP/linker.x @@ -0,0 +1,244 @@ +OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", + "elf64-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(_start) +SEARCH_DIR("/opt/riscv/riscv64-unknown-elf/lib"); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + /* init segment to ensure we get a consistent start routine*/ + . = 0x0000000000000000; + . = ALIGN(0x0); + .init : { + *(.init) + } + _start_end = .; + + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0)); . = SEGMENT_START("text-segment", _start_end); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf64.em. */ + *(.gnu.warning) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : + { + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : + { + PROVIDE_HIDDEN (__tdata_start = .); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + . = DATA_SEGMENT_RELRO_END (0, .); + .data : + { + __DATA_BEGIN__ = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + __SDATA_BEGIN__ = .; + *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + .sbss : + { + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we do not + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(64 / 8); + __BSS_END__ = .; + __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, + MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800)); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/testsBP/makefile.inc b/testsBP/makefile.inc new file mode 100644 index 00000000..af0b03bc --- /dev/null +++ b/testsBP/makefile.inc @@ -0,0 +1,92 @@ +CEXT := c +CPPEXT := cpp +AEXT := s +SEXT := S +SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\) +OBJEXT := o +DEPEXT := d +SRCDIR := . +BUILDDIR := OBJ +LINKER := ${ROOT}/linker.x + +SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort) +OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) + +#Default Make +all: directories $(TARGET).memfile + +#Remake +remake: clean all + +#Make the Directories +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + + +#Needed for building additional library projects +ifdef LIBRARY_DIRS +LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%} +INC+=${LIBRARY_DIRS:%=-I%} + +${LIBRARY_DIRS}: + make -C $@ -j 1 + +.PHONY: $(LIBRARY_DIRS) $(TARGET) +endif + + +#Pull in dependency info for *existing* .o files +-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) + +#Link +$(TARGET): $(OBJECTS) $(LIBRARY_DIRS) + $(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER} + + +#Compile +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# gcc won't output dependencies for assembly files for some reason +# most asm files don't have dependencies so the echo will work for now. +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +# C++ +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# convert to hex +$(TARGET).memfile: $(TARGET) + @echo 'Making object dump file.' + @riscv64-unknown-elf-objdump -D $< > $<.objdump + @echo 'Making memory file' + exe2memfile0.pl $< + extractFunctionRadix.sh $<.objdump diff --git a/testsBP/sieve/Makefile b/testsBP/sieve/Makefile new file mode 100644 index 00000000..9dcaab8d --- /dev/null +++ b/testsBP/sieve/Makefile @@ -0,0 +1,15 @@ +TARGETDIR := sieve +TARGET := $(TARGETDIR)/$(TARGETDIR).elf +ROOT := .. +LIBRARY_DIRS := ${ROOT}/crt0 +LIBRARY_FILES := crt0 +LINK_FLAGS := -nostartfiles -Wl,-Map=$(TARGET).map + +CFLAGS =-march=rv64ifd -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align +CC=riscv64-unknown-elf-gcc +DA=riscv64-unknown-elf-objdump -d + + +include $(ROOT)/makefile.inc + + diff --git a/testsBP/sieve/sieve.c b/testsBP/sieve/sieve.c new file mode 100644 index 00000000..e8207404 --- /dev/null +++ b/testsBP/sieve/sieve.c @@ -0,0 +1,101 @@ +/* + * Filename: + * + * sieve.c + * + * Description: + * + * The Sieve of Eratosthenes benchmark, from Byte Magazine + * early 1980s, when a PC would do well to run this in 10 + * seconds. This version really does count prime numbers + * but omits the numbers 1, 3 and all even numbers. The + * expected count is 1899. + * + */ + +#include +#include + +#define SIZE 8190 + +//#define SIZE 8388608 +double time_diff(struct timeval x , struct timeval y); + +int sieve () { + + unsigned char flags [SIZE + 1]; + int iter; + int count; + + for (iter = 1; iter <= 10; iter++) + { + int i, prime, k; + + count = 0; + + for (i = 0; i <= SIZE; i++) + flags [i] = 1; + + for (i = 0; i <= SIZE; i++) + { + if (flags [i]) + { + prime = i + i + 3; + k = i + prime; + + while (k <= SIZE) + { + flags [k] = 0; + k += prime; + } + + count++; + } + } + } + + return count; +} + +int main () { + + int ans; + + //struct timeval before , after; + //gettimeofday(&before , NULL); + + ans = sieve (); + //gettimeofday(&after , NULL); + if (ans != 1899) + printf ("Sieve result wrong, ans = %d, expected 1899", ans); + + //printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); + + + printf("Round 2\n"); + //gettimeofday(&before , NULL); + + ans = sieve (); + //gettimeofday(&after , NULL); + if (ans != 1899) + printf ("Sieve result wrong, ans = %d, expected 1899", ans); + + //printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) ); + + return 0; + +} + + +double time_diff(struct timeval x , struct timeval y) +{ + double x_ms , y_ms , diff; + + x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec; + y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec; + + diff = (double)y_ms - (double)x_ms; + + return diff; +} + diff --git a/testsBP/simple/Makefile b/testsBP/simple/Makefile new file mode 100644 index 00000000..aa350755 --- /dev/null +++ b/testsBP/simple/Makefile @@ -0,0 +1,15 @@ +TARGETDIR := simple +TARGET := $(TARGETDIR)/$(TARGETDIR).elf +ROOT := .. +LIBRARY_DIRS := ${ROOT}/crt0 +LIBRARY_FILES := crt0 +LINK_FLAGS := -nostartfiles -Wl,-Map=$(TARGET).map + +CFLAGS =-march=rv64ifd -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align +CC=riscv64-unknown-elf-gcc +DA=riscv64-unknown-elf-objdump -d + + +include $(ROOT)/makefile.inc + + diff --git a/testsBP/simple/fail.s b/testsBP/simple/fail.s new file mode 100644 index 00000000..552604fe --- /dev/null +++ b/testsBP/simple/fail.s @@ -0,0 +1,11 @@ +# Ross Thompson +# March 17, 2021 +# Oklahoma State University + +.section .text +.global fail +.type fail, @function +fail: + li gp, 1 + li a0, -1 + ecall diff --git a/testsBP/simple/header.h b/testsBP/simple/header.h new file mode 100644 index 00000000..b5268fbf --- /dev/null +++ b/testsBP/simple/header.h @@ -0,0 +1,6 @@ +#ifndef __header +#define __header + +int fail(); +int simple_csrbr_test(); +#endif diff --git a/testsBP/simple/main.c b/testsBP/simple/main.c new file mode 100644 index 00000000..047a52f8 --- /dev/null +++ b/testsBP/simple/main.c @@ -0,0 +1,10 @@ +#include "header.h" + +int main(){ + int res = simple_csrbr_test(); + if (res < 0) { + fail(); + return 0; + }else + return 0; +} diff --git a/testsBP/simple/sample.s b/testsBP/simple/sample.s new file mode 100644 index 00000000..1c707cba --- /dev/null +++ b/testsBP/simple/sample.s @@ -0,0 +1,61 @@ +.section .text +.global simple_csrbr_test +.type simple_csrbr_test, @function + +simple_csrbr_test: + + # step 1 enable the performance counters + # by default the hardware enables all performance counters + # however we will eventually want to manually enable incase + # some other code disables them + + # br count is counter 5 + # br mp count is counter 4 + li t0, 0x30 + + csrrc x0, 0x320, t0 # clear bits 4 and 5 of inhibit register. + + # step 2 read performance counters into general purpose registers + + csrrw t2, 0xB05, x0 # t2 = BR COUNT (perf count 5) + csrrw t3, 0xB04, x0 # t3 = BRMP COUNT (perf count 4) + + # step 3 simple loop to show the counters are updated. + li t0, 0 # this is the loop counter + li t1, 100 # this is the loop end condition + + # for(t1 = 0; t1 < t0; t1++); + +loop: + addi t0, t0, 1 + blt t0, t1, loop + +loop_done: + + # step 2 read performance counters into general purpose registers + + csrrw t4, 0xB05, x0 # t4 = BR COUNT (perf count 5) + csrrw t5, 0xB04, x0 # t5 = BRMP COUNT (perf count 4) + + sub t2, t4, t2 # this is the number of branch instructions committed. + sub t3, t5, t3 # this is the number of branch mispredictions committed. + + # now check if the branch count equals 100 and if the branch + bne t4, t2, fail + li t5, 3 + bne t3, t5, fail + +pass: + li a0, 0 +done: + li t0, 0x30 + csrrs x0, 0x320, t0 # set bits 4 and 5 + ret + +fail: + li a0, -1 + j done + +.data +sample_data: +.int 0 diff --git a/wally-pipelined/bin/exe2memfile.pl b/wally-pipelined/bin/exe2memfile.pl index 79b975c7..51af9ed6 100755 --- a/wally-pipelined/bin/exe2memfile.pl +++ b/wally-pipelined/bin/exe2memfile.pl @@ -43,43 +43,48 @@ for(my $i=0; $i<=$#ARGV; $i++) { my $address; # initialize to all zeros; + # *** need to fix the zeroing range. Not always 64K for (my $i=0; $i < 65536*4; $i++) { $memfilebytes[$i] = "00"; } while() { if ($mode == 0) { # Parse code - # print("Examining $_\n"); - if (/^\s*(\S\S\S\S\S\S\S\S):\s+(\S+)\s+/) { +# print("Examining $_\n"); + if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { $address = &fixadr($1); my $instr = $2; my $len = length($instr); for (my $i=0; $i<$len/2; $i++) { $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); } - # print ("address $address $instr\n"); - } - if (/Disassembly of section .data:/) { $mode = 1;} +# print ("address $address $instr\n"); + } + if (/Disassembly of section .data:/) { $mode = 1;} } elsif ($mode == 1) { # Parse data segment - if (/^\s*(\S\S\S\S\S\S\S\S):\s+(.*)/) { + if (/^\s*(\S{1,16}):\s+(.*)/) { $address = &fixadr($1); - # print "addresss $address maxaddress $maxaddress\n"; - if ($address > $maxaddress) { $maxaddress = $address; } +# print "addresss $address maxaddress $maxaddress\n"; + if ($address > $maxaddress) { $maxaddress = $address; } my $line = $2; # merge chunks with spaces + # *** might need to change $line =~ s/(\S)\s(\S)/$1$2/g; # strip off comments $line =~ /^(\S*)/; $payload = $1; &emitData($address, $payload); } - if (/Disassembly of section .riscv.attributes:/) { $mode = 2; } + if (/Disassembly of section .comment:/) { $mode = 2; } + } elsif ($mode == 2) { # parse the comment section + if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } } } close(FILE); $maxaddress += 32; # pad some zeros at the end # print to memory file + # *** this is a problem if ($fname =~ /rv32/) { open(MEMFILE, ">$memfile") || die("Can't write $memfile"); for (my $i=0; $i<= $maxaddress; $i = $i + 4) { @@ -133,7 +138,8 @@ sub emitData { sub fixadr { # strip off leading 8 from address and convert to decimal + # if the leading 8 is not present don't remove. my $adr = shift; if ($adr =~ s/^8/0/) { return hex($adr); } - else { die("address $adr lacks leading 8\n"); } + else { return hex($adr) } } diff --git a/wally-pipelined/bin/exe2memfile0.pl b/wally-pipelined/bin/exe2memfile0.pl new file mode 100755 index 00000000..8fbea6f8 --- /dev/null +++ b/wally-pipelined/bin/exe2memfile0.pl @@ -0,0 +1,145 @@ +#!/usr/bin/perl -w + +# exe2memfile.pl +# David_Harris@hmc.edu 26 November 2020 +# Converts an executable file to a series of 32-bit hex instructions +# to read into a Verilog simulation with $readmemh + +use File::stat; +use IO::Handle; + +if ($#ARGV == -1) { + die("Usage: $0 executable_file"); +} + +# array to hold contents of memory file +my @memfilebytes = (0)*16384*4; +my $maxaddress = 0; + +STDOUT->autoflush(1); +# *** Ross Thompson I think there is a bug here needs to be +1 +print ("Processing $#ARGV memfiles: "); +my $frac = $#ARGV/10; +for(my $i=0; $i<=$#ARGV; $i++) { + if ($i < 10 || $i % $frac == 0) { print ("$i ") }; + my $fname = $ARGV[$i]; +# print "fname = $fname"; + my $ofile = $fname.".objdump"; + my $memfile = $fname.".memfile"; + + my $needsprocessing = 0; + if (!-e $memfile) { $needsprocessing = 1; } # create memfile if it doesn't exist + else { + my $osb = stat($ofile) || die("Can't stat $ofile"); + my $msb = stat($memfile) || die("Can't stat $memfile"); + my $otime = $osb->mtime; + my $mtime = $msb->mtime; + if ($otime > $mtime) { $needsprocessing = 1; } # is memfile out of date? + } + + if ($needsprocessing == 1) { + open(FILE, $ofile) || die("Can't read $ofile"); + my $mode = 0; # parse for code + my $address; + + # initialize to all zeros; + # *** need to fix the zeroing range. Not always 64K + for (my $i=0; $i < 65536*4; $i++) { + $memfilebytes[$i] = "00"; + } + + while() { + # *** this mode stuff does not work if a section is missing or reordered. + if ($mode == 0) { # Parse code +# print("Examining $_\n"); + if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { + $address = &fixadr($1); + my $instr = $2; + my $len = length($instr); + for (my $i=0; $i<$len/2; $i++) { + $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); + } +# print ("address $address $instr\n"); + } + if (/Disassembly of section .data:/) { $mode = 1;} + } elsif ($mode == 1) { # Parse data segment + if (/^\s*(\S{1,16}):\s+(.*)/) { + $address = &fixadr($1); +# print "addresss $address maxaddress $maxaddress\n"; + if ($address > $maxaddress) { $maxaddress = $address; } + my $line = $2; + # merge chunks with spaces + # *** might need to change + $line =~ s/(\S)\s(\S)/$1$2/g; + # strip off comments + $line =~ /^(\S*)/; + $payload = $1; + &emitData($address, $payload); + } + if (/Disassembly of section .comment:/) { $mode = 2; } + } elsif ($mode == 2) { # parse the comment section + if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } + } + } + close(FILE); + $maxaddress += 32; # pad some zeros at the end + + # print to memory file + # *** this is a problem + if ($fname =~ /rv32/) { + open(MEMFILE, ">$memfile") || die("Can't write $memfile"); + for (my $i=0; $i<= $maxaddress; $i = $i + 4) { + for ($j=3; $j>=0; $j--) { + print MEMFILE "$memfilebytes[$i+$j]"; + } + print MEMFILE "\n"; + } + close(MEMFILE); + } else { + open(MEMFILE, ">$memfile") || die("Can't write $memfile"); + for (my $i=0; $i<= $maxaddress; $i = $i + 8) { + for ($j=7; $j>=0; $j--) { + print MEMFILE "$memfilebytes[$i+$j]"; + } + print MEMFILE "\n"; + } + close(MEMFILE); + } + } +} +print("\n"); + +sub emitData { + # print the data portion of the ELF into a memroy file, including 0s for empty stuff + # deal with endianness + my $address = shift; + my $payload = shift; + +# print("Emitting data. address = $address payload = $payload\n"); + + my $len = length($payload); + if ($len <= 8) { + # print word or halfword + for(my $i=0; $i<$len/2; $i++) { + my $adr = $address+$i; + my $b = substr($payload, $len-2-2*$i, 2); + $memfilebytes[$adr] = $b; +# print(" $adr $b\n"); + } + } elsif ($len == 12) { + # weird case of three halfwords on line + &emitData($address, substr($payload, 0, 4)); + &emitData($address+2, substr($payload, 4, 4)); + &emitData($address+4, substr($payload, 8, 4)); + } else { + &emitData($address, substr($payload, 0, 8)); + &emitData($address+4, substr($payload, 8, $len-8)); + } +} + +sub fixadr { + # strip off leading 8 from address and convert to decimal + # if the leading 8 is not present don't remove. + my $adr = shift; + return hex($adr); +} diff --git a/wally-pipelined/config/busybear/wally-config.vh b/wally-pipelined/config/busybear/wally-config.vh index 3a619598..cc3693f8 100644 --- a/wally-pipelined/config/busybear/wally-config.vh +++ b/wally-pipelined/config/busybear/wally-config.vh @@ -99,3 +99,4 @@ `define TWO_BIT_PRELOAD "../config/busybear/twoBitPredictor.txt" `define BTB_PRELOAD "../config/busybear/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/coremark/wally-config.vh b/wally-pipelined/config/coremark/wally-config.vh index 5f0714ae..74497064 100644 --- a/wally-pipelined/config/coremark/wally-config.vh +++ b/wally-pipelined/config/coremark/wally-config.vh @@ -101,3 +101,4 @@ `define TWO_BIT_PRELOAD "../config/coremark/twoBitPredictor.txt" `define BTB_PRELOAD "../config/coremark/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/coremark_bare/wally-config.vh b/wally-pipelined/config/coremark_bare/wally-config.vh index 368ae2d2..497f517d 100644 --- a/wally-pipelined/config/coremark_bare/wally-config.vh +++ b/wally-pipelined/config/coremark_bare/wally-config.vh @@ -98,3 +98,4 @@ `define TWO_BIT_PRELOAD "../config/coremark_bare/twoBitPredictor.txt" `define BTB_PRELOAD "../config/coremark_bare/BTBPredictor.txt" `define BPTYPE "BPGSHARE" +`define TESTSBP 0 diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index 5ee1d170..fadbe36c 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -95,3 +95,4 @@ `define TWO_BIT_PRELOAD "../config/rv32ic/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv32ic/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/rv64BP/BTBPredictor.txt b/wally-pipelined/config/rv64BP/BTBPredictor.txt new file mode 100644 index 00000000..b761147c --- /dev/null +++ b/wally-pipelined/config/rv64BP/BTBPredictor.txt @@ -0,0 +1,1024 @@ +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000 diff --git a/wally-pipelined/config/rv64BP/twoBitPredictor.txt b/wally-pipelined/config/rv64BP/twoBitPredictor.txt new file mode 100644 index 00000000..ff57bd47 --- /dev/null +++ b/wally-pipelined/config/rv64BP/twoBitPredictor.txt @@ -0,0 +1,1024 @@ +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh new file mode 100644 index 00000000..bd053750 --- /dev/null +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -0,0 +1,101 @@ +////////////////////////////////////////// +// wally-config.vh +// +// Written: David_Harris@hmc.edu 4 January 2021 +// Modified: Brett Mathis +// +// Purpose: Specify which features are configured +// Macros to determine which modes are supported based on MISA +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +// RV32 or RV64: XLEN = 32 or 64 +`define XLEN 64 + +//`define MISA (32'h00000104) +`define MISA (32'h00000104 | 1<<5 | 1<<18 | 1 << 20) +`define A_SUPPORTED ((`MISA >> 0) % 2 == 1) +`define C_SUPPORTED ((`MISA >> 2) % 2 == 1) +`define D_SUPPORTED ((`MISA >> 3) % 2 == 1) +`define F_SUPPORTED ((`MISA >> 5) % 2 == 1) +`define M_SUPPORTED ((`MISA >> 12) % 2 == 1) +`define S_SUPPORTED ((`MISA >> 18) % 2 == 1) +`define U_SUPPORTED ((`MISA >> 20) % 2 == 1) +`define ZCSR_SUPPORTED 1 +`define COUNTERS 31 +`define ZCOUNTERS_SUPPORTED 1 +// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21 +//`define N_SUPPORTED ((MISA >> 13) % 2 == 1) +`define N_SUPPORTED 0 + +`define M_MODE (2'b11) +`define S_MODE (2'b01) +`define U_MODE (2'b00) + +// Microarchitectural Features +`define UARCH_PIPELINED 1 +`define UARCH_SUPERSCALR 0 +`define UARCH_SINGLECYCLE 0 +`define MEM_DCACHE 0 +`define MEM_DTIM 1 +`define MEM_ICACHE 0 +`define MEM_VIRTMEM 0 + +// Address space +`define RESET_VECTOR 64'h0000000000000000 + +// Bus Interface width +`define AHBW 64 + +// Peripheral Addresses +// Peripheral memory space extends from BASE to BASE+RANGE +// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits + +`define BOOTTIMBASE 32'h00080000 +`define BOOTTIMRANGE 32'h00003FFF +`define TIMBASE 32'h00000000 +`define TIMRANGE 32'h0007FFFF +`define CLINTBASE 32'h02000000 +`define CLINTRANGE 32'h0000FFFF +`define GPIOBASE 32'h10012000 +`define GPIORANGE 32'h000000FF +`define UARTBASE 32'h10000000 +`define UARTRANGE 32'h00000007 +`define PLICBASE 32'h0C000000 +`define PLICRANGE 32'h03FFFFFF + +// Test modes + +// Tie GPIO outputs back to inputs +`define GPIO_LOOPBACK_TEST 0 + +// Busybear special CSR config to match OVPSim +`define OVPSIM_CSR_CONFIG 0 + +// Hardware configuration +`define UART_PRESCALE 1 + +/* verilator lint_off STMTDLY */ +/* verilator lint_off WIDTH */ +/* verilator lint_off ASSIGNDLY */ +/* verilator lint_off PINCONNECTEMPTY */ + +`define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" +`define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" +`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 1 diff --git a/wally-pipelined/config/rv64BP/wally-constants.vh b/wally-pipelined/config/rv64BP/wally-constants.vh new file mode 100644 index 00000000..55fb4e94 --- /dev/null +++ b/wally-pipelined/config/rv64BP/wally-constants.vh @@ -0,0 +1,31 @@ +////////////////////////////////////////// +// wally-constants.vh +// +// Written: tfleming@hmc.edu 4 March 2021 +// Modified: +// +// Purpose: Specify certain constants defined in the RISC-V 64-bit architecture. +// These macros should not be changed, except in the event of an +// update to the architecture or particularly special circumstances. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +// Virtual Memory Constants (sv39) +`define VPN_BITS 27 +`define PPN_BITS 44 +`define PA_BITS 56 diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index c3f9849a..b27a5e1c 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -98,3 +98,4 @@ `define TWO_BIT_PRELOAD "../config/rv64ic/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64ic/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/config/rv64icfd/wally-config.vh b/wally-pipelined/config/rv64icfd/wally-config.vh index 9b3dae29..853b8685 100644 --- a/wally-pipelined/config/rv64icfd/wally-config.vh +++ b/wally-pipelined/config/rv64icfd/wally-config.vh @@ -98,3 +98,4 @@ `define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" `define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define TESTSBP 0 diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index c3772967..d2992fa1 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -4,55 +4,85 @@ add wave -noupdate /testbench/clk add wave -noupdate /testbench/reset add wave -noupdate /testbench/test add wave -noupdate -radix ascii /testbench/memfilename -add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/function_radix/FunctionName +add wave -noupdate -expand -group {Execution Stage} /testbench/FunctionName/FunctionName/FunctionName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/InstrStall -add wave -noupdate -group HDU -expand -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM -add wave -noupdate -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF -add wave -noupdate -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushM +add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushW +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallF +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallD +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM +add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW +add wave -noupdate -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF +add wave -noupdate -group Bpred -expand -group direction -divider Lookup +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/BPPredF +add wave -noupdate -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/BPPredPCF +add wave -noupdate -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/SelBPPredF add wave -noupdate -group Bpred -expand -group direction -divider Update add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC +add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD +add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group Bpred -group BTB -divider Update -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget -add wave -noupdate -group Bpred -group BTB -divider Lookup -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid +add wave -noupdate -group Bpred -group {bp wrong} -divider pcs +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD +add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE +add wave -noupdate -group Bpred -expand -group BTB -divider Update +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ +add wave -noupdate -group Bpred -expand -group BTB -divider Lookup +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass +add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory +add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE @@ -66,12 +96,12 @@ add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -group {Decode Stage} /testbench/InstrDName -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -expand -group {Decode Stage} /testbench/InstrDName +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 @@ -82,7 +112,6 @@ add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/PCLinkW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW @@ -99,10 +128,10 @@ add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM -add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM +add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM +add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM +add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E @@ -126,23 +155,29 @@ add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE add wave -noupdate -expand -group PCS /testbench/dut/hart/PCM add wave -noupdate -expand -group PCS /testbench/PCW -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr -add wave -noupdate -group {function radix debug} -radix unsigned /testbench/functionRadix/function_radix/ProgramAddrIndex -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/reset -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapLineCount -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapLine -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapFP -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramLabelMapFile -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapLineCount -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapLine -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapFP -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrMapFile -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/pc -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex -add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr +add wave -noupdate -group {function radix debug} -radix unsigned /testbench/FunctionName/FunctionName/ProgramAddrIndex +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/reset +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapLineCount +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapLine +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapFP +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramLabelMapFile +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapLineCount +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapLine +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapFP +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrMapFile +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrIndex +add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionName +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW +add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/genblk1/HPMCOUNTER_REGW +add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate /testbench/dut/hart/priv/csr/genblk1/counters/CSRCReadValM TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {3758805 ns} 0} +WaveRestoreCursors {{Cursor 7} {13518 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -158,4 +193,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {1644110 ns} {15262484 ns} +WaveRestoreZoom {13489 ns} {13607 ns} diff --git a/wally-pipelined/src/ieu/datapath.sv b/wally-pipelined/src/ieu/datapath.sv index adcd4f6d..f94e665e 100644 --- a/wally-pipelined/src/ieu/datapath.sv +++ b/wally-pipelined/src/ieu/datapath.sv @@ -115,9 +115,6 @@ module datapath ( flopenrc #(`XLEN) ALUResultWReg(clk, reset, FlushW, ~StallW, ALUResultM, ALUResultW); flopenrc #(5) RdWEg(clk, reset, FlushW, ~StallW, RdM, RdW); - // *** something is not right here. Before the merge I found an issue with the jal instruction not writing - // the link address through the alu. - // not sure what changed. // handle Store Conditional result if atomic extension supported generate if (`A_SUPPORTED) diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index d7848e4b..b342c11b 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -33,20 +33,24 @@ module BTBPredictor ) (input logic clk, input logic reset, + input logic StallF, StallD, StallE, FlushF, FlushD, FlushE, input logic [`XLEN-1:0] LookUpPC, output logic [`XLEN-1:0] TargetPC, - output logic [3:0] InstrClass, + output logic [4:0] InstrClass, output logic Valid, // update input logic UpdateEN, input logic [`XLEN-1:0] UpdatePC, input logic [`XLEN-1:0] UpdateTarget, - input logic [3:0] UpdateInstrClass + input logic [3:0] UpdateInstrClass, + input logic UpdateInvalid ); localparam TotalDepth = 2 ** Depth; logic [TotalDepth-1:0] ValidBits; logic [Depth-1:0] LookUpPCIndex, UpdatePCIndex, LookUpPCIndexQ, UpdatePCIndexQ; + logic UpdateENQ; + // hashing function for indexing the PC // We have Depth bits to index, but XLEN bits as the input. @@ -58,7 +62,7 @@ module BTBPredictor flopenr #(Depth) UpdatePCIndexReg(.clk(clk), .reset(reset), - .en(1'b1), + .en(~StallE), .d(UpdatePCIndex), .q(UpdatePCIndexQ)); @@ -66,32 +70,53 @@ module BTBPredictor always_ff @ (posedge clk) begin if (reset) begin ValidBits <= #1 {TotalDepth{1'b0}}; - end else if (UpdateEN) begin - ValidBits[UpdatePCIndexQ] <= #1 1'b1; + end else + if (UpdateENQ) begin + ValidBits[UpdatePCIndexQ] <= #1 ~ UpdateInvalid; end end + assign Valid = ValidBits[LookUpPCIndexQ]; + +/* -----\/----- EXCLUDED -----\/----- + + regfile2p1r1w #(10, 1) validMem(.clk(clk), + .reset(reset), + .RA1(LookUpPCIndexQ), + .RD1(Valid), + .REN1(1'b1), + .WA1(UpdatePCIndexQ), + .WD1(1'b1), + .WEN1(UpdateEN)); + -----/\----- EXCLUDED -----/\----- */ + + flopenr #() UpdateENReg(.clk(clk), + .reset(reset), + .en(~StallF), + .d(UpdateEN), + .q(UpdateENQ)); + flopenr #(Depth) LookupPCIndexReg(.clk(clk), .reset(reset), - .en(1'b1), + .en(~StallF), .d(LookUpPCIndex), .q(LookUpPCIndexQ)); - assign Valid = ValidBits[LookUpPCIndexQ]; + // the BTB contains the target address. // Another optimization may be using a PC relative address. // *** need to add forwarding. - SRAM2P1R1W #(Depth, `XLEN+4) memory(.clk(clk), + SRAM2P1R1W #(Depth, `XLEN+5) memory(.clk(clk), .reset(reset), .RA1(LookUpPCIndex), .RD1({{InstrClass, TargetPC}}), - .REN1(1'b1), + .REN1(~StallF), .WA1(UpdatePCIndex), .WD1({UpdateInstrClass, UpdateTarget}), .WEN1(UpdateEN), - .BitWEN1({4'b0000, {`XLEN{1'b1}}})); // *** definitely not right. + .BitWEN1({5'h1F, {`XLEN{1'b1}}})); // *** definitely not right. endmodule diff --git a/wally-pipelined/src/ifu/RAsPredictor.sv b/wally-pipelined/src/ifu/RAsPredictor.sv index 9090878d..166ff911 100644 --- a/wally-pipelined/src/ifu/RAsPredictor.sv +++ b/wally-pipelined/src/ifu/RAsPredictor.sv @@ -42,7 +42,7 @@ module RASPredictor logic CounterEn; localparam Depth = $clog2(StackSize); - logic [StackSize-1:0] PtrD, PtrQ, PtrP1, PtrM1; + logic [Depth-1:0] PtrD, PtrQ, PtrP1, PtrM1; logic [StackSize-1:0] [`XLEN-1:0] memory; integer index; diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index 38d95948..ba9c688d 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -47,7 +47,7 @@ module bpred input logic [`XLEN-1:0] PCTargetE, // The branch destination if the branch is taken. input logic [`XLEN-1:0] PCD, // The address the branch predictor took. input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) - input logic [3:0] InstrClassE, + input logic [4:0] InstrClassE, // Report branch prediction status output logic BPPredWrongE ); @@ -55,12 +55,14 @@ module bpred logic BTBValidF; logic [1:0] BPPredF, BPPredD, BPPredE, UpdateBPPredE; - logic [3:0] BPInstrClassF, BPInstrClassD, BPInstrClassE; + logic [4:0] BPInstrClassF, BPInstrClassD, BPInstrClassE; logic [`XLEN-1:0] BTBPredPCF, RASPCF; logic TargetWrongE; logic FallThroughWrongE; logic PredictionDirWrongE; logic PredictionPCWrongE; + logic PredictionInstrClassWrongE; + logic [`XLEN-1:0] CorrectPCE; @@ -74,7 +76,7 @@ module bpred .Prediction(BPPredF), // update .UpdatePC(PCE), - .UpdateEN(InstrClassE[0]), + .UpdateEN(InstrClassE[0] & ~StallE), .UpdatePrediction(UpdateBPPredE)); end else if (`BPTYPE == "BPGLOBAL") begin:Predictor @@ -86,7 +88,7 @@ module bpred .Prediction(BPPredF), // update .UpdatePC(PCE), - .UpdateEN(InstrClassE[0]), + .UpdateEN(InstrClassE[0] & ~StallE), .PCSrcE(PCSrcE), .UpdatePrediction(UpdateBPPredE)); end else if (`BPTYPE == "BPGSHARE") begin:Predictor @@ -98,7 +100,7 @@ module bpred .Prediction(BPPredF), // update .UpdatePC(PCE), - .UpdateEN(InstrClassE[0]), + .UpdateEN(InstrClassE[0] & ~StallE), .PCSrcE(PCSrcE), .UpdatePrediction(UpdateBPPredE)); end @@ -119,16 +121,19 @@ module bpred // Part 2 Branch target address prediction // *** For now the BTB will house the direct and indirect targets + // *** getting to many false positivies from the BTB, we need a partial TAG to reduce this. BTBPredictor TargetPredictor(.clk(clk), .reset(reset), + .*, // Stalls and flushes .LookUpPC(PCNextF), .TargetPC(BTBPredPCF), .InstrClass(BPInstrClassF), .Valid(BTBValidF), // update - .UpdateEN(InstrClassE[2] | InstrClassE[1] | InstrClassE[0]), + .UpdateEN((|InstrClassE | (PredictionInstrClassWrongE)) & ~StallE), .UpdatePC(PCE), .UpdateTarget(PCTargetE), + .UpdateInvalid(PredictionInstrClassWrongE), .UpdateInstrClass(InstrClassE)); // need to forward when updating to the same address as reading. @@ -139,9 +144,9 @@ module bpred // *** need to add the logic to restore RAS on flushes. We will use incr for this. RASPredictor RASPredictor(.clk(clk), .reset(reset), - .pop(BPInstrClassF[3]), + .pop(BPInstrClassF[3] & ~StallF), .popPC(RASPCF), - .push(InstrClassE[3]), + .push(InstrClassE[4] & ~StallE), .incr(1'b0), .pushPC(PCLinkE)); @@ -188,7 +193,8 @@ module bpred assign FallThroughWrongE = PCLinkE != PCD; assign PredictionDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0]; assign PredictionPCWrongE = PCSrcE ? TargetWrongE : FallThroughWrongE; - assign BPPredWrongE = (PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE); + assign PredictionInstrClassWrongE = InstrClassE != BPInstrClassE; + assign BPPredWrongE = ((PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE)) | PredictionInstrClassWrongE; // Update predictors diff --git a/wally-pipelined/src/ifu/gshare.sv b/wally-pipelined/src/ifu/gshare.sv index a1c5bbc7..8af54145 100644 --- a/wally-pipelined/src/ifu/gshare.sv +++ b/wally-pipelined/src/ifu/gshare.sv @@ -42,22 +42,24 @@ module gsharePredictor ); - logic [k-1:0] GHRF, GHRD, GHRE; - logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE; + logic [k-1:0] GHRF, GHRD, GHRE, GHRENext; + //logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE; logic [k-1:0] LookUpPCIndex, UpdatePCIndex; logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF; logic [1:0] UpdatePredictionF; + + assign GHRENext = {PCSrcE, GHRE[k-1:1]}; flopenr #(k) GlobalHistoryRegister(.clk(clk), .reset(reset), .en(UpdateEN), - .d({PCSrcE, GHRF[k-1:1] }), + .d(GHRENext), .q(GHRF)); // for gshare xor the PC with the GHR - assign UpdatePCIndex = GHRE ^ UpdatePC[k:1]; + assign UpdatePCIndex = GHRENext ^ UpdatePC[k:1]; assign LookUpPCIndex = GHRF ^ LookUpPC[k:1]; // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT // GHR referes to the address that the past k branches points to in the prediction stage @@ -66,7 +68,7 @@ module gsharePredictor .reset(reset), .RA1(LookUpPCIndex), .RD1(PredictionMemory), - .REN1(1'b1), + .REN1(~StallF), .WA1(UpdatePCIndex), .WD1(UpdatePrediction), .WEN1(UpdateEN), @@ -92,6 +94,7 @@ module gsharePredictor assign Prediction = DoForwardingF ? UpdatePredictionF : PredictionMemory; //pipeline for GHR +/* -----\/----- EXCLUDED -----\/----- flopenrc #(k) LookUpDReg(.clk(clk), .reset(reset), .en(~StallD), @@ -105,5 +108,21 @@ module gsharePredictor .clear(FlushE), .d(LookUpPCIndexD), .q(LookUpPCIndexE)); + -----/\----- EXCLUDED -----/\----- */ + + flopenrc #(k) GHRRegD(.clk(clk), + .reset(reset), + .en(~StallD), + .clear(FlushD), + .d(GHRF), + .q(GHRD)); + + flopenrc #(k) GHRRegE(.clk(clk), + .reset(reset), + .en(~StallE), + .clear(FlushE), + .d(GHRD), + .q(GHRE)); + endmodule diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 35844fca..90bce2d1 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -85,7 +85,7 @@ module ifu ( // branch predictor signals logic SelBPPredF; logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F; - logic [3:0] InstrClassD, InstrClassE; + logic [4:0] InstrClassD, InstrClassE; // *** put memory interface on here, InstrF becomes output @@ -131,7 +131,7 @@ module ifu ( .reset(reset), .StallF(StallF), .StallD(StallD), - .StallE(1'b0), // *** may need this eventually + .StallE(StallE), .FlushF(FlushF), .FlushD(FlushD), .FlushE(FlushE), @@ -169,8 +169,9 @@ module ifu ( // the branch predictor needs a compact decoding of the instruction class. // *** consider adding in the alternate return address x5 for returns. - assign InstrClassD[3] = InstrD[6:0] == 7'h67 && InstrD[19:15] == 5'h01; // return - assign InstrClassD[2] = InstrD[6:0] == 7'h67 && InstrD[19:15] != 5'h01; // jump register, but not return + assign InstrClassD[4] = (InstrD[6:0] & 7'h77) == 7'h67 && (InstrD[11:07] & 5'h1B) == 5'h01; // jal(r) must link to ra or r5 + assign InstrClassD[3] = InstrD[6:0] == 7'h67 && (InstrD[19:15] & 5'h1B) == 5'h01; // return must link to ra or r5 + assign InstrClassD[2] = InstrD[6:0] == 7'h67 && (InstrD[19:15] & 5'h1B) != 5'h01; // jump register, but not return assign InstrClassD[1] = InstrD[6:0] == 7'h6F; // jump assign InstrClassD[0] = InstrD[6:0] == 7'h63; // branch @@ -197,14 +198,14 @@ module ifu ( flopenr #(`XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); // flopenr #(`XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW); // *** probably not needed; delete later - flopenrc #(4) InstrClassRegE(.clk(clk), + flopenrc #(5) InstrClassRegE(.clk(clk), .reset(reset), .en(~StallE), .clear(FlushE), .d(InstrClassD), .q(InstrClassE)); - flopenrc #(4) InstrClassRegM(.clk(clk), + flopenrc #(5) InstrClassRegM(.clk(clk), .reset(reset), .en(~StallM), .clear(FlushM), diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index 0c38b688..79e81303 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -28,7 +28,7 @@ module csr ( input logic clk, reset, - input logic FlushW, StallW, + input logic FlushW, StallD, StallE, StallM, StallW, input logic [31:0] InstrM, input logic [`XLEN-1:0] PCM, SrcAM, input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM, diff --git a/wally-pipelined/src/privileged/csrc.sv b/wally-pipelined/src/privileged/csrc.sv index dbf21e91..ba90a48a 100644 --- a/wally-pipelined/src/privileged/csrc.sv +++ b/wally-pipelined/src/privileged/csrc.sv @@ -29,8 +29,9 @@ module csrc ( input logic clk, reset, + input logic StallD, StallE, StallM, StallW, input logic InstrValidW, LoadStallD, CSRMWriteM, BPPredWrongM, - input logic [3:0] InstrClassM, + input logic [3:0] InstrClassM, input logic [11:0] CSRAdrM, input logic [1:0] PrivilegeModeW, input logic [`XLEN-1:0] CSRWriteValM, @@ -61,10 +62,10 @@ module csrc ( logic [`COUNTERS:0] MCOUNTEN; assign MCOUNTEN[0] = 1'b1; assign MCOUNTEN[1] = 1'b0; - assign MCOUNTEN[2] = InstrValidW; - assign MCOUNTEN[3] = LoadStallD; - assign MCOUNTEN[4] = BPPredWrongM; - assign MCOUNTEN[5] = InstrClassM[0]; + assign MCOUNTEN[2] = InstrValidW & ~StallW; + assign MCOUNTEN[3] = LoadStallD & ~StallD; + assign MCOUNTEN[4] = BPPredWrongM & ~StallM; + assign MCOUNTEN[5] = InstrClassM[0] & ~StallM; assign MCOUNTEN[`COUNTERS:6] = 0; genvar j; @@ -91,7 +92,7 @@ module csrc ( // Write / update counters // Only the Machine mode versions of the counter CSRs are writable if (`XLEN==64) begin // 64-bit counters - flopr #(64) HPMCOUNTERreg_j(clk, reset, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j]); + flopenr #(64) HPMCOUNTERreg_j(clk, reset, ~StallW, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j]); end else begin // 32-bit low and high counters logic [`COUNTERS:0] WriteHPMCOUNTERHM; @@ -102,8 +103,8 @@ module csrc ( assign NextHPMCOUNTERHM[j] = WriteHPMCOUNTERHM[j] ? CSRWriteValM : HPMCOUNTERPlusM[j][63:32]; // Counter CSRs - flopr #(32) HPMCOUNTERreg_j(clk, reset, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j][31:0]); - flopr #(32) HPMCOUNTERHreg_j(clk, reset, NextHPMCOUNTERHM[j], HPMCOUNTER_REGW[j][63:32]); + flopenr #(32) HPMCOUNTERreg_j(clk, reset, ~StallW, NextHPMCOUNTERM[j], HPMCOUNTER_REGW[j][31:0]); + flopenr #(32) HPMCOUNTERHreg_j(clk, reset, ~StallW, NextHPMCOUNTERHM[j], HPMCOUNTER_REGW[j][63:32]); end end // end for diff --git a/wally-pipelined/src/privileged/csri.sv b/wally-pipelined/src/privileged/csri.sv index 488c6ba4..d08ed201 100644 --- a/wally-pipelined/src/privileged/csri.sv +++ b/wally-pipelined/src/privileged/csri.sv @@ -33,6 +33,7 @@ module csri #(parameter SIE = 12'h104, SIP = 12'h144) ( input logic clk, reset, + input logic StallW, input logic CSRMWriteM, CSRSWriteM, input logic [11:0] CSRAdrM, input logic ExtIntM, TimerIntM, SwIntM, @@ -59,10 +60,10 @@ module csri #(parameter end // Interrupt Write Enables - assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP); - assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE); - assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP); - assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE); + assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP) && ~StallW; + assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE) && ~StallW; + assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP) && ~StallW; + assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE) && ~StallW; // Interrupt Pending and Enable Registers // MEIP, MTIP, MSIP are read-only diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index 73c42608..471872e8 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -75,6 +75,7 @@ module csrm #(parameter DSCRATCH0 = 12'h7B2, DSCRATCH1 = 12'h7B3) ( input logic clk, reset, + input logic StallW, input logic CSRMWriteM, MTrapM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW, @@ -107,34 +108,34 @@ module csrm #(parameter assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISAbits}; // Write machine Mode CSRs - assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS); - assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC); - assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG); - assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG); - assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH); - assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)); - assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)); - assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)); - assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)); - assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)); - assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0)); - assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1)); - assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2)); - assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3)); - assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4)); - assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5)); - assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6)); - assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7)); - assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8)); - assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9)); - assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10)); - assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11)); - assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12)); - assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13)); - assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14)); - assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)); - assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN); - assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT); + assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS) && ~StallW; + assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC) && ~StallW; + assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG) && ~StallW; + assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG) && ~StallW; + assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH) && ~StallW; + assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)) && ~StallW; + assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)) && ~StallW; + assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)) && ~StallW; + assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)) && ~StallW; + assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)) && ~StallW; + assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0)) && ~StallW; + assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1)) && ~StallW; + assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2)) && ~StallW; + assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3)) && ~StallW; + assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4)) && ~StallW; + assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5)) && ~StallW; + assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6)) && ~StallW; + assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7)) && ~StallW; + assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8)) && ~StallW; + assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9)) && ~StallW; + assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10)) && ~StallW; + assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11)) && ~StallW; + assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12)) && ~StallW; + assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13)) && ~StallW; + assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14)) && ~StallW; + assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)) && ~StallW; + assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN) && ~StallW; + assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT) && ~StallW; // CSRs flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, `XLEN'b0, MTVEC_REGW); //busybear: changed reset value to 0 diff --git a/wally-pipelined/src/privileged/csrn.sv b/wally-pipelined/src/privileged/csrn.sv index a3b3178b..2aa44bdf 100644 --- a/wally-pipelined/src/privileged/csrn.sv +++ b/wally-pipelined/src/privileged/csrn.sv @@ -36,6 +36,7 @@ module csrn #(parameter UTVAL = 12'h043, UIP = 12'h044) ( input logic clk, reset, + input logic StallW, input logic CSRNWriteM, UTrapM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, USTATUS_REGW, @@ -56,11 +57,11 @@ module csrn #(parameter logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW; // Write enables - assign WriteUSTATUSM = CSRNWriteM && (CSRAdrM == USTATUS); - assign WriteUTVECM = CSRNWriteM && (CSRAdrM == UTVEC); - assign WriteUEPCM = UTrapM | (CSRNWriteM && (CSRAdrM == UEPC)); - assign WriteUCAUSEM = UTrapM | (CSRNWriteM && (CSRAdrM == UCAUSE)); - assign WriteUTVALM = UTrapM | (CSRNWriteM && (CSRAdrM == UTVAL)); + assign WriteUSTATUSM = CSRNWriteM && (CSRAdrM == USTATUS) && ~StallW; + assign WriteUTVECM = CSRNWriteM && (CSRAdrM == UTVEC) && ~StallW; + assign WriteUEPCM = UTrapM | (CSRNWriteM && (CSRAdrM == UEPC)) && ~StallW; + assign WriteUCAUSEM = UTrapM | (CSRNWriteM && (CSRAdrM == UCAUSE)) && ~StallW; + assign WriteUTVALM = UTrapM | (CSRNWriteM && (CSRAdrM == UTVAL)) && ~StallW; // CSRs flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, CSRWriteValM, `RESET_VECTOR, UTVEC_REGW); @@ -95,4 +96,4 @@ module csrn #(parameter assign IllegalCSRNAccessM = 1; end endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/wally-pipelined/src/privileged/csrs.sv b/wally-pipelined/src/privileged/csrs.sv index ede8274a..c53f98d5 100644 --- a/wally-pipelined/src/privileged/csrs.sv +++ b/wally-pipelined/src/privileged/csrs.sv @@ -41,6 +41,7 @@ module csrs #(parameter SIP= 12'h144, SATP = 12'h180) ( input logic clk, reset, + input logic StallW, input logic CSRSWriteM, STrapM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW, @@ -66,14 +67,14 @@ module csrs #(parameter logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW; - assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS); - assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC); - assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH); - assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC)); - assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE)); - assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL)); - assign WriteSATPM = STrapM | (CSRSWriteM && (CSRAdrM == SATP)); - assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN); + assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW; + assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW; + assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH) && ~StallW; + assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC)) && ~StallW; + assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE)) && ~StallW; + assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL)) && ~StallW; + assign WriteSATPM = STrapM | (CSRSWriteM && (CSRAdrM == SATP)) && ~StallW; + assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW; // CSRs flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, zero, STVEC_REGW); //busybear: change reset to 0 diff --git a/wally-pipelined/src/privileged/csru.sv b/wally-pipelined/src/privileged/csru.sv index 0fad64bf..ad309594 100644 --- a/wally-pipelined/src/privileged/csru.sv +++ b/wally-pipelined/src/privileged/csru.sv @@ -32,6 +32,7 @@ module csru #(parameter FRM = 12'h002, FCSR = 12'h003) ( input logic clk, reset, + input logic StallW, input logic CSRUWriteM, input logic [11:0] CSRAdrM, input logic [`XLEN-1:0] CSRWriteValM, @@ -50,9 +51,9 @@ module csru #(parameter logic [4:0] NextFFLAGSM; // Write enables - assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR); - assign WriteFFLAGSM = CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM ; - assign WriteFRMM = CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM; + assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR) && ~StallW; + assign WriteFFLAGSM = (CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM) && ~StallW; + assign WriteFRMM = (CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM) && ~StallW; // Write Values assign NextFRMM = WriteFCSRM ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; @@ -81,4 +82,4 @@ module csru #(parameter assign IllegalCSRUAccessM = 1; end endgenerate -endmodule \ No newline at end of file +endmodule diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 16a3d5db..4973e64b 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -49,7 +49,7 @@ module privileged ( output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, output logic [2:0] FRM_REGW, - input logic FlushD, FlushE, FlushM, StallD, StallW, StallE, StallM + input logic FlushD, FlushE, FlushM, StallD, StallE, StallM, StallW ); logic [1:0] NextPrivilegeModeM; diff --git a/wally-pipelined/testbench/function_radix.sv b/wally-pipelined/testbench/function_radix.sv index e6bd479f..20e2ff13 100644 --- a/wally-pipelined/testbench/function_radix.sv +++ b/wally-pipelined/testbench/function_radix.sv @@ -27,9 +27,10 @@ `include "wally-config.vh" -module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); +module FunctionName(reset, clk, ProgramAddrMapFile, ProgramLabelMapFile); input logic reset; + input logic clk; input string ProgramAddrMapFile; input string ProgramLabelMapFile; @@ -38,13 +39,23 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); string FunctionName; - logic [`XLEN-1:0] pc, FunctionAddr; + logic [`XLEN-1:0] PCF, PCD, PCE, FunctionAddr; + logic StallD, StallE, FlushD, FlushE; integer ProgramAddrIndex; - // *** I should look into the system verilog objects instead of signal spy. - initial begin - $init_signal_spy("/testbench/dut/hart/PCE", "/testbench/functionRadix/function_radix/pc"); - end + assign PCF = testbench.dut.hart.PCF; + assign StallD = testbench.dut.hart.StallD; + assign StallE = testbench.dut.hart.StallE; + assign FlushD = testbench.dut.hart.FlushD; + assign FlushE = testbench.dut.hart.FlushE; + + // copy from ifu + // when the F and D stages are flushed we need to ensure the PCE is held so that the function name does not + // erroneously change. + flopenrc #(`XLEN) PCDReg(clk, reset, 1'b0, ~StallD, FlushE & FlushD ? PCE : PCF, PCD); + flopenr #(`XLEN) PCEReg(clk, reset, ~StallE, FlushE ? PCE : PCD, PCE); + + task automatic bin_search_min; input logic [`XLEN-1:0] pc; @@ -74,7 +85,7 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); end else if( array[mid] > pc) begin right = mid -1; end else begin - $display("Critical Error in function radix. PC, %x not found.", pc); + $display("Critical Error in FunctionName. PC, %x not found.", pc); return; //$stop(); end @@ -141,8 +152,8 @@ module function_radix(reset, ProgramAddrMapFile, ProgramLabelMapFile); end - always @(pc) begin - bin_search_min(pc, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex); + always @(PCE) begin + bin_search_min(PCE, ProgramAddrMapLineCount, ProgramAddrMapMemory, FunctionAddr, ProgramAddrIndex); end diff --git a/wally-pipelined/testbench/testbench-busybear.sv b/wally-pipelined/testbench/testbench-busybear.sv index 8a75eb81..5209b2bc 100644 --- a/wally-pipelined/testbench/testbench-busybear.sv +++ b/wally-pipelined/testbench/testbench-busybear.sv @@ -39,7 +39,7 @@ module testbench_busybear(); // read pc trace file integer data_file_PC, scan_file_PC; initial begin - data_file_PC = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r"); + data_file_PC = $fopen("../../../busybear_boot/parsedPC.txt", "r"); if (data_file_PC == 0) begin $display("file couldn't be opened"); $stop; @@ -48,7 +48,7 @@ module testbench_busybear(); integer data_file_PCW, scan_file_PCW; initial begin - data_file_PCW = $fopen("/courses/e190ax/busybear_boot/parsedPC.txt", "r"); + data_file_PCW = $fopen("../../../busybear_boot/parsedPC.txt", "r"); if (data_file_PCW == 0) begin $display("file couldn't be opened"); $stop; @@ -58,7 +58,7 @@ module testbench_busybear(); // read register trace file integer data_file_rf, scan_file_rf; initial begin - data_file_rf = $fopen("/courses/e190ax/busybear_boot/parsedRegs.txt", "r"); + data_file_rf = $fopen("../../../busybear_boot/parsedRegs.txt", "r"); if (data_file_rf == 0) begin $display("file couldn't be opened"); $stop; @@ -68,7 +68,7 @@ module testbench_busybear(); // read CSR trace file integer data_file_csr, scan_file_csr; initial begin - data_file_csr = $fopen("/courses/e190ax/busybear_boot/parsedCSRs.txt", "r"); + data_file_csr = $fopen("../../../busybear_boot/parsedCSRs.txt", "r"); if (data_file_csr == 0) begin $display("file couldn't be opened"); $stop; @@ -78,7 +78,7 @@ module testbench_busybear(); // read memreads trace file integer data_file_memR, scan_file_memR; initial begin - data_file_memR = $fopen("/courses/e190ax/busybear_boot/parsedMemRead.txt", "r"); + data_file_memR = $fopen("../../../busybear_boot/parsedMemRead.txt", "r"); if (data_file_memR == 0) begin $display("file couldn't be opened"); $stop; @@ -88,7 +88,7 @@ module testbench_busybear(); // read memwrite trace file integer data_file_memW, scan_file_memW; initial begin - data_file_memW = $fopen("/courses/e190ax/busybear_boot/parsedMemWrite.txt", "r"); + data_file_memW = $fopen("../../../busybear_boot/parsedMemWrite.txt", "r"); if (data_file_memW == 0) begin $display("file couldn't be opened"); $stop; @@ -97,10 +97,10 @@ module testbench_busybear(); // initial loading of memories initial begin - $readmemh("/courses/e190ax/busybear_boot/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3); - $readmemh("/courses/e190ax/busybear_boot/ram.txt", dut.uncore.dtim.RAM); - $readmemh("/courses/e190ax/busybear_boot/bootmem.txt", dut.imem.bootram, 'h1000 >> 3); - $readmemh("/courses/e190ax/busybear_boot/ram.txt", dut.imem.RAM); + $readmemh("../../../busybear_boot/bootmem.txt", dut.uncore.bootdtim.RAM, 'h1000 >> 3); + $readmemh("../../../busybear_boot/ram.txt", dut.uncore.dtim.RAM); + $readmemh("../../../busybear_boot/bootmem.txt", dut.imem.bootram, 'h1000 >> 3); + $readmemh("../../../busybear_boot/ram.txt", dut.imem.RAM); $readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.Predictor.DirPredictor.PHT.memory); $readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.TargetPredictor.memory.memory); end diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 71457d1f..d9b74449 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -28,7 +28,6 @@ module testbench(); parameter DEBUG = 0; - parameter TESTSBP = 0; logic clk; logic reset; @@ -321,7 +320,8 @@ string tests32i[] = { }; string testsBP64[] = '{ - "rv64BP/reg-test", "10000" + "rv64BP/simple", "10000", + "rv64BP/sieve", "1000000" }; string tests[]; string ProgramAddrMapFile, ProgramLabelMapFile; @@ -343,8 +343,8 @@ string tests32i[] = { // pick tests based on modes supported initial if (`XLEN == 64) begin // RV64 - if (TESTSBP) begin - tests = testsBP64; + if(`TESTSBP) begin + tests = testsBP64; end else begin tests = {tests64i}; if (`C_SUPPORTED) tests = {tests, tests64ic}; @@ -485,10 +485,11 @@ string tests32i[] = { end // always @ (negedge clk) // track the current function or global label - if (DEBUG == 1) begin : functionRadix - function_radix function_radix(.reset(reset), - .ProgramAddrMapFile(ProgramAddrMapFile), - .ProgramLabelMapFile(ProgramLabelMapFile)); + if (DEBUG == 1) begin : FunctionName + FunctionName FunctionName(.reset(reset), + .clk(clk), + .ProgramAddrMapFile(ProgramAddrMapFile), + .ProgramLabelMapFile(ProgramLabelMapFile)); end // initialize the branch predictor From 9172e522867f1176561974f2e8cfab18417eb0d5 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 31 Mar 2021 11:54:02 -0500 Subject: [PATCH 29/55] Corrected a number of bugs in the branch predictor. Added performance counters to individually track branches; jumps, jump register, jal, and jalr; return. jump and jump register are special cases of jal and jalr. Similarlly return is a special case of jalr. Also added counters to track if the branch direction was wrong, btb target wrong, or the ras target was wrong. Finally added one more counter to track if the BP incorrectly predicts a non-cfi instruction. --- wally-pipelined/src/ifu/BTBPredictor.sv | 4 +- wally-pipelined/src/ifu/RAsPredictor.sv | 2 +- wally-pipelined/src/ifu/bpred.sv | 46 ++++++++++++++---- wally-pipelined/src/ifu/ifu.sv | 47 +++++++++++-------- wally-pipelined/src/privileged/csr.sv | 8 +++- wally-pipelined/src/privileged/csrc.sv | 31 +++++++----- wally-pipelined/src/privileged/privileged.sv | 8 +++- .../src/wally/wallypipelinedhart.sv | 9 +++- 8 files changed, 107 insertions(+), 48 deletions(-) diff --git a/wally-pipelined/src/ifu/BTBPredictor.sv b/wally-pipelined/src/ifu/BTBPredictor.sv index b342c11b..4b54c0bb 100644 --- a/wally-pipelined/src/ifu/BTBPredictor.sv +++ b/wally-pipelined/src/ifu/BTBPredictor.sv @@ -42,7 +42,7 @@ module BTBPredictor input logic UpdateEN, input logic [`XLEN-1:0] UpdatePC, input logic [`XLEN-1:0] UpdateTarget, - input logic [3:0] UpdateInstrClass, + input logic [4:0] UpdateInstrClass, input logic UpdateInvalid ); @@ -89,7 +89,7 @@ module BTBPredictor .WEN1(UpdateEN)); -----/\----- EXCLUDED -----/\----- */ - flopenr #() UpdateENReg(.clk(clk), + flopenr #(1) UpdateENReg(.clk(clk), .reset(reset), .en(~StallF), .d(UpdateEN), diff --git a/wally-pipelined/src/ifu/RAsPredictor.sv b/wally-pipelined/src/ifu/RAsPredictor.sv index 166ff911..bde30be5 100644 --- a/wally-pipelined/src/ifu/RAsPredictor.sv +++ b/wally-pipelined/src/ifu/RAsPredictor.sv @@ -55,7 +55,7 @@ module RASPredictor // may have to handle a push and an incr at the same time. // *** what happens if jal is executing and there is a return being flushed in Decode? - flopenr #(StackSize) PTR(.clk(clk), + flopenr #(Depth) PTR(.clk(clk), .reset(reset), .en(CounterEn), .d(PtrD), diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index ba9c688d..5de3f4ec 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -49,7 +49,11 @@ module bpred input logic [`XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address) input logic [4:0] InstrClassE, // Report branch prediction status - output logic BPPredWrongE + output logic BPPredWrongE, + output logic BPPredDirWrongE, + output logic BTBPredPCWrongE, + output logic RASPredPCWrongE, + output logic BPPredClassNonCFIWrongE ); logic BTBValidF; @@ -59,7 +63,6 @@ module bpred logic [`XLEN-1:0] BTBPredPCF, RASPCF; logic TargetWrongE; logic FallThroughWrongE; - logic PredictionDirWrongE; logic PredictionPCWrongE; logic PredictionInstrClassWrongE; @@ -172,14 +175,14 @@ module bpred .q(BPPredE)); // pipeline the class - flopenrc #(4) InstrClassRegD(.clk(clk), + flopenrc #(5) InstrClassRegD(.clk(clk), .reset(reset), .en(~StallD), .clear(FlushD), .d(BPInstrClassF), .q(BPInstrClassD)); - flopenrc #(4) InstrClassRegE(.clk(clk), + flopenrc #(5) InstrClassRegE(.clk(clk), .reset(reset), .en(~StallE), .clear(FlushE), @@ -189,13 +192,40 @@ module bpred // Check the prediction makes execution. + + // first check if the target or fallthrough address matches what was predicted. assign TargetWrongE = PCTargetE != PCD; assign FallThroughWrongE = PCLinkE != PCD; - assign PredictionDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0]; - assign PredictionPCWrongE = PCSrcE ? TargetWrongE : FallThroughWrongE; - assign PredictionInstrClassWrongE = InstrClassE != BPInstrClassE; - assign BPPredWrongE = ((PredictionPCWrongE | PredictionDirWrongE) & (|InstrClassE)) | PredictionInstrClassWrongE; + // If the target is taken check the target rather than fallthrough. The instruction needs to be a branch if PCSrcE is selected + // Remember the bpred can incorrectly predict a non cfi instruction as a branch taken. If the real instruction is non cfi + // it must have selected teh fall through. + assign PredictionPCWrongE = (PCSrcE & (|InstrClassE) ? TargetWrongE : FallThroughWrongE); + // The branch direction also need to checked. + // However if the direction is wrong then the pc will be wrong. This is only relavent to checking the + // accuracy of the direciton prediction. + assign BPPredDirWrongE = (BPPredE[1] ^ PCSrcE) & InstrClassE[0]; + + // Finally we need to check if the class is wrong. When the class is wrong the BTB needs to be updated. + // Also we want to track this in a performance counter. + assign PredictionInstrClassWrongE = InstrClassE != BPInstrClassE; + + // We want to output to the instruction fetch if the PC fetched was wrong. If by chance the predictor was wrong about + // the direction or class, but correct about the target we don't have the flush the pipeline. However we still + // need this information to verify the accuracy of the predictors. + + + //assign BPPredWrongE = ((PredictionPCWrongE | BPPredDirWrongE) & (|InstrClassE)) | PredictionInstrClassWrongE; + + assign BPPredWrongE = (PredictionPCWrongE & |InstrClassE) | BPPredClassNonCFIWrongE; + + // If we have a jump, jump register or jal or jalr and the PC is wrong we need to increment the performance counter. + assign BTBPredPCWrongE = (InstrClassE[4] | InstrClassE[2] | InstrClassE[1]) & PredictionPCWrongE; + // similar with RAS + assign RASPredPCWrongE = InstrClassE[3] & PredictionPCWrongE; + // Finally if the real instruction class is non CFI but the predictor said it was we need to count. + assign BPPredClassNonCFIWrongE = PredictionInstrClassWrongE & ~|InstrClassE; + // Update predictors satCounter2 BPDirUpdate(.BrDir(PCSrcE), diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 30e25bea..79d5878a 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -27,14 +27,14 @@ `include "wally-config.vh" module ifu ( - input logic clk, reset, - input logic StallF, StallD, StallE, StallM, StallW, - input logic FlushF, FlushD, FlushE, FlushM, FlushW, + input logic clk, reset, + input logic StallF, StallD, StallE, StallM, StallW, + input logic FlushF, FlushD, FlushE, FlushM, FlushW, // Fetch - input logic [`XLEN-1:0] InstrInF, + input logic [`XLEN-1:0] InstrInF, output logic [`XLEN-1:0] PCF, output logic [`XLEN-1:0] InstrPAdrF, - output logic InstrReadF, + output logic InstrReadF, // Decode // Execute output logic [`XLEN-1:0] PCLinkE, @@ -47,23 +47,26 @@ module ifu ( input logic [`XLEN-1:0] PrivilegedNextPCM, output logic [31:0] InstrD, InstrM, output logic [`XLEN-1:0] PCM, - output logic [3:0] InstrClassM, - output logic BPPredWrongM, + output logic [4:0] InstrClassM, + output logic BPPredDirWrongM, + output logic BTBPredPCWrongM, + output logic RASPredPCWrongM, + output logic BPPredClassNonCFIWrongM, // Writeback // output logic [`XLEN-1:0] PCLinkW, // Faults - input logic IllegalBaseInstrFaultD, - output logic IllegalIEUInstrFaultD, - output logic InstrMisalignedFaultM, + input logic IllegalBaseInstrFaultD, + output logic IllegalIEUInstrFaultD, + output logic InstrMisalignedFaultM, output logic [`XLEN-1:0] InstrMisalignedAdrM, // TLB management - input logic [1:0] PrivilegeModeW, - input logic [`XLEN-1:0] PageTableEntryF, - input logic [`XLEN-1:0] SATP_REGW, - input logic ITLBWriteF, // ITLBFlushF, - output logic ITLBMissF, ITLBHitF, + input logic [1:0] PrivilegeModeW, + input logic [`XLEN-1:0] PageTableEntryF, + input logic [`XLEN-1:0] SATP_REGW, + input logic ITLBWriteF, // ITLBFlushF, + output logic ITLBMissF, ITLBHitF, // bogus - input logic [15:0] rd2 + input logic [15:0] rd2 ); @@ -135,7 +138,11 @@ module ifu ( .PCD(PCD), .PCLinkE(PCLinkE), .InstrClassE(InstrClassE), - .BPPredWrongE(BPPredWrongE)); + .BPPredWrongE(BPPredWrongE), + .BPPredDirWrongE(BPPredDirWrongE), + .BTBPredPCWrongE(BTBPredPCWrongE), + .RASPredPCWrongE(RASPredPCWrongE), + .BPPredClassNonCFIWrongE(BPPredClassNonCFIWrongE)); // The true correct target is PCTargetE if PCSrcE is 1 else it is the fall through PCLinkE. assign PCCorrectE = PCSrcE ? PCTargetE : PCLinkE; @@ -216,12 +223,12 @@ module ifu ( .d(InstrClassE), .q(InstrClassM)); - flopenrc #(1) BPPredWrongRegM(.clk(clk), + flopenrc #(4) BPPredWrongRegM(.clk(clk), .reset(reset), .en(~StallM), .clear(FlushM), - .d(BPPredWrongE), - .q(BPPredWrongM)); + .d({BPPredDirWrongE, BTBPredPCWrongE, RASPredPCWrongE, BPPredClassNonCFIWrongE}), + .q({BPPredDirWrongM, BTBPredPCWrongM, RASPredPCWrongM, BPPredClassNonCFIWrongM})); // seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL. // either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index 79e81303..2148d885 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -33,8 +33,12 @@ module csr ( input logic [`XLEN-1:0] PCM, SrcAM, input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM, input logic TimerIntM, ExtIntM, SwIntM, - input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM, - input logic [3:0] InstrClassM, + input logic InstrValidW, FloatRegWriteW, LoadStallD, + input logic BPPredDirWrongM, + input logic BTBPredPCWrongM, + input logic RASPredPCWrongM, + input logic BPPredClassNonCFIWrongM, + input logic [4:0] InstrClassM, input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, input logic [`XLEN-1:0] CauseM, NextFaultMtvalM, output logic [1:0] STATUS_MPP, diff --git a/wally-pipelined/src/privileged/csrc.sv b/wally-pipelined/src/privileged/csrc.sv index ba90a48a..01e3a168 100644 --- a/wally-pipelined/src/privileged/csrc.sv +++ b/wally-pipelined/src/privileged/csrc.sv @@ -28,16 +28,20 @@ `include "wally-config.vh" module csrc ( - input logic clk, reset, - input logic StallD, StallE, StallM, StallW, - input logic InstrValidW, LoadStallD, CSRMWriteM, BPPredWrongM, - input logic [3:0] InstrClassM, - input logic [11:0] CSRAdrM, - input logic [1:0] PrivilegeModeW, - input logic [`XLEN-1:0] CSRWriteValM, - input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, + input logic clk, reset, + input logic StallD, StallE, StallM, StallW, + input logic InstrValidW, LoadStallD, CSRMWriteM, + input logic BPPredDirWrongM, + input logic BTBPredPCWrongM, + input logic RASPredPCWrongM, + input logic BPPredClassNonCFIWrongM, + input logic [4:0] InstrClassM, + input logic [11:0] CSRAdrM, + input logic [1:0] PrivilegeModeW, + input logic [`XLEN-1:0] CSRWriteValM, + input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, output logic [`XLEN-1:0] CSRCReadValM, - output logic IllegalCSRCAccessM); + output logic IllegalCSRCAccessM); // create Counter arrays to store address of each counter integer MHPMCOUNTER [`COUNTERS:0]; @@ -64,9 +68,14 @@ module csrc ( assign MCOUNTEN[1] = 1'b0; assign MCOUNTEN[2] = InstrValidW & ~StallW; assign MCOUNTEN[3] = LoadStallD & ~StallD; - assign MCOUNTEN[4] = BPPredWrongM & ~StallM; + assign MCOUNTEN[4] = BPPredDirWrongM & ~StallM; assign MCOUNTEN[5] = InstrClassM[0] & ~StallM; - assign MCOUNTEN[`COUNTERS:6] = 0; + assign MCOUNTEN[6] = BTBPredPCWrongM & ~StallM; + assign MCOUNTEN[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & ~StallM; + assign MCOUNTEN[8] = RASPredPCWrongM & ~StallM; + assign MCOUNTEN[9] = InstrClassM[3] & ~StallM; + assign MCOUNTEN[10] = BPPredClassNonCFIWrongM & ~StallM; + assign MCOUNTEN[`COUNTERS:11] = 0; genvar j; generate diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index f863b7fa..bb8e7e5e 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -36,8 +36,12 @@ module privileged ( output logic [`XLEN-1:0] CSRReadValW, output logic [`XLEN-1:0] PrivilegedNextPCM, output logic RetM, TrapM, - input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM, - input logic [3:0] InstrClassM, + input logic InstrValidW, FloatRegWriteW, LoadStallD, + input logic BPPredDirWrongM, + input logic BTBPredPCWrongM, + input logic RASPredPCWrongM, + input logic BPPredClassNonCFIWrongM, + input logic [4:0] InstrClassM, input logic PrivilegedM, input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD, input logic LoadMisalignedFaultM, LoadAccessFaultM, diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 5975015f..1559c906 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -111,8 +111,13 @@ module wallypipelinedhart ( logic DataStall, InstrStall; logic InstrAckD, MemAckW; - logic BPPredWrongE, BPPredWrongM; - logic [3:0] InstrClassM; + logic BPPredWrongE; + logic BPPredDirWrongM; + logic BTBPredPCWrongM; + logic RASPredPCWrongM; + logic BPPredClassNonCFIWrongM; + + logic [4:0] InstrClassM; ifu ifu(.InstrInF(InstrRData), .*); // instruction fetch unit: PC, branch prediction, instruction cache From b5445267669da0707898a8bc710cee943dd8d8db Mon Sep 17 00:00:00 2001 From: Shreya Sanghai Date: Wed, 31 Mar 2021 21:56:14 -0400 Subject: [PATCH 30/55] fixed bugs in global history to read latest GHRE --- wally-pipelined/config/rv64BP/wally-config.vh | 2 +- wally-pipelined/src/ifu/globalHistoryPredictor.sv | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh index bd053750..f39c6cee 100644 --- a/wally-pipelined/config/rv64BP/wally-config.vh +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -97,5 +97,5 @@ `define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" -`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define BPTYPE "BPGLOBAL" // BPGLOBAL or BPTWOBIT or BPGSHARE `define TESTSBP 1 diff --git a/wally-pipelined/src/ifu/globalHistoryPredictor.sv b/wally-pipelined/src/ifu/globalHistoryPredictor.sv index b9addb38..babafb52 100644 --- a/wally-pipelined/src/ifu/globalHistoryPredictor.sv +++ b/wally-pipelined/src/ifu/globalHistoryPredictor.sv @@ -41,12 +41,13 @@ module globalHistoryPredictor input logic [1:0] UpdatePrediction ); - logic [k-1:0] GHRF, GHRD, GHRE; + logic [k-1:0] GHRF, GHRD, GHRE, GHRENext; + assign GHRENext = {PCSrcE, GHRE[k-1:1]}; flopenr #(k) GlobalHistoryRegister(.clk(clk), .reset(reset), .en(UpdateEN), - .d({PCSrcE, GHRF[k-1:1] }), + .d(GHRENext), .q(GHRF)); @@ -66,8 +67,8 @@ module globalHistoryPredictor .reset(reset), .RA1(GHRF), .RD1(PredictionMemory), - .REN1(1'b1), - .WA1(GHRE), + .REN1(~StallF), + .WA1(GHRENext), .WD1(UpdatePrediction), .WEN1(UpdateEN), .BitWEN1(2'b11)); From 28a9c6ba56973b212c6c040d24de97d3823c5f3d Mon Sep 17 00:00:00 2001 From: ShreyaSanghai Date: Thu, 1 Apr 2021 22:22:40 +0530 Subject: [PATCH 31/55] added localHistoryPredictor --- .../src/ifu/globalHistoryPredictor.sv | 9 +- .../src/ifu/localHistoryPredictor.sv | 138 ++++++++++++++++++ 2 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 wally-pipelined/src/ifu/localHistoryPredictor.sv diff --git a/wally-pipelined/src/ifu/globalHistoryPredictor.sv b/wally-pipelined/src/ifu/globalHistoryPredictor.sv index babafb52..1fd0720f 100644 --- a/wally-pipelined/src/ifu/globalHistoryPredictor.sv +++ b/wally-pipelined/src/ifu/globalHistoryPredictor.sv @@ -37,7 +37,7 @@ module globalHistoryPredictor output logic [1:0] Prediction, // update input logic [`XLEN-1:0] UpdatePC, - input logic UpdateEN, PCSrcE, /// *** need to add as input from bpred.sv + input logic UpdateEN, PCSrcE, input logic [1:0] UpdatePrediction ); @@ -55,11 +55,8 @@ module globalHistoryPredictor logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF; logic [1:0] UpdatePredictionF; - - // for gshare xor the PC with the GHR - // TODO: change in sram memory2 module - // assign UpdatePCIndex = GHRE ^ UpdatePC; - // assign LookUpPCIndex = LookUpPC ^ GHR; + + // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT // GHR referes to the address that the past k branches points to in the prediction stage // GHRE refers to the address that the past k branches points to in the exectution stage diff --git a/wally-pipelined/src/ifu/localHistoryPredictor.sv b/wally-pipelined/src/ifu/localHistoryPredictor.sv new file mode 100644 index 00000000..85f41357 --- /dev/null +++ b/wally-pipelined/src/ifu/localHistoryPredictor.sv @@ -0,0 +1,138 @@ +/////////////////////////////////////////// +// locallHistoryPredictor.sv +// +// Written: Shreya Sanghai +// Email: ssanghai@hmc.edu +// Created: March 16, 2021 +// Modified: +// +// Purpose: Global History Branch predictor with parameterized global history register +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +`include "wally-config.vh" + +module localHistoryPredictor + #( parameter int m = 6, // 2^m = number of local history branches + parameter int k = 10 // number of past branches stored + ) + (input logic clk, + input logic reset, + input logic StallF, StallD, StallE, FlushF, FlushD, FlushE, + input logic [`XLEN-1:0] LookUpPC, + output logic [1:0] Prediction, + // update + input logic [`XLEN-1:0] UpdatePC, + input logic UpdateEN, PCSrcE, + input logic [1:0] UpdatePrediction + + ); + + logic [2**m-1:0][k-1:0] LHRNextF; + logic [k-1:0] LHRD, LHRE, LHRENext, ForwardLHRNext; + logic [m-1:0] LookUpPCIndex, UpdatePCIndex; + logic [1:0] PredictionMemory; + logic DoForwarding, DoForwardingF, DoForwardingPHT, DoForwardingPHTF; + logic [1:0] UpdatePredictionF; + + assign LHRENext = {PCSrcE, LHRE[k-1:1]}; + assign UpdatePCIndex = {UpdatePC[m+1] ^ UpdatePC[1], UpdatePC[m:2]}; + assign LookUpPCIndex = {LookUpPC[m+1] ^ LookUpPC[1], LookUpPC[m:2]}; + +// INCASE we do ahead pipelining +// SRAM2P1R1W #(m,k) LHR(.clk(clk)), +// .reset(reset), +// .RA1(LookUpPCIndex), // need hashing function to get correct PC address +// .RD1(LHRF), +// .REN1(~StallF), +// .WA1(UpdatePCIndex), +// .WD1(LHRENExt), +// .WEN1(UpdateEN), +// .BitWEN1(2'b11)); + +genvar index; +generate + for (index = 0; index < 2**m; index = index +1) begin:index + + flopenr #(k) LocalHistoryRegister(.clk(clk), + .reset(reset), + .en(UpdateEN && (index == UpdatePCIndex)), + .d(LHRENext), + .q(LHRNextF[index])); + end +endgenerate + +// need to forward when updating to the same address as reading. +// first we compare to see if the update and lookup addreses are the same +assign DoForwarding = LookUpPCIndex == UpdatePCIndex; +assign ForwardLHRNext = DoForwarding ? LHRENext :LHRNextF[LookUpPCIndex]; + + // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT + // LHR referes to the address that the past k branches points to in the prediction stage + // LHRE refers to the address that the past k branches points to in the exectution stage + SRAM2P1R1W #(k, 2) PHT(.clk(clk), + .reset(reset), + .RA1(ForwardLHRNext), + .RD1(PredictionMemory), + .REN1(~StallF), + .WA1(LHRENext), + .WD1(UpdatePrediction), + .WEN1(UpdateEN), + .BitWEN1(2'b11)); + + + +assign DoForwardingPHT = LHRENext == ForwardLHRNext; + + // register the update value and the forwarding signal into the Fetch stage + // TODO: add stall logic *** + flopr #(1) DoForwardingReg(.clk(clk), + .reset(reset), + .d(DoForwardingPHT), + .q(DoForwardingPHTF)); + + flopr #(2) UpdatePredictionReg(.clk(clk), + .reset(reset), + .d(UpdatePrediction), + .q(UpdatePredictionF)); + + assign Prediction = DoForwardingPHTF ? UpdatePredictionF : PredictionMemory; + + //pipeline for LHR + flopenrc #(k) LHRFReg(.clk(clk), + .reset(reset), + .en(~StallF), + .clear(FlushF), + .d(ForwardLHRNext), + .q(LHRF)); + + flopenrc #(k) LHRDReg(.clk(clk), + .reset(reset), + .en(~StallD), + .clear(FlushD), + .d(LHRF), + .q(LHRD)); + + flopenrc #(k) LHREReg(.clk(clk), + .reset(reset), + .en(~StallE), + .clear(FlushE), + .d(LHRD), + .q(LHRE)); + +endmodule From df149d1be7445442e326975a269ffec523416a18 Mon Sep 17 00:00:00 2001 From: Shreya Sanghai Date: Thu, 1 Apr 2021 13:40:08 -0400 Subject: [PATCH 32/55] fixed minor bugs in localHistory --- wally-pipelined/config/rv32ic/wally-config.vh | 2 +- wally-pipelined/config/rv64ic/wally-config.vh | 2 +- wally-pipelined/config/rv64icfd/wally-config.vh | 2 +- wally-pipelined/src/ifu/bpred.sv | 13 +++++++++++++ wally-pipelined/src/ifu/localHistoryPredictor.sv | 4 ++-- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index fadbe36c..f369c19b 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -94,5 +94,5 @@ `define TWO_BIT_PRELOAD "../config/rv32ic/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv32ic/BTBPredictor.txt" -`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define BPTYPE "BPLOCALPAg" // BPGLOBAL or BPTWOBIT or BPGSHARE `define TESTSBP 0 diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index b27a5e1c..9cfb5a8e 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -97,5 +97,5 @@ `define TWO_BIT_PRELOAD "../config/rv64ic/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64ic/BTBPredictor.txt" -`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define BPTYPE "BPLOCALPAg" // BPGLOBAL or BPTWOBIT or BPGSHARE `define TESTSBP 0 diff --git a/wally-pipelined/config/rv64icfd/wally-config.vh b/wally-pipelined/config/rv64icfd/wally-config.vh index 853b8685..6ea013d9 100644 --- a/wally-pipelined/config/rv64icfd/wally-config.vh +++ b/wally-pipelined/config/rv64icfd/wally-config.vh @@ -97,5 +97,5 @@ `define TWO_BIT_PRELOAD "../config/rv64icfd/twoBitPredictor.txt" `define BTB_PRELOAD "../config/rv64icfd/BTBPredictor.txt" -`define BPTYPE "BPGSHARE" // BPGLOBAL or BPTWOBIT or BPGSHARE +`define BPTYPE "BPGLOBAL" // BPGLOBAL or BPTWOBIT or BPGSHARE `define TESTSBP 0 diff --git a/wally-pipelined/src/ifu/bpred.sv b/wally-pipelined/src/ifu/bpred.sv index a96d4353..56ee1624 100644 --- a/wally-pipelined/src/ifu/bpred.sv +++ b/wally-pipelined/src/ifu/bpred.sv @@ -104,6 +104,19 @@ module bpred .PCSrcE(PCSrcE), .UpdatePrediction(UpdateBPPredE)); end + else if (`BPTYPE == "BPLOCALPAg") begin:Predictor + + localHistoryPredictor DirPredictor(.clk(clk), + .reset(reset), + .*, // Stalls and flushes + .LookUpPC(PCNextF), + .Prediction(BPPredF), + // update + .UpdatePC(PCE), + .UpdateEN(InstrClassE[0] & ~StallE), + .PCSrcE(PCSrcE), + .UpdatePrediction(UpdateBPPredE)); + end endgenerate diff --git a/wally-pipelined/src/ifu/localHistoryPredictor.sv b/wally-pipelined/src/ifu/localHistoryPredictor.sv index 85f41357..ef33bbc8 100644 --- a/wally-pipelined/src/ifu/localHistoryPredictor.sv +++ b/wally-pipelined/src/ifu/localHistoryPredictor.sv @@ -44,7 +44,7 @@ module localHistoryPredictor ); logic [2**m-1:0][k-1:0] LHRNextF; - logic [k-1:0] LHRD, LHRE, LHRENext, ForwardLHRNext; + logic [k-1:0] LHRF, LHRD, LHRE, LHRENext, ForwardLHRNext; logic [m-1:0] LookUpPCIndex, UpdatePCIndex; logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF, DoForwardingPHT, DoForwardingPHTF; @@ -67,7 +67,7 @@ module localHistoryPredictor genvar index; generate - for (index = 0; index < 2**m; index = index +1) begin:index + for (index = 0; index < 2**m; index = index +1) begin flopenr #(k) LocalHistoryRegister(.clk(clk), .reset(reset), From 5afb2552519af4b74954d7941796352cf2515ba1 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 1 Apr 2021 13:55:21 -0400 Subject: [PATCH 33/55] Begin changes to direct-mapped cache --- wally-pipelined/src/cache/dmapped.sv | 100 +++++++++++++++++---------- 1 file changed, 63 insertions(+), 37 deletions(-) diff --git a/wally-pipelined/src/cache/dmapped.sv b/wally-pipelined/src/cache/dmapped.sv index 9a51737a..9138089e 100644 --- a/wally-pipelined/src/cache/dmapped.sv +++ b/wally-pipelined/src/cache/dmapped.sv @@ -26,7 +26,7 @@ `include "wally-config.vh" -module rodirectmappedmem #(parameter LINESIZE = 256, parameter NUMLINES = 512, parameter WORDSIZE = `XLEN) ( +module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) ( // Pipeline stuff input logic clk, input logic reset, @@ -44,50 +44,76 @@ module rodirectmappedmem #(parameter LINESIZE = 256, parameter NUMLINES = 512, p output logic DataValid ); - localparam integer SETWIDTH = $clog2(NUMLINES); - localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); - localparam integer TAGWIDTH = `XLEN-SETWIDTH-OFFSETWIDTH; + // Various compile-time constants + localparam integer WORDWIDTH = $clog2(WORDSIZE); + localparam integer LINEWIDTH = $clog2(LINESIZE/8); + localparam integer OFFSETWIDTH = $clog2(LINESIZE) - WORDWIDTH; + localparam integer SETWIDTH = $clog2(NUMLINES); + localparam integer TAGWIDTH = $clog2(`XLEN) - $clog2(LINESIZE) - SETWIDTH; - logic [NUMLINES-1:0][WORDSIZE-1:0] LineOutputs; - logic [NUMLINES-1:0] ValidOutputs; - logic [NUMLINES-1:0][TAGWIDTH-1:0] TagOutputs; - logic [OFFSETWIDTH-1:0] WordSelect; - logic [`XLEN-1:0] ReadPAdr; - logic [SETWIDTH-1:0] ReadSet, WriteSet; - logic [TAGWIDTH-1:0] ReadTag, WriteTag; + // Machinery to read from and write to the correct addresses in memory + logic [`XLEN-1:0] ReadPAdr; + logic [OFFSETWIDTH-1:0] ReadOffset, WriteOffset; + logic [SETWIDTH-1:0] ReadSet, WriteSet; + logic [TAGWIDTH-1:0] ReadTag, WriteTag; - // Swizzle bits to get the offset, set, and tag out of the read and write addresses + // Machinery to check if a given read is valid and is the desired value + logic [TAGWIDTH-1:0] DataTag; + logic [NUMLINES-1:0] ValidOut, NextValidOut; + + // Assign the read and write addresses in cache memory always_comb begin - // Read address - assign WordSelect = ReadLowerAdr[OFFSETWIDTH-1:0]; + assign ReadOffset = ReadLowerAdr[WORDWIDTH+OFFSETWIDTH-1:WORDWIDTH]; assign ReadPAdr = {ReadUpperPAdr, ReadLowerAdr}; - assign ReadSet = ReadPAdr[SETWIDTH+OFFSETWIDTH-1:OFFSETWIDTH]; - assign ReadTag = ReadPAdr[`XLEN-1:SETWIDTH+OFFSETWIDTH]; - // Write address - assign WriteSet = WritePAdr[SETWIDTH+OFFSETWIDTH-1:OFFSETWIDTH]; - assign WriteTag = WritePAdr[`XLEN-1:SETWIDTH+OFFSETWIDTH]; + assign ReadSet = ReadPAdr[LINEWIDTH+SETWIDTH-1:LINEWIDTH]; + assign ReadTag = ReadPAdr[`XLEN-1:LINEWIDTH+SETWIDTH]; + + assign WriteOffset = WritePAdr[WORDWIDTH+OFFSETWIDTH-1:WORDWIDTH]; + assign WriteSet = WritePAdr[LINEWIDTH+SETWIDTH-1:LINEWIDTH]; + assign WriteTag = WritePAdr[`XLEN-1:LINEWIDTH+SETWIDTH]; end - genvar i; - generate - for (i=0; i < NUMLINES; i++) begin - rocacheline #(LINESIZE, TAGWIDTH, WORDSIZE) lines ( - .*, - .WriteEnable(WriteEnable & (WriteSet == i)), - .WriteData(WriteLine), - .WriteTag(WriteTag), - .DataWord(LineOutputs[i]), - .DataTag(TagOutputs[i]), - .DataValid(ValidOutputs[i]) - ); - end - endgenerate + SRAM2P1R1W #(.Depth(OFFSETWIDTH), .Width(WORDSIZE)) cachemem ( + .*, + .RA1(ReadOffset), + .RD1(DataWord), + .REN1(1'b1), + .WA1(WriteOffset), + .WD1(WriteSet), + .WEN1(WriteEnable), + .BitWEN1(0) + ); - // Get the data and valid out of the lines + SRAM2P1R1W #(.Depth(OFFSETWIDTH), .Width(TAGWIDTH)) cachetags ( + .*, + .RA1(ReadOffset), + .RD1(DataTag), + .REN1(1'b1), + .WA1(WriteOffset), + .WD1(WriteTag), + .WEN1(WriteEnable), + .BitWEN1(0) + ); + + // Correctly handle the valid bits always_comb begin - assign DataWord = LineOutputs[ReadSet]; - assign DataValid = ValidOutputs[ReadSet] & (TagOutputs[ReadSet] == ReadTag); + if (WriteEnable) begin + assign NextValidOut = {NextValidOut[NUMLINES-1:WriteSet+1], 1'b1, NextValidOut[WriteSet-1:0]}; + end else begin + assign NextValidOut = ValidOut; + end + end + always_ff @(posedge clk, reset, flush) begin + if (reset || flush) begin + ValidOut <= {NUMLINES{1'b0}}; + end else begin + ValidOut <= NextValidOut; + end + end + + // Determine if the line coming out is valid and matches the desired data + always_comb begin + assign DataValid = ValidOut[ReadSet] && (DataTag == ReadTag); end endmodule - From c95da7d11e39cdff1dc14c2c281f807af325a025 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Sat, 3 Apr 2021 18:04:59 -0400 Subject: [PATCH 34/55] Fix bug in icache --- wally-pipelined/src/ifu/icache.sv | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 4208c355..d0308a4e 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -55,6 +55,7 @@ module icache( // Buffer the last read, for ease of accessing it again logic LastReadDataValidF; logic [`XLEN-1:0] LastReadDataF, LastReadAdrF, InDataF; + logic [`XLEN-1:0] LastCyclePCPF; // instruction for NOP logic [31:0] nop = 32'h00000013; @@ -80,15 +81,17 @@ module icache( flopenr #(1) lastReadDataVFlop(clk, reset, InstrReadF & ~StallF, 1'b1, LastReadDataValidF); flopenr #(`XLEN) lastReadAdrFlop(clk, reset, InstrReadF & ~StallF, InstrPAdrF, LastReadAdrF); + flopenr #(`XLEN) rememberPCPFFlop(clk, reset, ~StallF, PCPF, LastCyclePCPF); + // Decide which address needs to be fetched and sent out over InstrPAdrF // If the requested address fits inside one read from memory, we fetch that // address, adjusted to the bit width. Otherwise, we request the lower word // and then the upper word, in that order. generate if (`XLEN == 32) begin - assign InstrPAdrF = PCPF[1] ? ((DelaySideF & ~CompressedF) ? {PCPF[31:2], 2'b00} : {PCPF[31:2], 2'b00}) : PCPF; + assign InstrPAdrF = PCPF[1] ? ((DelaySideF & ~CompressedF) ? {LastCyclePCPF[31:2]+1, 2'b00} : {PCPF[31:2], 2'b00}) : PCPF; end else begin - assign InstrPAdrF = PCPF[2] ? (PCPF[1] ? ((DelaySideF & ~CompressedF) ? {PCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}) : {PCPF[63:3], 3'b000}) : {PCPF[63:3], 3'b000}; + assign InstrPAdrF = (PCPF[2] && PCPF[1] && (DelaySideF & ~CompressedF)) ? {PCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}; end endgenerate From 3afc3589744f0f97920815556bf0d3c164cdab6f Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Tue, 6 Apr 2021 12:48:42 -0400 Subject: [PATCH 35/55] Fix another bug in icache --- wally-pipelined/src/ifu/icache.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index d0308a4e..8743e108 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -69,7 +69,7 @@ module icache( flopr #(1) flushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCyclen | ~StallF), FlushDLastCyclen); flopenr #(1) delayDFlop(clk, reset, ~StallF, DelayF & ~CompressedF, DelayD); - flopenrc#(1) delayStateFlop(clk, reset, FlushD, ~StallF, DelayF & ~DelaySideF, DelaySideF); + flopenrc#(1) delayStateFlop(clk, reset, FlushD, ~StallF, DelayF & ~DelaySideF & ~CompressedF, DelaySideF); // This flop stores the first half of a misaligned instruction while waiting for the other half flopenr #(16) halfInstrFlop(clk, reset, DelayF & ~StallF, MisalignedHalfInstrF, MisalignedHalfInstrD); @@ -91,7 +91,7 @@ module icache( if (`XLEN == 32) begin assign InstrPAdrF = PCPF[1] ? ((DelaySideF & ~CompressedF) ? {LastCyclePCPF[31:2]+1, 2'b00} : {PCPF[31:2], 2'b00}) : PCPF; end else begin - assign InstrPAdrF = (PCPF[2] && PCPF[1] && (DelaySideF & ~CompressedF)) ? {PCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}; + assign InstrPAdrF = (PCPF[2] && PCPF[1] && DelaySideF & ~CompressedF) ? {LastCyclePCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}; end endgenerate From bd8f1eea3cdc6b913ed6e18ae2035fcad7d43ca3 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Tue, 6 Apr 2021 17:47:00 -0400 Subject: [PATCH 36/55] Fix another bug in icache --- wally-pipelined/src/ifu/icache.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 8743e108..5bb4efe8 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -89,9 +89,9 @@ module icache( // and then the upper word, in that order. generate if (`XLEN == 32) begin - assign InstrPAdrF = PCPF[1] ? ((DelaySideF & ~CompressedF) ? {LastCyclePCPF[31:2]+1, 2'b00} : {PCPF[31:2], 2'b00}) : PCPF; + assign InstrPAdrF = DelaySideF ? {LastCyclePCPF[31:2]+1, 2'b00} : {PCPF[31:2], 2'b00}; end else begin - assign InstrPAdrF = (PCPF[2] && PCPF[1] && DelaySideF & ~CompressedF) ? {LastCyclePCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}; + assign InstrPAdrF = DelaySideF ? {LastCyclePCPF[63:3]+1, 3'b000} : {PCPF[63:3], 3'b000}; end endgenerate From bff2d61a1f34c3f27e1d0120b6c215de9f55fb4c Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 6 Apr 2021 21:20:51 -0500 Subject: [PATCH 37/55] Steps to getting branch predictor benchmarks running. --- testsBP/crt0/start.s | 2 +- testsBP/makefile.inc | 1 + testsBP/simple/header.h | 1 + testsBP/simple/main.c | 1 + wally-pipelined/bin/exe2memfile0.pl | 120 +++++++++++----- wally-pipelined/config/rv64BP/wally-config.vh | 20 +-- wally-pipelined/regression/wave.do | 130 +++++++++++------- .../testbench/testbench-imperas.sv | 1 + 8 files changed, 183 insertions(+), 93 deletions(-) diff --git a/testsBP/crt0/start.s b/testsBP/crt0/start.s index 17543581..19a240d8 100644 --- a/testsBP/crt0/start.s +++ b/testsBP/crt0/start.s @@ -45,7 +45,7 @@ _start: # set the stack pointer to the top of memory # 0x8000_0000 + 64K - 8 bytes - li sp, 0x0000FFF8 + li sp, 0x007FFFF8 jal ra, main jal ra, _halt diff --git a/testsBP/makefile.inc b/testsBP/makefile.inc index af0b03bc..141b5d91 100644 --- a/testsBP/makefile.inc +++ b/testsBP/makefile.inc @@ -90,3 +90,4 @@ $(TARGET).memfile: $(TARGET) @echo 'Making memory file' exe2memfile0.pl $< extractFunctionRadix.sh $<.objdump + cp $(TARGETDIR)/* ../../imperas-riscv-tests/work/rv64BP/ diff --git a/testsBP/simple/header.h b/testsBP/simple/header.h index b5268fbf..a52bf804 100644 --- a/testsBP/simple/header.h +++ b/testsBP/simple/header.h @@ -3,4 +3,5 @@ int fail(); int simple_csrbr_test(); +int lbu_test(); #endif diff --git a/testsBP/simple/main.c b/testsBP/simple/main.c index 047a52f8..97adcb7c 100644 --- a/testsBP/simple/main.c +++ b/testsBP/simple/main.c @@ -6,5 +6,6 @@ int main(){ fail(); return 0; }else + res = lbu_test(); return 0; } diff --git a/wally-pipelined/bin/exe2memfile0.pl b/wally-pipelined/bin/exe2memfile0.pl index 8fbea6f8..1b0dad53 100755 --- a/wally-pipelined/bin/exe2memfile0.pl +++ b/wally-pipelined/bin/exe2memfile0.pl @@ -18,7 +18,7 @@ my $maxaddress = 0; STDOUT->autoflush(1); # *** Ross Thompson I think there is a bug here needs to be +1 -print ("Processing $#ARGV memfiles: "); +print ("Processing $#ARGV memfiles: \n"); my $frac = $#ARGV/10; for(my $i=0; $i<=$#ARGV; $i++) { if ($i < 10 || $i % $frac == 0) { print ("$i ") }; @@ -40,7 +40,11 @@ for(my $i=0; $i<=$#ARGV; $i++) { if ($needsprocessing == 1) { open(FILE, $ofile) || die("Can't read $ofile"); my $mode = 0; # parse for code + my $section = ""; + my $data = ""; my $address; + my $first = 0; + my $firstAddress; # initialize to all zeros; # *** need to fix the zeroing range. Not always 64K @@ -49,57 +53,100 @@ for(my $i=0; $i<=$#ARGV; $i++) { } while() { - # *** this mode stuff does not work if a section is missing or reordered. - if ($mode == 0) { # Parse code -# print("Examining $_\n"); - if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { - $address = &fixadr($1); - my $instr = $2; - my $len = length($instr); - for (my $i=0; $i<$len/2; $i++) { - $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); - } -# print ("address $address $instr\n"); + # objdump fill is divided into several .sections of which only some we want to actually process. + # In general we want everything except the .comment and .*attributes + if (/Disassembly of section (.*):/) { + $section = $1; + print ("setting section to $section\n"); + } else { + # now check if the section is one we are interested in processing. + #if ($section ne ".comment" && $section ne ".riscv.attributes" && $section =~ /\.debug.*/) { + if ($section =~ "\.init|\.text|\..*data|\..*bss") { + # the structure is: possible space(s) hex number: possible space(s) hex number space(s) junk + # there are also lines we need to skip: possible space(s) hex number : + if (/^\s*([0-9A-Fa-f]{1,16}):\s+([0-9A-Fa-f]+).*$/) { + $address = &fixadr($1); + if ($first == 0) { + $first = 1; + $firstAddress = $address; + } + $data = $2; + &emitData($address, $data); + # my $len = length($data); + # for (my $i=0; $i<$len/2; $i++) { + # $memfilebytes[$address+$i] = substr($data, $len-2-2*$i, 2); + # } +# print ("Addr $address $data\n"); +# } elsif (/^\s*\.\.\./) { +# print ("Got ...\n"); +# } else { +# print ("No match\n"); + } } - if (/Disassembly of section .data:/) { $mode = 1;} - } elsif ($mode == 1) { # Parse data segment - if (/^\s*(\S{1,16}):\s+(.*)/) { - $address = &fixadr($1); -# print "addresss $address maxaddress $maxaddress\n"; - if ($address > $maxaddress) { $maxaddress = $address; } - my $line = $2; - # merge chunks with spaces - # *** might need to change - $line =~ s/(\S)\s(\S)/$1$2/g; - # strip off comments - $line =~ /^(\S*)/; - $payload = $1; - &emitData($address, $payload); - } - if (/Disassembly of section .comment:/) { $mode = 2; } - } elsif ($mode == 2) { # parse the comment section - if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } - } + } +# # *** this mode stuff does not work if a section is missing or reordered. +# if ($mode == 0) { # Parse code +# # print("Examining $_\n"); +# if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { +# $address = &fixadr($1); +# my $instr = $2; +# my $len = length($instr); +# for (my $i=0; $i<$len/2; $i++) { +# $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); +# } +# print ("address $address $instr\n"); +# } +# if (/Disassembly of section .data:/) { $mode = 1;} +# } elsif ($mode == 1) { # Parse data segment +# if (/^\s*(\S{1,16}):\s+(.*)/) { +# $address = &fixadr($1); +# # print "addresss $address maxaddress $maxaddress\n"; +# if ($address > $maxaddress) { $maxaddress = $address; } +# my $line = $2; +# # merge chunks with spaces +# # *** might need to change +# $line =~ s/(\S)\s(\S)/$1$2/g; +# # strip off comments +# $line =~ /^(\S*)/; +# $payload = $1; +# &emitData($address, $payload); +# } +# if (/Disassembly of section .comment:/) { $mode = 2; } +# } elsif ($mode == 2) { # parse the comment section +# if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } +# } } close(FILE); - $maxaddress += 32; # pad some zeros at the end + $maxaddress = $address + 32; # pad some zeros at the end # print to memory file # *** this is a problem if ($fname =~ /rv32/) { open(MEMFILE, ">$memfile") || die("Can't write $memfile"); - for (my $i=0; $i<= $maxaddress; $i = $i + 4) { + for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 4) { for ($j=3; $j>=0; $j--) { - print MEMFILE "$memfilebytes[$i+$j]"; + no warnings 'uninitialized'; + my $value = $memfilebytes[$i+$j]; + if ($value eq ""){ + print MEMFILE "00"; + } else { + print MEMFILE "$memfilebytes[$i+$j]"; + } } print MEMFILE "\n"; } close(MEMFILE); } else { open(MEMFILE, ">$memfile") || die("Can't write $memfile"); - for (my $i=0; $i<= $maxaddress; $i = $i + 8) { + for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 8) { for ($j=7; $j>=0; $j--) { - print MEMFILE "$memfilebytes[$i+$j]"; + no warnings 'uninitialized'; + my $value = $memfilebytes[$i+$j]; + if ($value eq ""){ + print MEMFILE "00"; + } else { + print MEMFILE "$memfilebytes[$i+$j]"; + } } print MEMFILE "\n"; } @@ -141,5 +188,6 @@ sub fixadr { # strip off leading 8 from address and convert to decimal # if the leading 8 is not present don't remove. my $adr = shift; + #print "addr $adr\n"; return hex($adr); } diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh index bd053750..030c4381 100644 --- a/wally-pipelined/config/rv64BP/wally-config.vh +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -66,18 +66,18 @@ // Peripheral memory space extends from BASE to BASE+RANGE // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits -`define BOOTTIMBASE 32'h00080000 +`define BOOTTIMBASE 32'h00800000 `define BOOTTIMRANGE 32'h00003FFF `define TIMBASE 32'h00000000 -`define TIMRANGE 32'h0007FFFF -`define CLINTBASE 32'h02000000 -`define CLINTRANGE 32'h0000FFFF -`define GPIOBASE 32'h10012000 -`define GPIORANGE 32'h000000FF -`define UARTBASE 32'h10000000 -`define UARTRANGE 32'h00000007 -`define PLICBASE 32'h0C000000 -`define PLICRANGE 32'h03FFFFFF +`define TIMRANGE 32'h007FFFFF +`define CLINTBASE 32'h02000000 +`define CLINTRANGE 32'h0000FFFF +`define GPIOBASE 32'h10012000 +`define GPIORANGE 32'h000000FF +`define UARTBASE 32'h10000000 +`define UARTRANGE 32'h00000007 +`define PLICBASE 32'h0C000000 +`define PLICRANGE 32'h03FFFFFF // Test modes diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index ede2da62..88e22891 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -56,15 +56,14 @@ add wave -noupdate -group Bpred -expand -group direction -group other /testbench add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionDirWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group Bpred -group {bp wrong} -divider pcs -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD -add wave -noupdate -group Bpred -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -group Bpred -expand -group {bp wrong} -divider pcs +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCTargetE add wave -noupdate -group Bpred -expand -group BTB -divider Update add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC @@ -96,25 +95,25 @@ add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM -add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -expand -group {Decode Stage} /testbench/InstrDName -add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD -add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD -add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D -add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -group {Decode Stage} /testbench/InstrDName +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D +add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D +add wave -noupdate -group RegFile -expand /testbench/dut/hart/ieu/dp/regf/rf +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol @@ -128,10 +127,11 @@ add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName -add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM -add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM -add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM -add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM +add wave -noupdate -expand -group dcache -radix hexadecimal /testbench/dut/hart/MemPAdrM +add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM +add wave -noupdate -expand -group dcache /testbench/dut/hart/ReadDataW +add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E @@ -150,15 +150,15 @@ add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALURe add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM -add wave -noupdate -group PCS /testbench/dut/hart/ifu/PCNextF -add wave -noupdate -group PCS /testbench/dut/hart/PCF -add wave -noupdate -group PCS /testbench/dut/hart/ifu/PCD -add wave -noupdate -group PCS /testbench/dut/hart/PCE -add wave -noupdate -group PCS /testbench/dut/hart/PCM -add wave -noupdate -group PCS /testbench/dut/hart/ifu/PCW -add wave -noupdate -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNextF -add wave -noupdate -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNext0F -add wave -noupdate -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNext1F +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCNextF +add wave -noupdate -expand -group PCS /testbench/dut/hart/PCF +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD +add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE +add wave -noupdate -expand -group PCS /testbench/dut/hart/PCM +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCW +add wave -noupdate -expand -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNextF +add wave -noupdate -expand -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNext0F +add wave -noupdate -expand -group PCS -group pcnextmux /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr add wave -noupdate -group {function radix debug} -radix unsigned /testbench/FunctionName/FunctionName/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/reset @@ -173,15 +173,53 @@ add wave -noupdate -group {function radix debug} /testbench/FunctionName/Functio add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionAddr add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/FunctionName/FunctionName/FunctionName -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW -add wave -noupdate -expand -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/genblk1/HPMCOUNTER_REGW +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTEN +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/MCOUNTINHIBIT_REGW +add wave -noupdate -group {performance counters} /testbench/dut/hart/priv/csr/genblk1/counters/genblk1/HPMCOUNTER_REGW add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultW add wave -noupdate /testbench/dut/hart/ieu/dp/ResultSrcW add wave -noupdate /testbench/dut/hart/ieu/dp/CSRReadValW add wave -noupdate /testbench/dut/hart/priv/csr/genblk1/counters/CSRCReadValM +add wave -noupdate -radix unsigned /testbench/dut/imem/adrbits +add wave -noupdate /testbench/dut/imem/rd +add wave -noupdate /testbench/dut/imem/AdrF +add wave -noupdate /testbench/dut/imem/InstrF +add wave -noupdate /testbench/dut/InstrF +add wave -noupdate /testbench/dut/InstrF +add wave -noupdate -divider {New Divider} +add wave -noupdate /testbench/dut/hart/ifu/InstrInF +add wave -noupdate /testbench/dut/hart/ifu/rd2 +add wave -noupdate /testbench/dut/hart/InstrRData +add wave -noupdate /testbench/dut/hart/rd2 +add wave -noupdate /testbench/dut/hart/ebu/InstrRData +add wave -noupdate /testbench/dut/hart/ebu/InstrPAdrF +add wave -noupdate /testbench/dut/hart/ebu/HRDATA +add wave -noupdate /testbench/dut/uncore/HSELUARTD +add wave -noupdate /testbench/dut/uncore/HSELUART +add wave -noupdate /testbench/dut/uncore/HSELTimD +add wave -noupdate /testbench/dut/uncore/HSELTim +add wave -noupdate /testbench/dut/uncore/HSELPLICD +add wave -noupdate /testbench/dut/uncore/HSELPLIC +add wave -noupdate /testbench/dut/uncore/HSELGPIOD +add wave -noupdate /testbench/dut/uncore/HSELGPIO +add wave -noupdate /testbench/dut/uncore/HSELCLINTD +add wave -noupdate /testbench/dut/uncore/HSELCLINT +add wave -noupdate /testbench/dut/uncore/HSELBootTimD +add wave -noupdate /testbench/dut/uncore/HSELBootTim +add wave -noupdate /testbench/dut/uncore/HREADTim +add wave -noupdate /testbench/dut/uncore/dtim/HREADTim +add wave -noupdate /testbench/dut/uncore/dtim/HREADTim0 +add wave -noupdate /testbench/dut/uncore/dtim/BASE +add wave -noupdate /testbench/dut/uncore/dtim/RANGE +add wave -noupdate /testbench/memfilename +add wave -noupdate {/testbench/dut/uncore/dtim/RAM[770056]} +add wave -noupdate {/testbench/dut/uncore/dtim/RAM[771306]} +add wave -noupdate -radix hexadecimal /testbench/dut/uncore/dtim/HADDR +add wave -noupdate /testbench/dut/uncore/dtim/RAM +add wave -noupdate /testbench/dut/uncore/dtim/HREADTim +add wave -noupdate /testbench/dut/uncore/dtim/HREADTim0 TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 7} {13518 ns} 0} +WaveRestoreCursors {{Cursor 7} {15047768 ns} 0} {{Cursor 2} {34763538 ns} 0} {{Cursor 3} {15046271 ns} 0} {{Cursor 4} {15047307 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -197,4 +235,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {13489 ns} {13607 ns} +WaveRestoreZoom {15047734 ns} {15047902 ns} diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index c9c5919a..c11b805a 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -317,6 +317,7 @@ string tests32i[] = { string testsBP64[] = '{ "rv64BP/simple", "10000", + "rv64BP/qsort", "1000000", "rv64BP/sieve", "1000000" }; string tests[]; From 4322694f7ab2b47d8017d7cd1570e8e43642d721 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 7 Apr 2021 19:12:43 -0500 Subject: [PATCH 38/55] Switch to use RV64IC for the benchmarks. Still not working correctly with the icache. instr addr correct got --- testsBP/crt0/Makefile | 9 +- testsBP/mibench_qsort/LICENSE | 3 + testsBP/mibench_qsort/Makefile | 19 + testsBP/mibench_qsort/qsort_small.c | 10038 ++++++++++++++++ testsBP/sieve/Makefile | 8 +- testsBP/simple/Makefile | 7 +- testsBP/simple/lbu_test.s | 19 + wally-pipelined/bin/exe2memfile0.pl | 4 - wally-pipelined/regression/wave.do | 85 +- wally-pipelined/src/uncore/dtim.sv | 16 +- .../testbench/testbench-imperas.sv | 13 +- 11 files changed, 10165 insertions(+), 56 deletions(-) create mode 100644 testsBP/mibench_qsort/LICENSE create mode 100644 testsBP/mibench_qsort/Makefile create mode 100644 testsBP/mibench_qsort/qsort_small.c create mode 100644 testsBP/simple/lbu_test.s diff --git a/testsBP/crt0/Makefile b/testsBP/crt0/Makefile index 97b83faf..ab47384f 100644 --- a/testsBP/crt0/Makefile +++ b/testsBP/crt0/Makefile @@ -3,10 +3,13 @@ TARGET := $(TARGETDIR)/start ROOT := .. LIBRARY_DIRS := LIBRARY_FILES := -LINK_FLAGS := -nostartfiles -AFLAGS =-march=rv64ifd -W -CFLAGS =-march=rv64ifd -mcmodel=medany +MARCH :=-march=rv64ic +MABI :=-mabi=lp64 +LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles + +AFLAGS =$(MARCH) $(MABI) -march=rv64ic -mabi=lp64 -W +CFLAGS =$(MARCH) $(MABI) -march=rv64ic -mabi=lp64 -mcmodel=medany AS=riscv64-unknown-elf-as CC=riscv64-unknown-elf-gcc AR=riscv64-unknown-elf-ar diff --git a/testsBP/mibench_qsort/LICENSE b/testsBP/mibench_qsort/LICENSE new file mode 100644 index 00000000..6016daa7 --- /dev/null +++ b/testsBP/mibench_qsort/LICENSE @@ -0,0 +1,3 @@ +Matt wrote this using STL. + +It is GPL'ed. diff --git a/testsBP/mibench_qsort/Makefile b/testsBP/mibench_qsort/Makefile new file mode 100644 index 00000000..f4d36839 --- /dev/null +++ b/testsBP/mibench_qsort/Makefile @@ -0,0 +1,19 @@ +TARGETDIR := qsort +TARGET := $(TARGETDIR)/$(TARGETDIR).elf +ROOT := .. +LIBRARY_DIRS := ${ROOT}/crt0 +LIBRARY_FILES := crt0 + +MARCH :=-march=rv64ic +MABI :=-mabi=lp64 +LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles -Wl,-Map=$(TARGET).map + +CFLAGS =$(MARCH) $(MABI) -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align + +CC=riscv64-unknown-elf-gcc +DA=riscv64-unknown-elf-objdump -d + + +include $(ROOT)/makefile.inc + + diff --git a/testsBP/mibench_qsort/qsort_small.c b/testsBP/mibench_qsort/qsort_small.c new file mode 100644 index 00000000..1b28eea4 --- /dev/null +++ b/testsBP/mibench_qsort/qsort_small.c @@ -0,0 +1,10038 @@ +#include +#include +#include + +#define UNLIMIT +#define MAXARRAY 11000 /* this number, if too large, will cause a seg. fault!! */ + +struct myStringStruct { + char qstring[128]; +}; + +struct myStringStruct array[MAXARRAY]; + +int compare(const void *elem1, const void *elem2) +{ + int result; + + result = strcmp((*((struct myStringStruct *)elem1)).qstring, (*((struct myStringStruct *)elem2)).qstring); + + return (result < 0) ? 1 : ((result == 0) ? 0 : -1); +} + + +int +main(int argc, char *argv[]) { + FILE *fp; + int i,count=0; + +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "stick"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Understand"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "friends"); +strcpy(array[count++].qstring, "come"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "go"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "precious"); +strcpy(array[count++].qstring, "few"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "should"); +strcpy(array[count++].qstring, "hold"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "Work"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "bridge"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "gaps"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "geography"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "lifestyle"); +strcpy(array[count++].qstring, "because"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "older"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "need"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "knew"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "New"); +strcpy(array[count++].qstring, "York"); +strcpy(array[count++].qstring, "City"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "hard"); +strcpy(array[count++].qstring, "Live"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "Northern"); +strcpy(array[count++].qstring, "California"); +strcpy(array[count++].qstring, "once"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "leave"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "makes"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "soft"); +strcpy(array[count++].qstring, "Travel"); +strcpy(array[count++].qstring, "Accept"); +strcpy(array[count++].qstring, "certain"); +strcpy(array[count++].qstring, "inalienable"); +strcpy(array[count++].qstring, "truths"); +strcpy(array[count++].qstring, "Prices"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "rise"); +strcpy(array[count++].qstring, "Politicians"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "philander"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "get"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "And"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "fantasize"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "young"); +strcpy(array[count++].qstring, "prices"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "reasonable"); +strcpy(array[count++].qstring, "politicians"); +strcpy(array[count++].qstring, "were"); +strcpy(array[count++].qstring, "noble"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "respected"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Respect"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "elders"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "expect"); +strcpy(array[count++].qstring, "anyone"); +strcpy(array[count++].qstring, "else"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "support"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "fund"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "wealthy"); +strcpy(array[count++].qstring, "spouse"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "might"); +strcpy(array[count++].qstring, "run"); +strcpy(array[count++].qstring, "out"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "mess"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "hair"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "85"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "careful"); +strcpy(array[count++].qstring, "whose"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "buy"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "patient"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "those"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "supply"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Advice"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "form"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "nostalgia"); +strcpy(array[count++].qstring, "Dispensing"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "fishing"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "from"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "disposal"); +strcpy(array[count++].qstring, "wiping"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "off"); +strcpy(array[count++].qstring, "painting"); +strcpy(array[count++].qstring, "over"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "parts"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recycling"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "worth"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "Kurt"); +strcpy(array[count++].qstring, "Vonneguts"); +strcpy(array[count++].qstring, "Commencement"); +strcpy(array[count++].qstring, "Address"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "MIT"); +strcpy(array[count++].qstring, "Ladies"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "gentlemen"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "class"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "97"); +strcpy(array[count++].qstring, "Wear"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "could"); +strcpy(array[count++].qstring, "offer"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "tip"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "would"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "longterm"); +strcpy(array[count++].qstring, "benefits"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "sunscreen"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "been"); +strcpy(array[count++].qstring, "proved"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "scientists"); +strcpy(array[count++].qstring, "whereas"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "rest"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "has"); +strcpy(array[count++].qstring, "no"); +strcpy(array[count++].qstring, "basis"); +strcpy(array[count++].qstring, "more"); +strcpy(array[count++].qstring, "reliable"); +strcpy(array[count++].qstring, "than"); +strcpy(array[count++].qstring, "my"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "meandering"); +strcpy(array[count++].qstring, "experience"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "dispense"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "advice"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "Oh"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "understand"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "power"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "youth"); +strcpy(array[count++].qstring, "until"); +strcpy(array[count++].qstring, "theyve"); +strcpy(array[count++].qstring, "faded"); +strcpy(array[count++].qstring, "But"); +strcpy(array[count++].qstring, "trust"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "20"); +strcpy(array[count++].qstring, "years"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "look"); +strcpy(array[count++].qstring, "back"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "photos"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "recall"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "a"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "cant"); +strcpy(array[count++].qstring, "grasp"); +strcpy(array[count++].qstring, "now"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "possibility"); +strcpy(array[count++].qstring, "lay"); +strcpy(array[count++].qstring, "before"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "fabulous"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "really"); +strcpy(array[count++].qstring, "looked"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "fat"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "imagine"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "about"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "future"); +strcpy(array[count++].qstring, "Or"); +strcpy(array[count++].qstring, "worry"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "worrying"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "effective"); +strcpy(array[count++].qstring, "as"); +strcpy(array[count++].qstring, "trying"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "solve"); +strcpy(array[count++].qstring, "an"); +strcpy(array[count++].qstring, "algebra"); +strcpy(array[count++].qstring, "equation"); +strcpy(array[count++].qstring, "by"); +strcpy(array[count++].qstring, "chewing"); +strcpy(array[count++].qstring, "bubble"); +strcpy(array[count++].qstring, "gum"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "real"); +strcpy(array[count++].qstring, "troubles"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "apt"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "things"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "crossed"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "worried"); +strcpy(array[count++].qstring, "mind"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "blindside"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "4"); +strcpy(array[count++].qstring, "pm"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "some"); +strcpy(array[count++].qstring, "idle"); +strcpy(array[count++].qstring, "Tuesday"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "one"); +strcpy(array[count++].qstring, "thing"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "day"); +strcpy(array[count++].qstring, "that"); +strcpy(array[count++].qstring, "scares"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "Sing"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "peoples"); +strcpy(array[count++].qstring, "hearts"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "put"); +strcpy(array[count++].qstring, "up"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "who"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "reckless"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yours"); +strcpy(array[count++].qstring, "Floss"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "waste"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "time"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "jealousy"); +strcpy(array[count++].qstring, "Sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "ahead"); +strcpy(array[count++].qstring, "sometimes"); +strcpy(array[count++].qstring, "youre"); +strcpy(array[count++].qstring, "behind"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "race"); +strcpy(array[count++].qstring, "is"); +strcpy(array[count++].qstring, "long"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "end"); +strcpy(array[count++].qstring, "its"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "Remember"); +strcpy(array[count++].qstring, "compliments"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "receive"); +strcpy(array[count++].qstring, "Forget"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "insults"); +strcpy(array[count++].qstring, "If"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "succeed"); +strcpy(array[count++].qstring, "in"); +strcpy(array[count++].qstring, "doing"); +strcpy(array[count++].qstring, "this"); +strcpy(array[count++].qstring, "tell"); +strcpy(array[count++].qstring, "me"); +strcpy(array[count++].qstring, "how"); +strcpy(array[count++].qstring, "Keep"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "love"); +strcpy(array[count++].qstring, "letters"); +strcpy(array[count++].qstring, "Throw"); +strcpy(array[count++].qstring, "away"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "old"); +strcpy(array[count++].qstring, "bank"); +strcpy(array[count++].qstring, "statements"); +strcpy(array[count++].qstring, "Stretch"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "guilty"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "want"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "life"); +strcpy(array[count++].qstring, "The"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "didnt"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "22"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "they"); +strcpy(array[count++].qstring, "wanted"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "with"); +strcpy(array[count++].qstring, "their"); +strcpy(array[count++].qstring, "lives"); +strcpy(array[count++].qstring, "Some"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "interesting"); +strcpy(array[count++].qstring, "40yearolds"); +strcpy(array[count++].qstring, "I"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "still"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "plenty"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "calcium"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "kind"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "knees"); +strcpy(array[count++].qstring, "Youll"); +strcpy(array[count++].qstring, "miss"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyre"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "marry"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "children"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "wont"); +strcpy(array[count++].qstring, "Maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "divorce"); +strcpy(array[count++].qstring, "at"); +strcpy(array[count++].qstring, "40"); +strcpy(array[count++].qstring, "maybe"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "dance"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "funky"); +strcpy(array[count++].qstring, "chicken"); +strcpy(array[count++].qstring, "on"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "75th"); +strcpy(array[count++].qstring, "wedding"); +strcpy(array[count++].qstring, "anniversary"); +strcpy(array[count++].qstring, "Whatever"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "congratulate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "too"); +strcpy(array[count++].qstring, "much"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "berate"); +strcpy(array[count++].qstring, "yourself"); +strcpy(array[count++].qstring, "either"); +strcpy(array[count++].qstring, "Your"); +strcpy(array[count++].qstring, "choices"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "half"); +strcpy(array[count++].qstring, "chance"); +strcpy(array[count++].qstring, "So"); +strcpy(array[count++].qstring, "are"); +strcpy(array[count++].qstring, "everybody"); +strcpy(array[count++].qstring, "elses"); +strcpy(array[count++].qstring, "Enjoy"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "body"); +strcpy(array[count++].qstring, "Use"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "every"); +strcpy(array[count++].qstring, "way"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "can"); +strcpy(array[count++].qstring, "Dont"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "afraid"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "or"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "what"); +strcpy(array[count++].qstring, "other"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "think"); +strcpy(array[count++].qstring, "of"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "Its"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "greatest"); +strcpy(array[count++].qstring, "instrument"); +strcpy(array[count++].qstring, "youll"); +strcpy(array[count++].qstring, "ever"); +strcpy(array[count++].qstring, "own"); +strcpy(array[count++].qstring, "Dance"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "have"); +strcpy(array[count++].qstring, "nowhere"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "do"); +strcpy(array[count++].qstring, "it"); +strcpy(array[count++].qstring, "but"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "living"); +strcpy(array[count++].qstring, "room"); +strcpy(array[count++].qstring, "Read"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "directions"); +strcpy(array[count++].qstring, "even"); +strcpy(array[count++].qstring, "if"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "dont"); +strcpy(array[count++].qstring, "follow"); +strcpy(array[count++].qstring, "them"); +strcpy(array[count++].qstring, "Do"); +strcpy(array[count++].qstring, "not"); +strcpy(array[count++].qstring, "read"); +strcpy(array[count++].qstring, "beauty"); +strcpy(array[count++].qstring, "magazines"); +strcpy(array[count++].qstring, "They"); +strcpy(array[count++].qstring, "will"); +strcpy(array[count++].qstring, "only"); +strcpy(array[count++].qstring, "make"); +strcpy(array[count++].qstring, "you"); +strcpy(array[count++].qstring, "feel"); +strcpy(array[count++].qstring, "ugly"); +strcpy(array[count++].qstring, "Get"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "parents"); +strcpy(array[count++].qstring, "You"); +strcpy(array[count++].qstring, "never"); +strcpy(array[count++].qstring, "know"); +strcpy(array[count++].qstring, "when"); +strcpy(array[count++].qstring, "theyll"); +strcpy(array[count++].qstring, "be"); +strcpy(array[count++].qstring, "gone"); +strcpy(array[count++].qstring, "for"); +strcpy(array[count++].qstring, "good"); +strcpy(array[count++].qstring, "Be"); +strcpy(array[count++].qstring, "nice"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "siblings"); +strcpy(array[count++].qstring, "Theyre"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "best"); +strcpy(array[count++].qstring, "link"); +strcpy(array[count++].qstring, "to"); +strcpy(array[count++].qstring, "your"); +strcpy(array[count++].qstring, "past"); +strcpy(array[count++].qstring, "and"); +strcpy(array[count++].qstring, "the"); +strcpy(array[count++].qstring, "people"); +strcpy(array[count++].qstring, "most"); +strcpy(array[count++].qstring, "likely"); +strcpy(array[count++].qstring, "to"); + + + +//printf("\nSorting %d elements.\n\n",count); + qsort(array,count,sizeof(struct myStringStruct),compare); + + //for(i=0;iautoflush(1); # *** Ross Thompson I think there is a bug here needs to be +1 -<<<<<<< HEAD print ("Processing $#ARGV memfiles: \n"); -======= -print ("Processing $#ARGV memfiles: "); ->>>>>>> icache_bp_bug my $frac = $#ARGV/10; for(my $i=0; $i<=$#ARGV; $i++) { if ($i < 10 || $i % $frac == 0) { print ("$i ") }; diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 7b48f4a5..6a935d58 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -59,29 +59,30 @@ add wave -noupdate -group Bpred -expand -group direction -group other /testbench add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredClassNonCFIWrongE +add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCSrcE add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE add wave -noupdate -group Bpred -expand -group {bp wrong} -divider pcs add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD -add wave -noupdate -group Bpred -expand -group BTB -divider Update -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ -add wave -noupdate -group Bpred -expand -group BTB -divider Lookup -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass -add wave -noupdate -group Bpred -expand -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid +add wave -noupdate -group Bpred -group BTB -divider Update +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ +add wave -noupdate -group Bpred -group BTB -divider Lookup +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass +add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory -add wave -noupdate -group Bpred -expand -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC -add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrF +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory +add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM @@ -94,25 +95,26 @@ add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD -add wave -noupdate -group {Decode Stage} /testbench/InstrDName -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D -add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D -add wave -noupdate -group RegFile -expand /testbench/dut/hart/ieu/dp/regf/rf -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 -add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW -add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ifu/InstrD +add wave -noupdate -expand -group {Decode Stage} /testbench/InstrDName +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D +add wave -noupdate -expand -group {Decode Stage} /testbench/dut/hart/ifu/ic/DelaySideF +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 +add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol @@ -186,8 +188,8 @@ add wave -noupdate /testbench/dut/imem/InstrF add wave -noupdate /testbench/dut/InstrF add wave -noupdate /testbench/dut/InstrF add wave -noupdate -divider {New Divider} +add wave -noupdate /testbench/dut/hart/ifu/ic/InDataF add wave -noupdate /testbench/dut/hart/ifu/InstrInF -add wave -noupdate /testbench/dut/hart/ifu/rd2 add wave -noupdate /testbench/dut/hart/InstrRData add wave -noupdate /testbench/dut/hart/rd2 add wave -noupdate /testbench/dut/hart/ebu/InstrRData @@ -217,9 +219,10 @@ add wave -noupdate -radix hexadecimal /testbench/dut/uncore/dtim/HADDR add wave -noupdate /testbench/dut/uncore/dtim/RAM add wave -noupdate /testbench/dut/uncore/dtim/HREADTim add wave -noupdate /testbench/dut/uncore/dtim/HREADTim0 +add wave -noupdate /testbench/dut/uncore/dtim/HRESETn TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 7} {15047768 ns} 0} {{Cursor 2} {34763538 ns} 0} {{Cursor 3} {15046271 ns} 0} {{Cursor 4} {15047307 ns} 0} -quietly wave cursor active 1 +WaveRestoreCursors {{Cursor 7} {10896277 ns} 1} {{Cursor 9} {10896453 ns} 0} {{wrong instruction} {10895117 ns} 0} +quietly wave cursor active 3 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 configure wave -justifyvalue left @@ -234,4 +237,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {15047734 ns} {15047902 ns} +WaveRestoreZoom {10895029 ns} {10895205 ns} diff --git a/wally-pipelined/src/uncore/dtim.sv b/wally-pipelined/src/uncore/dtim.sv index 29d938f1..778c509f 100644 --- a/wally-pipelined/src/uncore/dtim.sv +++ b/wally-pipelined/src/uncore/dtim.sv @@ -37,6 +37,9 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( output logic HRESPTim, HREADYTim ); + localparam integer MemStartAddr = BASE>>(1+`XLEN/32); + localparam integer MemEndAddr = (RANGE+BASE)>>1+(`XLEN/32); + logic [`XLEN-1:0] RAM[BASE>>(1+`XLEN/32):(RANGE+BASE)>>1+(`XLEN/32)]; logic [31:0] HWADDR, A; logic [`XLEN-1:0] HREADTim0; @@ -48,6 +51,7 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( logic memread, memwrite; logic [3:0] busycount; + assign initTrans = HREADY & HSELTim & (HTRANS != 2'b00); // *** this seems like a weird way to use reset @@ -82,12 +86,22 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( assign risingHREADYTim = HREADYTim & ~prevHREADYTim; // Model memory read and write +/* -----\/----- EXCLUDED -----\/----- + integer index; + + initial begin + for(index = MemStartAddr; index < MemEndAddr; index = index + 1) begin + RAM[index] <= {`XLEN{1'b0}}; + end + end + -----/\----- EXCLUDED -----/\----- */ + generate if (`XLEN == 64) begin always_ff @(posedge HCLK) begin HWADDR <= #1 A; HREADTim0 <= #1 RAM[A[31:3]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; + if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; end end else begin always_ff @(posedge HCLK) begin diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 772c3ec8..5670b431 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -386,17 +386,24 @@ string tests32i[] = { InstrEName, InstrMName, InstrWName); // initialize tests + localparam integer MemStartAddr = `TIMBASE>>(1+`XLEN/32); + localparam integer MemEndAddr = (`TIMRANGE+`TIMBASE)>>1+(`XLEN/32); + initial begin test = 0; totalerrors = 0; testadr = 0; // fill memory with defined values to reduce Xs in simulation + // Quick note the memory will need to be initialized. The C library does not + // guarantee the initialized reads. For example a strcmp can read 6 byte + // strings, but uses a load double to read them in. If the last 2 bytes are + // not initialized the compare results in an 'x' which propagates through + // the design. if (`XLEN == 32) meminit = 32'hFEDC0123; else meminit = 64'hFEDCBA9876543210; - for (i=0; i<=65535; i = i+1) begin - //dut.imem.RAM[i] = meminit; - // dut.uncore.RAM[i] = meminit; + for (i=MemStartAddr; i Date: Thu, 8 Apr 2021 15:05:08 -0500 Subject: [PATCH 39/55] Created special test for driving the instruction spill error. The extact problem occurs when a 4 byte instruction startles two cache blocks (or without a cache two ahbi words) and the code jumps to a cache block other than the next cache block. Consider the following sample of code. 0000000000000080 : 80: 42a9 li t0,10 82: 0001 nop 84: 0001 nop 86: 0001 nop 88: 02bd addi t0,t0,15 8a: 00628e33 add t3,t0,t1 8e: 01ce8963 beq t4,t3,a0 0000000000000092 : 92: 557d li a0,-1 94: 8082 ret 96: 00000013 nop 9a: 00000013 nop 9e: 0001 nop 00000000000000a0 : a0: 1ffd addi t6,t6,-1 a2: fc0f9fe3 bnez t6,80 a6: 4501 li a0,0 a8: 8082 ret Instructions 0x88, 0x8a and 0x8e are read incorrectly. However once the branch predictor begins to correctly predict the beq at 0x8e the instrution at 0xa0 is loaded incorrectly as the 2 upper bytes of 0x8e and the two bytes of 0x92. This amalgamation causes c.addi at 0xa0 to do something else and the loop never terminates. The button of wavefile wave.do shows the exact problem in the 'icache'. --- testsBP/simple/header.h | 1 + testsBP/simple/main.c | 11 +- wally-pipelined/regression/wave.do | 171 ++++++++++++++++------------- 3 files changed, 101 insertions(+), 82 deletions(-) diff --git a/testsBP/simple/header.h b/testsBP/simple/header.h index a52bf804..bfe014a4 100644 --- a/testsBP/simple/header.h +++ b/testsBP/simple/header.h @@ -4,4 +4,5 @@ int fail(); int simple_csrbr_test(); int lbu_test(); +int icache_spill_test(); #endif diff --git a/testsBP/simple/main.c b/testsBP/simple/main.c index 97adcb7c..3e863f81 100644 --- a/testsBP/simple/main.c +++ b/testsBP/simple/main.c @@ -1,11 +1,16 @@ #include "header.h" int main(){ - int res = simple_csrbr_test(); + int res = icache_spill_test(); if (res < 0) { fail(); return 0; - }else - res = lbu_test(); + }else { + if((res = lbu_test()) < 0) { + fail(); + return 0; + } + res = simple_csrbr_test(); return 0; + } } diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 6a935d58..68946a6d 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -38,51 +38,51 @@ add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbe add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallE add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallM add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/ifu/StallW -add wave -noupdate -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF -add wave -noupdate -group Bpred -expand -group direction -divider Lookup -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/BPPredF -add wave -noupdate -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/BPPredPCF -add wave -noupdate -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/SelBPPredF -add wave -noupdate -group Bpred -expand -group direction -divider Update -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN -add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction -add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding -add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF -add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD -add wave -noupdate -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredClassNonCFIWrongE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCSrcE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group Bpred -expand -group {bp wrong} -divider pcs -add wave -noupdate -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD -add wave -noupdate -group Bpred -group BTB -divider Update -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ -add wave -noupdate -group Bpred -group BTB -divider Lookup -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass -add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid -add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory -add wave -noupdate -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC +add wave -noupdate -expand -group Bpred -expand -group direction -color Yellow /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRF +add wave -noupdate -expand -group Bpred -expand -group direction -divider Lookup +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPC +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/LookUpPCIndex +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/PredictionMemory +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/Prediction +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/BPPredF +add wave -noupdate -expand -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/BPPredPCF +add wave -noupdate -expand -group Bpred -expand -group direction -expand -group output /testbench/dut/hart/ifu/bpred/SelBPPredF +add wave -noupdate -expand -group Bpred -expand -group direction -divider Update +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePCIndex +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN +add wave -noupdate -expand -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePrediction +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwarding +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/DoForwardingF +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRD +add wave -noupdate -expand -group Bpred -expand -group direction -group other /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/GHRE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/TargetWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/FallThroughWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PredictionPCWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredClassNonCFIWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCSrcE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} -divider pcs +add wave -noupdate -expand -group Bpred -expand -group {bp wrong} /testbench/dut/hart/ifu/bpred/PCD +add wave -noupdate -expand -group Bpred -group BTB -divider Update +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateEN +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePC +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/InstrClassE +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdateTarget +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/UpdatePCIndexQ +add wave -noupdate -expand -group Bpred -group BTB -divider Lookup +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/InstrClass +add wave -noupdate -expand -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid +add wave -noupdate -expand -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pop +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/push +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/pushPC +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrD +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/PtrQ +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/memory +add wave -noupdate -expand -group Bpred -group RAS /testbench/dut/hart/ifu/bpred/RASPredictor/popPC add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM @@ -152,7 +152,7 @@ add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCNextF -add wave -noupdate -expand -group PCS /testbench/dut/hart/PCF +add wave -noupdate -expand -group PCS -color Yellow /testbench/dut/hart/PCF add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE add wave -noupdate -expand -group PCS /testbench/dut/hart/PCM @@ -188,40 +188,53 @@ add wave -noupdate /testbench/dut/imem/InstrF add wave -noupdate /testbench/dut/InstrF add wave -noupdate /testbench/dut/InstrF add wave -noupdate -divider {New Divider} -add wave -noupdate /testbench/dut/hart/ifu/ic/InDataF -add wave -noupdate /testbench/dut/hart/ifu/InstrInF -add wave -noupdate /testbench/dut/hart/InstrRData -add wave -noupdate /testbench/dut/hart/rd2 -add wave -noupdate /testbench/dut/hart/ebu/InstrRData -add wave -noupdate /testbench/dut/hart/ebu/InstrPAdrF -add wave -noupdate /testbench/dut/hart/ebu/HRDATA -add wave -noupdate /testbench/dut/uncore/HSELUARTD -add wave -noupdate /testbench/dut/uncore/HSELUART -add wave -noupdate /testbench/dut/uncore/HSELTimD -add wave -noupdate /testbench/dut/uncore/HSELTim -add wave -noupdate /testbench/dut/uncore/HSELPLICD -add wave -noupdate /testbench/dut/uncore/HSELPLIC -add wave -noupdate /testbench/dut/uncore/HSELGPIOD -add wave -noupdate /testbench/dut/uncore/HSELGPIO -add wave -noupdate /testbench/dut/uncore/HSELCLINTD -add wave -noupdate /testbench/dut/uncore/HSELCLINT -add wave -noupdate /testbench/dut/uncore/HSELBootTimD -add wave -noupdate /testbench/dut/uncore/HSELBootTim -add wave -noupdate /testbench/dut/uncore/HREADTim -add wave -noupdate /testbench/dut/uncore/dtim/HREADTim -add wave -noupdate /testbench/dut/uncore/dtim/HREADTim0 -add wave -noupdate /testbench/dut/uncore/dtim/BASE -add wave -noupdate /testbench/dut/uncore/dtim/RANGE -add wave -noupdate /testbench/memfilename -add wave -noupdate {/testbench/dut/uncore/dtim/RAM[770056]} -add wave -noupdate {/testbench/dut/uncore/dtim/RAM[771306]} add wave -noupdate -radix hexadecimal /testbench/dut/uncore/dtim/HADDR -add wave -noupdate /testbench/dut/uncore/dtim/RAM -add wave -noupdate /testbench/dut/uncore/dtim/HREADTim -add wave -noupdate /testbench/dut/uncore/dtim/HREADTim0 -add wave -noupdate /testbench/dut/uncore/dtim/HRESETn +add wave -noupdate {/testbench/dut/uncore/dtim/RAM[93182]} +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/ifu/ic/InDataF +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/ifu/InstrInF +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/InstrRData +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/rd2 +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/ebu/InstrRData +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/ebu/InstrPAdrF +add wave -noupdate -group {ahbi debug} /testbench/dut/hart/ebu/HRDATA +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELUARTD +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELUART +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELTimD +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELTim +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELPLICD +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELPLIC +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELGPIOD +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELGPIO +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELCLINTD +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELCLINT +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELBootTimD +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HSELBootTim +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/HREADTim +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/HREADTim +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/HREADTim0 +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/BASE +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/RANGE +add wave -noupdate -group {ahbi debug} /testbench/memfilename +add wave -noupdate -group {ahbi debug} {/testbench/dut/uncore/dtim/RAM[770056]} +add wave -noupdate -group {ahbi debug} {/testbench/dut/uncore/dtim/RAM[771306]} +add wave -noupdate -group {ahbi debug} -radix hexadecimal /testbench/dut/uncore/dtim/HADDR +add wave -noupdate -group {ahbi debug} {/testbench/dut/uncore/dtim/RAM[93182]} +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/RAM +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/HREADTim +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/HREADTim0 +add wave -noupdate -group {ahbi debug} /testbench/dut/uncore/dtim/HRESETn +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/PCPF +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/DelaySideF +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/InstrPAdrF +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/InstrInF +add wave -noupdate -expand -group {icache debug} -color Yellow /testbench/dut/hart/PCF +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/InstrF +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/DelayF +add wave -noupdate -expand -group {icache debug} /testbench/dut/hart/ifu/ic/CompressedF +add wave -noupdate -color Yellow /testbench/dut/hart/ifu/PCD +add wave -noupdate /testbench/dut/hart/ifu/ic/InstrRawD TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 7} {10896277 ns} 1} {{Cursor 9} {10896453 ns} 0} {{wrong instruction} {10895117 ns} 0} +WaveRestoreCursors {{Cursor 7} {10896277 ns} 1} {{Cursor 9} {10896453 ns} 0} {{wrong instruction} {3708 ns} 0} quietly wave cursor active 3 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -237,4 +250,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {10895029 ns} {10895205 ns} +WaveRestoreZoom {3592 ns} {3824 ns} From fc8b8ad7aa746b2776d5ff8582b35a336c553e89 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Tue, 13 Apr 2021 01:06:57 -0400 Subject: [PATCH 40/55] A few more cache fixes --- wally-pipelined/src/cache/cache-sram.sv | 22 +++++ wally-pipelined/src/cache/dmapped.sv | 92 ++++++++++--------- wally-pipelined/src/ifu/icache.sv | 33 ++++--- wally-pipelined/src/ifu/ifu.sv | 8 +- .../testbench/testbench-imperas.sv | 2 +- 5 files changed, 95 insertions(+), 62 deletions(-) create mode 100644 wally-pipelined/src/cache/cache-sram.sv diff --git a/wally-pipelined/src/cache/cache-sram.sv b/wally-pipelined/src/cache/cache-sram.sv new file mode 100644 index 00000000..0ba0efa5 --- /dev/null +++ b/wally-pipelined/src/cache/cache-sram.sv @@ -0,0 +1,22 @@ +// Depth is number of bits in one "word" of the memory, width is number of such words +module Sram1Read1Write #(parameter DEPTH=128, WIDTH=256) ( + input logic clk, + // port 1 is read only + input logic [$clog2(WIDTH)-1:0] ReadAddr, + output logic [DEPTH-1:0] ReadData, + + // port 2 is write only + input logic [$clog2(WIDTH)-1:0] WriteAddr, + input logic [DEPTH-1:0] WriteData, + input logic WriteEnable +); + + logic [WIDTH-1:0][DEPTH-1:0] StoredData; + + always_ff @(posedge clk) begin + ReadData <= StoredData[ReadAddr]; + if (WriteEnable) begin + StoredData[WriteAddr] <= WriteData; + end + end +endmodule diff --git a/wally-pipelined/src/cache/dmapped.sv b/wally-pipelined/src/cache/dmapped.sv index 9138089e..346355bd 100644 --- a/wally-pipelined/src/cache/dmapped.sv +++ b/wally-pipelined/src/cache/dmapped.sv @@ -30,6 +30,7 @@ module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, par // Pipeline stuff input logic clk, input logic reset, + input logic stall, // If flush is high, invalidate the entire cache input logic flush, // Select which address to read (broken for efficiency's sake) @@ -45,75 +46,80 @@ module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, par ); // Various compile-time constants - localparam integer WORDWIDTH = $clog2(WORDSIZE); - localparam integer LINEWIDTH = $clog2(LINESIZE/8); - localparam integer OFFSETWIDTH = $clog2(LINESIZE) - WORDWIDTH; + localparam integer WORDWIDTH = $clog2(WORDSIZE/8); + localparam integer OFFSETWIDTH = $clog2(LINESIZE/WORDSIZE); localparam integer SETWIDTH = $clog2(NUMLINES); - localparam integer TAGWIDTH = $clog2(`XLEN) - $clog2(LINESIZE) - SETWIDTH; + localparam integer TAGWIDTH = `XLEN - OFFSETWIDTH - SETWIDTH - WORDWIDTH; + + localparam integer OFFSETBEGIN = WORDWIDTH; + localparam integer OFFSETEND = OFFSETBEGIN+OFFSETWIDTH-1; + localparam integer SETBEGIN = OFFSETEND+1; + localparam integer SETEND = SETBEGIN + SETWIDTH - 1; + localparam integer TAGBEGIN = SETEND + 1; + localparam integer TAGEND = TAGBEGIN + TAGWIDTH - 1; // Machinery to read from and write to the correct addresses in memory logic [`XLEN-1:0] ReadPAdr; + logic [`XLEN-1:0] OldReadPAdr; logic [OFFSETWIDTH-1:0] ReadOffset, WriteOffset; logic [SETWIDTH-1:0] ReadSet, WriteSet; logic [TAGWIDTH-1:0] ReadTag, WriteTag; + logic [LINESIZE-1:0] ReadLine; + logic [LINESIZE/WORDSIZE-1:0][WORDSIZE-1:0] ReadLineTransformed; // Machinery to check if a given read is valid and is the desired value logic [TAGWIDTH-1:0] DataTag; - logic [NUMLINES-1:0] ValidOut, NextValidOut; + logic [NUMLINES-1:0] ValidOut; + + flopenr #(`XLEN) ReadPAdrFlop(clk, reset, ~stall, ReadPAdr, OldReadPAdr); // Assign the read and write addresses in cache memory always_comb begin - assign ReadOffset = ReadLowerAdr[WORDWIDTH+OFFSETWIDTH-1:WORDWIDTH]; + assign ReadOffset = OldReadPAdr[OFFSETEND:OFFSETBEGIN]; assign ReadPAdr = {ReadUpperPAdr, ReadLowerAdr}; - assign ReadSet = ReadPAdr[LINEWIDTH+SETWIDTH-1:LINEWIDTH]; - assign ReadTag = ReadPAdr[`XLEN-1:LINEWIDTH+SETWIDTH]; + assign ReadSet = ReadPAdr[SETEND:SETBEGIN]; + assign ReadTag = OldReadPAdr[TAGEND:TAGBEGIN]; - assign WriteOffset = WritePAdr[WORDWIDTH+OFFSETWIDTH-1:WORDWIDTH]; - assign WriteSet = WritePAdr[LINEWIDTH+SETWIDTH-1:LINEWIDTH]; - assign WriteTag = WritePAdr[`XLEN-1:LINEWIDTH+SETWIDTH]; + assign WriteOffset = WritePAdr[OFFSETEND:OFFSETBEGIN]; + assign WriteSet = WritePAdr[SETEND:SETBEGIN]; + assign WriteTag = WritePAdr[TAGEND:TAGBEGIN]; end - SRAM2P1R1W #(.Depth(OFFSETWIDTH), .Width(WORDSIZE)) cachemem ( + // Depth is number of bits in one "word" of the memory, width is number of such words + Sram1Read1Write #(.DEPTH(LINESIZE), .WIDTH(NUMLINES)) cachemem ( .*, - .RA1(ReadOffset), - .RD1(DataWord), - .REN1(1'b1), - .WA1(WriteOffset), - .WD1(WriteSet), - .WEN1(WriteEnable), - .BitWEN1(0) + .ReadAddr(ReadSet), + .ReadData(ReadLine), + .WriteAddr(WriteSet), + .WriteData(WriteLine) + ); + Sram1Read1Write #(.DEPTH(TAGWIDTH), .WIDTH(NUMLINES)) cachetags ( + .*, + .ReadAddr(ReadSet), + .ReadData(DataTag), + .WriteAddr(WriteSet), + .WriteData(WriteTag) ); - SRAM2P1R1W #(.Depth(OFFSETWIDTH), .Width(TAGWIDTH)) cachetags ( - .*, - .RA1(ReadOffset), - .RD1(DataTag), - .REN1(1'b1), - .WA1(WriteOffset), - .WD1(WriteTag), - .WEN1(WriteEnable), - .BitWEN1(0) - ); + // Pick the right bits coming out the read line + assign DataWord = ReadLineTransformed[ReadOffset]; + genvar i; + generate + for (i=0; i < LINESIZE/WORDSIZE; i++) begin + assign ReadLineTransformed[i] = ReadLine[(i+1)*WORDSIZE-1:i*WORDSIZE]; + end + endgenerate // Correctly handle the valid bits - always_comb begin - if (WriteEnable) begin - assign NextValidOut = {NextValidOut[NUMLINES-1:WriteSet+1], 1'b1, NextValidOut[WriteSet-1:0]}; - end else begin - assign NextValidOut = ValidOut; - end - end - always_ff @(posedge clk, reset, flush) begin + always_ff @(posedge clk, posedge reset) begin if (reset || flush) begin ValidOut <= {NUMLINES{1'b0}}; end else begin - ValidOut <= NextValidOut; + if (WriteEnable) begin + ValidOut[WriteSet] <= 1; + end end - end - - // Determine if the line coming out is valid and matches the desired data - always_comb begin - assign DataValid = ValidOut[ReadSet] && (DataTag == ReadTag); + DataValid <= ValidOut[ReadSet] && (DataTag == ReadTag); end endmodule diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 0d953760..e42edb49 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -31,9 +31,9 @@ module icache( input logic StallF, StallD, input logic FlushD, // Upper bits of physical address for PC - input logic [`XLEN-1:12] UpperPCPF, + input logic [`XLEN-1:12] UpperPCNextPF, // Lower 12 bits of virtual PC address, since it's faster this way - input logic [11:0] LowerPCF, + input logic [11:0] LowerPCNextF, // Data read in from the ebu unit input logic [`XLEN-1:0] InstrInF, input logic InstrAckF, @@ -65,8 +65,9 @@ module icache( logic [`XLEN-1:0] ICacheMemReadData; logic ICacheMemReadValid; - rodirectmappedmem #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES)) cachemem( + rodirectmappedmem #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES), .WORDSIZE(`XLEN)) cachemem( .*, + .stall(StallF && (~ICacheStallF || ~InstrAckF)), .flush(FlushMem), .ReadUpperPAdr(ICacheMemReadUpperPAdr), .ReadLowerAdr(ICacheMemReadLowerAdr), @@ -79,6 +80,7 @@ module icache( icachecontroller #(.LINESIZE(ICACHELINESIZE)) controller(.*); + // For now, assume no writes to executable memory assign FlushMem = 1'b0; endmodule @@ -90,9 +92,9 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Input the address to read // The upper bits of the physical pc - input logic [`XLEN-1:12] UpperPCPF, + input logic [`XLEN-1:12] UpperPCNextPF, // The lower bits of the virtual pc - input logic [11:0] LowerPCF, + input logic [11:0] LowerPCNextF, // Signals to/from cache memory // The read coming out of it @@ -130,6 +132,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( logic FlushDLastCycleN; logic PCPMisalignedF; const logic [31:0] NOP = 32'h13; + logic [`XLEN-1:0] PCPF; // Misaligned signals logic [`XLEN:0] MisalignedInstrRawF; logic MisalignedStall; @@ -143,18 +146,19 @@ module icachecontroller #(parameter LINESIZE = 256) ( generate if (`XLEN == 32) begin - assign AlignedInstrRawF = LowerPCF[1] ? MisalignedInstrRawF : ICacheMemReadData; - assign PCPMisalignedF = LowerPCF[1] && ~CompressedF; + assign AlignedInstrRawF = PCPF[1] ? MisalignedInstrRawF : ICacheMemReadData; + assign PCPMisalignedF = PCPF[1] && ~CompressedF; end else begin - assign AlignedInstrRawF = LowerPCF[2] - ? (LowerPCF[1] ? MisalignedInstrRawF : ICacheMemReadData[63:32]) - : (LowerPCF[1] ? ICacheMemReadData[47:16] : ICacheMemReadData[31:0]); - assign PCPMisalignedF = LowerPCF[2] && LowerPCF[1] && ~CompressedF; + assign AlignedInstrRawF = PCPF[2] + ? (PCPF[1] ? MisalignedInstrRawF : ICacheMemReadData[63:32]) + : (PCPF[1] ? ICacheMemReadData[47:16] : ICacheMemReadData[31:0]); + assign PCPMisalignedF = PCPF[2] && PCPF[1] && ~CompressedF; end endgenerate flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD); flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN); + flopenr #(`XLEN) PCPFFlop(clk, reset, ~StallF, {UpperPCNextPF, LowerPCNextF}, PCPF); mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD); // Stall for faults or misaligned reads @@ -197,12 +201,13 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Pick the correct address to read generate if (`XLEN == 32) begin - assign ICacheMemReadLowerAdr = {LowerPCF[11:2] + (PCPMisalignedF & ~MisalignedState), 2'b00}; + assign ICacheMemReadLowerAdr = {LowerPCNextF[11:2] + (PCPMisalignedF & ~MisalignedState), 2'b00}; end else begin - assign ICacheMemReadLowerAdr = {LowerPCF[11:3] + (PCPMisalignedF & ~MisalignedState), 3'b00}; + assign ICacheMemReadLowerAdr = {LowerPCNextF[11:3] + (PCPMisalignedF & ~MisalignedState), 3'b00}; end endgenerate - assign ICacheMemReadUpperPAdr = UpperPCPF; + // TODO Handle reading instructions that cross page boundaries + assign ICacheMemReadUpperPAdr = UpperPCNextPF; // Handle cache faults diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 3347d80c..2ddd6706 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -71,7 +71,7 @@ module ifu ( logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM; logic PrivilegedChangePCM; logic IllegalCompInstrD; - logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM, PCPF; + logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM, PCNextPF; logic CompressedF; logic [31:0] InstrRawD, InstrE, InstrW; logic [31:0] nop = 32'h00000013; // instruction for NOP @@ -98,12 +98,12 @@ module ifu ( // assign InstrReadF = 1; // *** & ICacheMissF; add later // jarred 2021-03-14 Add instrution cache block to remove rd2 - assign PCPF = PCF; // Temporary workaround until iTLB is live + assign PCNextPF = PCNextF; // Temporary workaround until iTLB is live icache ic( .*, .InstrPAdrF(ICacheInstrPAdrF), - .UpperPCPF(PCPF[`XLEN-1:12]), - .LowerPCF(PCF[11:0]) + .UpperPCNextPF(PCNextPF[`XLEN-1:12]), + .LowerPCNextF(PCNextF[11:0]) ); // Prioritize the iTLB for reads if it wants one mux2 #(`XLEN) instrPAdrMux(ICacheInstrPAdrF, ITLBInstrPAdrF, ITLBMissF, InstrPAdrF); diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 09c63d56..fbd4a829 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -393,7 +393,7 @@ module testbench(); // if (`F_SUPPORTED) tests = {tests64f, tests}; // if (`D_SUPPORTED) tests = {tests64d, tests}; if (`A_SUPPORTED) tests = {tests, tests64a}; - if (`MEM_VIRTMEM) tests = {tests64mmu, tests}; + if (`MEM_VIRTMEM) tests = {tests, tests64mmu}; end //tests = {tests64a, tests}; // tests = {tests, tests64p}; From 892dfd5a9bff95f018476e397dfd4130d198dd6a Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 14 Apr 2021 19:03:33 -0400 Subject: [PATCH 41/55] More icache bugfixes --- wally-pipelined/src/cache/dmapped.sv | 5 +++-- wally-pipelined/src/ifu/icache.sv | 27 +++++++++++++++------------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/wally-pipelined/src/cache/dmapped.sv b/wally-pipelined/src/cache/dmapped.sv index 634f29a9..f97cfa2d 100644 --- a/wally-pipelined/src/cache/dmapped.sv +++ b/wally-pipelined/src/cache/dmapped.sv @@ -70,6 +70,7 @@ module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, par // Machinery to check if a given read is valid and is the desired value logic [TAGWIDTH-1:0] DataTag; logic [NUMLINES-1:0] ValidOut; + logic DataValidBit; flopenr #(`XLEN) ReadPAdrFlop(clk, reset, ~stall, ReadPAdr, OldReadPAdr); @@ -119,7 +120,7 @@ module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, par ValidOut[WriteSet] <= 1; end end - DataValid <= ValidOut[ReadSet] && (DataTag == ReadTag); + DataValidBit <= ValidOut[ReadSet]; end - + assign DataValid = DataValidBit && (DataTag == ReadTag); endmodule diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index e42edb49..31d16b8a 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -61,13 +61,14 @@ module icache( logic ICacheMemWriteEnable; logic [ICACHELINESIZE-1:0] ICacheMemWriteData; logic [`XLEN-1:0] ICacheMemWritePAdr; + logic EndFetchState; // Output signals from cache memory logic [`XLEN-1:0] ICacheMemReadData; logic ICacheMemReadValid; rodirectmappedmem #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES), .WORDSIZE(`XLEN)) cachemem( .*, - .stall(StallF && (~ICacheStallF || ~InstrAckF)), + .stall(StallF && (~ICacheStallF || ~EndFetchState)), .flush(FlushMem), .ReadUpperPAdr(ICacheMemReadUpperPAdr), .ReadLowerAdr(ICacheMemReadLowerAdr), @@ -116,7 +117,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( output logic [31:0] InstrRawD, // Outputs to pipeline control stuff - output logic ICacheStallF, + output logic ICacheStallF, EndFetchState, // Signals to/from ahblite interface // A read containing the requested data @@ -142,6 +143,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Detect if the instruction is compressed assign CompressedF = AlignedInstrRawF[1:0] != 2'b11; + // Handle happy path (data in cache, reads aligned) generate @@ -216,7 +218,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( localparam integer LOGWPL = $clog2(WORDSPERLINE); localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); - logic FetchState, EndFetchState, BeginFetchState; + logic FetchState, BeginFetchState; logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; logic [`XLEN-1:0] LineAlignedPCPF; @@ -232,26 +234,27 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Enter the fetch state when we hit a cache fault always_comb begin - assign BeginFetchState = ~ICacheMemReadValid & ~FetchState; + BeginFetchState = ~ICacheMemReadValid & ~FetchState & (FetchWordNum == 0); end + // Exit the fetch state once the cache line has been loaded + flopr #(1) EndFetchStateFlop(clk, reset, ICacheMemWriteEnable, EndFetchState); // Machinery to request the correct addresses from main memory always_comb begin - assign InstrReadF = FetchState & ~EndFetchState; - assign LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; - assign InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); - assign NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; + InstrReadF = FetchState & ~EndFetchState & ~ICacheMemWriteEnable; + LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; + InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); + NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; end // Write to cache memory when we have the line here always_comb begin - assign EndFetchState = FetchWordNum == {1'b1, {LOGWPL{1'b0}}} & FetchState; - assign ICacheMemWritePAdr = LineAlignedPCPF; - assign ICacheMemWriteEnable = EndFetchState; + ICacheMemWritePAdr = LineAlignedPCPF; + ICacheMemWriteEnable = FetchWordNum == {1'b1, {LOGWPL{1'b0}}} & FetchState & ~EndFetchState; end // Stall the pipeline while loading a new line from memory always_comb begin - assign FaultStall = FetchState | ~ICacheMemReadValid; + FaultStall = FetchState | ~ICacheMemReadValid; end endmodule From 3717699ad93533f8b8005d6003b91806d66022ac Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Wed, 14 Apr 2021 23:14:59 -0400 Subject: [PATCH 42/55] Add a comment to explain a detail --- wally-pipelined/src/ifu/icache.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 31d16b8a..f6440fcf 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -68,6 +68,7 @@ module icache( rodirectmappedmem #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES), .WORDSIZE(`XLEN)) cachemem( .*, + // Stall it if the pipeline is stalled, unless we're stalling it and we're ending our stall .stall(StallF && (~ICacheStallF || ~EndFetchState)), .flush(FlushMem), .ReadUpperPAdr(ICacheMemReadUpperPAdr), From 7854d838c70e024a91614fe105f1ce3e126f74e7 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 15 Apr 2021 21:13:40 -0400 Subject: [PATCH 43/55] Enable linting of blocks not yet in the hierarchy --- wally-pipelined/lint-wally | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/wally-pipelined/lint-wally b/wally-pipelined/lint-wally index 9d5a20ba..791435ac 100755 --- a/wally-pipelined/lint-wally +++ b/wally-pipelined/lint-wally @@ -1,11 +1,25 @@ # check for warnings in Verilog code # The verilator lint tool is faster and better than Modelsim so it is best to run this first. -echo "rv64ic linting..." -verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv -echo "rv32ic linting..." -verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv -#verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv src/*/div/*.sv +if [ -n "$1" ]; then + echo "rv64ic linting..." + if verilator --lint-only --top-module "$1" -Iconfig/rv64ic src/*/*.sv; then + echo "rv32ic linting..." + verilator --lint-only --top-module "$1" -Iconfig/rv32ic src/*/*.sv + else + echo "Skipping rv32ic because rv64ic had errors or warnings" + exit 1 + fi +else + echo "rv64ic linting..." + if verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv; then + echo "rv32ic linting..." + verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv + else + echo "Skipping rv32ic because rv64ic had errors or warnings" + exit 1 + fi +fi # --lint-only just runs lint rather than trying to compile and simulate # -I points to the include directory where files such as `include wally-config.vh are found From aef57cab500b8afb47a23139838f657899ee3b20 Mon Sep 17 00:00:00 2001 From: Jarred Allen Date: Thu, 15 Apr 2021 21:13:56 -0400 Subject: [PATCH 44/55] dcache lints --- wally-pipelined/src/cache/dmapped.sv | 111 +++++++++++++++- wally-pipelined/src/dmem/dcache.sv | 184 +++++++++++++++++++++++++++ 2 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 wally-pipelined/src/dmem/dcache.sv diff --git a/wally-pipelined/src/cache/dmapped.sv b/wally-pipelined/src/cache/dmapped.sv index f97cfa2d..fb6ce4c5 100644 --- a/wally-pipelined/src/cache/dmapped.sv +++ b/wally-pipelined/src/cache/dmapped.sv @@ -4,8 +4,7 @@ // Written: jaallen@g.hmc.edu 2021-03-23 // Modified: // -// Purpose: An implementation of a direct-mapped cache memory -// This cache is read-only, so "write"s to the memory are loading new data +// Purpose: An implementation of a direct-mapped cache memory, with read-only and write-through versions // // A component of the Wally configurable RISC-V project. // @@ -26,6 +25,7 @@ `include "wally-config.vh" +// Read-only direct-mapped memory module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) ( // Pipeline stuff input logic clk, @@ -124,3 +124,110 @@ module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, par end assign DataValid = DataValidBit && (DataTag == ReadTag); endmodule + +// Write-through direct-mapped memory +module wtdirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) ( + // Pipeline stuff + input logic clk, + input logic reset, + input logic stall, + // If flush is high, invalidate the entire cache + input logic flush, + // Select which address to read (broken for efficiency's sake) + input logic [`XLEN-1:12] ReadUpperPAdr, + input logic [11:0] ReadLowerAdr, + // Load new data into the cache (from main memory) + input logic LoadEnable, + input logic [LINESIZE-1:0] LoadLine, + input logic [`XLEN-1:0] LoadPAdr, + // Write data to the cache (like from a store instruction) + input logic WriteEnable, + input logic [WORDSIZE-1:0] WriteWord, + input logic [`XLEN-1:0] WritePAdr, + input logic [1:0] WriteSize, // Specify size of the write (non-written bits should be preserved) + // Output the word, as well as if it is valid + output logic [WORDSIZE-1:0] DataWord, + output logic DataValid +); + + // Various compile-time constants + localparam integer WORDWIDTH = $clog2(WORDSIZE/8); + localparam integer OFFSETWIDTH = $clog2(LINESIZE/WORDSIZE); + localparam integer SETWIDTH = $clog2(NUMLINES); + localparam integer TAGWIDTH = `XLEN - OFFSETWIDTH - SETWIDTH - WORDWIDTH; + + localparam integer OFFSETBEGIN = WORDWIDTH; + localparam integer OFFSETEND = OFFSETBEGIN+OFFSETWIDTH-1; + localparam integer SETBEGIN = OFFSETEND+1; + localparam integer SETEND = SETBEGIN + SETWIDTH - 1; + localparam integer TAGBEGIN = SETEND + 1; + localparam integer TAGEND = TAGBEGIN + TAGWIDTH - 1; + + // Machinery to read from and write to the correct addresses in memory + logic [`XLEN-1:0] ReadPAdr; + logic [`XLEN-1:0] OldReadPAdr; + logic [OFFSETWIDTH-1:0] ReadOffset, LoadOffset; + logic [SETWIDTH-1:0] ReadSet, LoadSet; + logic [TAGWIDTH-1:0] ReadTag, LoadTag; + logic [LINESIZE-1:0] ReadLine; + logic [LINESIZE/WORDSIZE-1:0][WORDSIZE-1:0] ReadLineTransformed; + + // Machinery to check if a given read is valid and is the desired value + logic [TAGWIDTH-1:0] DataTag; + logic [NUMLINES-1:0] ValidOut; + logic DataValidBit; + + flopenr #(`XLEN) ReadPAdrFlop(clk, reset, ~stall, ReadPAdr, OldReadPAdr); + + // Assign the read and write addresses in cache memory + always_comb begin + ReadOffset = OldReadPAdr[OFFSETEND:OFFSETBEGIN]; + ReadPAdr = {ReadUpperPAdr, ReadLowerAdr}; + ReadSet = ReadPAdr[SETEND:SETBEGIN]; + ReadTag = OldReadPAdr[TAGEND:TAGBEGIN]; + + LoadOffset = LoadPAdr[OFFSETEND:OFFSETBEGIN]; + LoadSet = LoadPAdr[SETEND:SETBEGIN]; + LoadTag = LoadPAdr[TAGEND:TAGBEGIN]; + end + + // Depth is number of bits in one "word" of the memory, width is number of such words + Sram1Read1Write #(.DEPTH(LINESIZE), .WIDTH(NUMLINES)) cachemem ( + .*, + .ReadAddr(ReadSet), + .ReadData(ReadLine), + .WriteAddr(LoadSet), + .WriteData(LoadLine), + .WriteEnable(LoadEnable) + ); + Sram1Read1Write #(.DEPTH(TAGWIDTH), .WIDTH(NUMLINES)) cachetags ( + .*, + .ReadAddr(ReadSet), + .ReadData(DataTag), + .WriteAddr(LoadSet), + .WriteData(LoadTag), + .WriteEnable(LoadEnable) + ); + + // Pick the right bits coming out the read line + assign DataWord = ReadLineTransformed[ReadOffset]; + genvar i; + generate + for (i=0; i < LINESIZE/WORDSIZE; i++) begin + assign ReadLineTransformed[i] = ReadLine[(i+1)*WORDSIZE-1:i*WORDSIZE]; + end + endgenerate + + // Correctly handle the valid bits + always_ff @(posedge clk, posedge reset) begin + if (reset || flush) begin + ValidOut <= {NUMLINES{1'b0}}; + end else begin + if (LoadEnable) begin + ValidOut[LoadSet] <= 1; + end + end + DataValidBit <= ValidOut[ReadSet]; + end + assign DataValid = DataValidBit && (DataTag == ReadTag); +endmodule diff --git a/wally-pipelined/src/dmem/dcache.sv b/wally-pipelined/src/dmem/dcache.sv new file mode 100644 index 00000000..243c6975 --- /dev/null +++ b/wally-pipelined/src/dmem/dcache.sv @@ -0,0 +1,184 @@ +/////////////////////////////////////////// +// dcache.sv +// +// Written: jaallen@g.hmc.edu 2021-04-15 +// Modified: +// +// Purpose: Cache memory for the dmem so it can access memory less often, saving cycles +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////// + +`include "wally-config.vh" + +module dcache( + // Basic pipeline stuff + input logic clk, reset, + input logic StallW, + input logic FlushW, + // Upper bits of physical address + input logic [`XLEN-1:12] UpperPAdrM, + // Lower 12 bits of virtual address, since it's faster this way + input logic [11:0] LowerVAdrM, + // Write to the dcache + input logic [`XLEN-1:0] DCacheWriteDataM, + input logic DCacheReadM, DCacheWriteM, + // Data read in from the ebu unit + input logic [`XLEN-1:0] ReadDataW, + input logic MemAckW, + // Access requested from the ebu unit + output logic [`XLEN-1:0] MemPAdrM, + output logic MemReadM, MemWriteM, + // High if the dcache is requesting a stall + output logic DCacheStallW, + // The data that was requested from the cache + output logic [`XLEN-1:0] DCacheReadW +); + + // Configuration parameters + // TODO Move these to a config file + localparam integer DCACHELINESIZE = 256; + localparam integer DCACHENUMLINES = 512; + + // Input signals to cache memory + logic FlushMem; + logic [`XLEN-1:12] DCacheMemUpperPAdr; + logic [11:0] DCacheMemLowerAdr; + logic DCacheMemWriteEnable; + logic [DCACHELINESIZE-1:0] DCacheMemWriteData; + logic [`XLEN-1:0] DCacheMemWritePAdr; + logic EndFetchState; + // Output signals from cache memory + logic [`XLEN-1:0] DCacheMemReadData; + logic DCacheMemReadValid; + + wtdirectmappedmem #(.LINESIZE(DCACHELINESIZE), .NUMLINES(DCACHENUMLINES), .WORDSIZE(`XLEN)) cachemem( + .*, + // Stall it if the pipeline is stalled, unless we're stalling it and we're ending our stall + .stall(StallW), + .flush(FlushMem), + .ReadUpperPAdr(DCacheMemUpperPAdr), + .ReadLowerAdr(DCacheMemLowerAdr), + .LoadEnable(DCacheMemWriteEnable), + .LoadLine(DCacheMemWriteData), + .LoadPAdr(DCacheMemWritePAdr), + .DataWord(DCacheMemReadData), + .DataValid(DCacheMemReadValid), + .WriteEnable(0), + .WriteWord(0), + .WritePAdr(0), + .WriteSize(2'b10) + ); + + dcachecontroller #(.LINESIZE(DCACHELINESIZE)) controller(.*); + + // For now, assume no writes to executable memory + assign FlushMem = 1'b0; +endmodule + +module dcachecontroller #(parameter LINESIZE = 256) ( + // Inputs from pipeline + input logic clk, reset, + input logic StallW, + input logic FlushW, + + // Input the address to read + // The upper bits of the physical pc + input logic [`XLEN-1:12] DCacheMemUpperPAdr, + // The lower bits of the virtual pc + input logic [11:0] DCacheMemLowerAdr, + + // Signals to/from cache memory + // The read coming out of it + input logic [`XLEN-1:0] DCacheMemReadData, + input logic DCacheMemReadValid, + // Load data into the cache + output logic DCacheMemWriteEnable, + output logic [LINESIZE-1:0] DCacheMemWriteData, + output logic [`XLEN-1:0] DCacheMemWritePAdr, + + // The read that was requested + output logic [31:0] DCacheReadW, + + // Outputs to pipeline control stuff + output logic DCacheStallW, EndFetchState, + + // Signals to/from ahblite interface + // A read containing the requested data + input logic [`XLEN-1:0] ReadDataW, + input logic MemAckW, + // The read we request from main memory + output logic [`XLEN-1:0] MemPAdrM, + output logic MemReadM, MemWriteM +); + + // Cache fault signals + logic FaultStall; + + // Handle happy path (data in cache) + + always_comb begin + DCacheReadW = DCacheMemReadData; + end + + + // Handle cache faults + + localparam integer WORDSPERLINE = LINESIZE/`XLEN; + localparam integer LOGWPL = $clog2(WORDSPERLINE); + localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); + + logic FetchState, BeginFetchState; + logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; + logic [`XLEN-1:0] LineAlignedPCPF; + + flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState); + flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum); + + genvar i; + generate + for (i=0; i < WORDSPERLINE; i++) begin + flopenr #(`XLEN) flop(clk, reset, FetchState & (i == FetchWordNum), ReadDataW, DCacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]); + end + endgenerate + + // Enter the fetch state when we hit a cache fault + always_comb begin + BeginFetchState = ~DCacheMemReadValid & ~FetchState & (FetchWordNum == 0); + end + // Exit the fetch state once the cache line has been loaded + flopr #(1) EndFetchStateFlop(clk, reset, DCacheMemWriteEnable, EndFetchState); + + // Machinery to request the correct addresses from main memory + always_comb begin + MemReadM = FetchState & ~EndFetchState & ~DCacheMemWriteEnable; + LineAlignedPCPF = {DCacheMemUpperPAdr, DCacheMemLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; + MemPAdrM = LineAlignedPCPF + FetchWordNum*(`XLEN/8); + NextFetchWordNum = FetchState ? FetchWordNum+MemAckW : {LOGWPL+1{1'b0}}; + end + + // Write to cache memory when we have the line here + always_comb begin + DCacheMemWritePAdr = LineAlignedPCPF; + DCacheMemWriteEnable = FetchWordNum == {1'b1, {LOGWPL{1'b0}}} & FetchState & ~EndFetchState; + end + + // Stall the pipeline while loading a new line from memory + always_comb begin + DCacheStallW = FetchState | ~DCacheMemReadValid; + end +endmodule From 251ece20fec50df6c7cee2bfc61e44ae9bb4626a Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 20 Apr 2021 19:55:49 -0500 Subject: [PATCH 45/55] Broken icache. Design is done. Time to debug. --- wally-pipelined/regression/wave.do | 148 ++++--- wally-pipelined/src/ifu/icache.sv | 396 ++++++++++++++++-- wally-pipelined/src/ifu/ifu.sv | 20 +- .../testbench/testbench-imperas.sv | 2 +- 4 files changed, 468 insertions(+), 98 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 470cc599..36401fd9 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -26,7 +26,6 @@ add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSR add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/InstrStall add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/MulDivStallD add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF @@ -39,11 +38,6 @@ add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbe add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallE add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallM add wave -noupdate -expand -group HDU -expand -group Stall -color Orange /testbench/dut/hart/StallW -add wave -noupdate /testbench/dut/hart/hzu/StallFCause_Q -add wave -noupdate /testbench/dut/hart/hzu/StallDCause_Q -add wave -noupdate /testbench/dut/hart/hzu/StallECause_Q -add wave -noupdate /testbench/dut/hart/hzu/StallMCause_Q -add wave -noupdate /testbench/dut/hart/hzu/StallWCause_Q add wave -noupdate -group Bpred -expand -group direction -divider Update add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdatePC add wave -noupdate -group Bpred -expand -group direction /testbench/dut/hart/ifu/bpred/Predictor/DirPredictor/UpdateEN @@ -80,36 +74,36 @@ add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rf -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 -add wave -noupdate -expand -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW -add wave -noupdate -expand -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/result -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/flags -add wave -noupdate -expand -group alu -divider internals -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/overflow -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/carry -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/zero -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt -add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rf +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a1 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a2 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/a3 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd1 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/rd2 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/we3 +add wave -noupdate -group RegFile /testbench/dut/hart/ieu/dp/regf/wd3 +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ALUResultW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ReadDataW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW +add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/a +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/b +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/result +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/flags +add wave -noupdate -group alu -divider internals +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/overflow +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/carry +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/zero +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt +add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM -add wave -noupdate -expand -group dcache /testbench/dut/hart/WriteDataM -add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM +add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM +add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM +add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E @@ -148,32 +142,64 @@ add wave -noupdate -group {function radix debug} /testbench/functionRadix/functi add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionAddr add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/ProgramAddrIndex add wave -noupdate -group {function radix debug} /testbench/functionRadix/function_radix/FunctionName -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/InstrD -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/SrcAE -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/SrcBE -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/Funct3E -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/MulDivE -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/W64E -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/StallM -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/StallW -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/FlushM -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/FlushW -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/MulDivResultW -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/genblk1/div/start -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/DivDoneE -add wave -noupdate -expand -group muldiv /testbench/dut/hart/mdu/DivBusyE -add wave -noupdate /testbench/dut/hart/mdu/genblk1/gclk -add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/fsm1/CURRENT_STATE -add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/N -add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/D -add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/Q -add wave -noupdate -expand -group divider /testbench/dut/hart/mdu/genblk1/div/rem0 -add wave -noupdate /testbench/dut/hart/MulDivResultW -add wave -noupdate /testbench/dut/hart/mdu/genblk1/PrelimResultE -add wave -noupdate /testbench/dut/hart/mdu/Funct3E -add wave -noupdate /testbench/dut/hart/mdu/genblk1/QuotE +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/InstrD +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/SrcAE +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/SrcBE +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/Funct3E +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/MulDivE +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/W64E +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/StallM +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/StallW +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/FlushM +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/FlushW +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/MulDivResultW +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/genblk1/div/start +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/DivDoneE +add wave -noupdate -group muldiv /testbench/dut/hart/mdu/DivBusyE +add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/fsm1/CURRENT_STATE +add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/N +add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/D +add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/Q +add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/rem0 +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/AHBByteLength +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/AHBOFFETWIDTH +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/BlockByteLength +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/OFFSETWIDTH +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/WORDSPERLINE +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LOGWPL +add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LINESIZE +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/CurrState +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPF +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF +add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/FinalInstrRawF +add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/AlignedInstrRawD +add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/InstrRawD +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/hit +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/spill +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/spillSave +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/UnalignedSelect +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCMux +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPFinalF +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataValidBit +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataValid +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadTag +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataTag +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteEnable +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteLine +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WritePAdr +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteSet +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteTag +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {128433 ns} 0} +WaveRestoreCursors {{Cursor 2} {237 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -189,4 +215,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {128007 ns} {128663 ns} +WaveRestoreZoom {96 ns} {400 ns} diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index f6440fcf..573e885a 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -129,57 +129,141 @@ module icachecontroller #(parameter LINESIZE = 256) ( output logic InstrReadF ); - // Happy path signals - logic [31:0] AlignedInstrRawF, AlignedInstrRawD; - logic FlushDLastCycleN; - logic PCPMisalignedF; - const logic [31:0] NOP = 32'h13; - logic [`XLEN-1:0] PCPF; - // Misaligned signals - logic [`XLEN:0] MisalignedInstrRawF; - logic MisalignedStall; - // Cache fault signals - logic FaultStall; + // FSM states + localparam STATE_READY = 0; + localparam STATE_HIT_SPILL = 1; // spill, block 0 hit + localparam STATE_HIT_SPILL_MISS_FETCH_WDV = 2; // block 1 miss, issue read to AHB and wait data. + localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 3; // write data into SRAM/LUT + localparam STATE_HIT_SPILL_MERGE = 4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL. + localparam STATE_MISS_FETCH_WDV = 5; // aligned miss, issue read to AHB and wait for data. + localparam STATE_MISS_FETCH_DONE = 6; // write data into SRAM/LUT + localparam STATE_MISS_READ = 7; // read block 1 from SRAM/LUT + + localparam STATE_MISS_SPILL_FETCH_WDV = 8; // spill, miss on block 0, issue read to AHB and wait + localparam STATE_MISS_SPILL_FETCH_DONE = 9; // write data into SRAM/LUT + localparam STATE_MISS_SPILL_READ1 = 10; // read block 0 from SRAM/LUT + localparam STATE_MISS_SPILL_2 = 11; // return to ready if hit or do second block update. + localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 12; // miss on block 1, issue read to AHB and wait + localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 13; // write data to SRAM/LUT + localparam STATE_MISS_SPILL_MERGE = 14; // read block 0 of CPU access, + + localparam STATE_INVALIDATE = 15; // *** not sure if invalidate or evict? invalidate by cache block or address? + + localparam AHBByteLength = `XLEN / 8; + localparam AHBOFFETWIDTH = $clog2(AHBByteLength); + + + localparam BlockByteLength = LINESIZE / 8; + localparam OFFSETWIDTH = $clog2(BlockByteLength); + + localparam WORDSPERLINE = LINESIZE/`XLEN; + localparam LOGWPL = $clog2(WORDSPERLINE); + + logic [3:0] CurrState, NextState; + logic hit, spill; + logic SavePC; + logic [1:0] PCMux; + logic CntReset; + logic PreCntEn, CntEn; + logic spillSave; + logic UnalignedSelect; + logic FetchCountFlag; + localparam FetchCountThreshold = WORDSPERLINE - 1; + + logic [LOGWPL:0] FetchCount, NextFetchCount; + + logic [`XLEN-1:0] PCPreFinalF, PCPFinalF, PCSpillF; + logic [`XLEN-1:OFFSETWIDTH] PCPTrunkF; + + + logic [31:0] FinalInstrRawF; + + logic [15:0] SpillDataBlock0; + + + + // Happy path signals + logic [31:0] AlignedInstrRawD; + + //logic [31:0] AlignedInstrRawF, AlignedInstrRawD; + //logic FlushDLastCycleN; + //logic PCPMisalignedF; + const logic [31:0] NOP = 32'h13; + logic [`XLEN-1:0] PCPF; + + logic reset_q; + + // Misaligned signals + //logic [`XLEN:0] MisalignedInstrRawF; + //logic MisalignedStall; + // Cache fault signals + //logic FaultStall; + + + flopenr #(`XLEN) PCPFFlop(clk, reset, SavePC, {UpperPCNextPF, LowerPCNextF}, PCPF); + // on spill we want to get the first 2 bytes of the next cache block. + // the spill only occurs if the PCPF mod BlockByteLength == -2. Therefore we can + // simply add 2 to land on the next cache block. + assign PCSpillF = PCPF + 2'b10; + + // now we have to select between these three PCs + assign PCPreFinalF = PCMux[0] ? PCPF : {UpperPCNextPF, LowerPCNextF}; + assign PCPFinalF = PCMux[1] ? PCSpillF : PCPreFinalF; + + + + // truncate the offset from PCPF for memory address generation + assign PCPTrunkF = PCPFinalF[`XLEN-1:OFFSETWIDTH]; + // Detect if the instruction is compressed - assign CompressedF = AlignedInstrRawF[1:0] != 2'b11; + assign CompressedF = FinalInstrRawF[1:0] != 2'b11; // Handle happy path (data in cache, reads aligned) +/* -----\/----- EXCLUDED -----\/----- generate if (`XLEN == 32) begin assign AlignedInstrRawF = PCPF[1] ? MisalignedInstrRawF : ICacheMemReadData; - assign PCPMisalignedF = PCPF[1] && ~CompressedF; + //assign PCPMisalignedF = PCPF[1] && ~CompressedF; end else begin assign AlignedInstrRawF = PCPF[2] ? (PCPF[1] ? MisalignedInstrRawF : ICacheMemReadData[63:32]) : (PCPF[1] ? ICacheMemReadData[47:16] : ICacheMemReadData[31:0]); - assign PCPMisalignedF = PCPF[2] && PCPF[1] && ~CompressedF; + //assign PCPMisalignedF = PCPF[2] && PCPF[1] && ~CompressedF; end endgenerate + -----/\----- EXCLUDED -----/\----- */ - flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD); - flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN); - flopenr #(`XLEN) PCPFFlop(clk, reset, ~StallF, {UpperPCNextPF, LowerPCNextF}, PCPF); - mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD); + //flopenr #(32) AlignedInstrRawDFlop(clk, reset, ~StallD, AlignedInstrRawF, AlignedInstrRawD); + //flopr #(1) FlushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCycleN | ~StallF), FlushDLastCycleN); + + //mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCycleN, InstrRawD); // Stall for faults or misaligned reads +/* -----\/----- EXCLUDED -----\/----- always_comb begin assign ICacheStallF = FaultStall | MisalignedStall; end + -----/\----- EXCLUDED -----/\----- */ // Handle misaligned, noncompressed reads +/* -----\/----- EXCLUDED -----\/----- logic MisalignedState, NextMisalignedState; logic [15:0] MisalignedHalfInstrF; logic [15:0] UpperHalfWord; + -----/\----- EXCLUDED -----/\----- */ +/* -----\/----- EXCLUDED -----\/----- flopenr #(16) MisalignedHalfInstrFlop(clk, reset, ~FaultStall & (PCPMisalignedF & MisalignedState), AlignedInstrRawF[15:0], MisalignedHalfInstrF); flopenr #(1) MisalignedStateFlop(clk, reset, ~FaultStall, NextMisalignedState, MisalignedState); + -----/\----- EXCLUDED -----/\----- */ // When doing a misaligned read, swizzle the bits correctly +/* -----\/----- EXCLUDED -----\/----- generate if (`XLEN == 32) begin assign UpperHalfWord = ICacheMemReadData[31:16]; @@ -194,14 +278,18 @@ module icachecontroller #(parameter LINESIZE = 256) ( assign MisalignedInstrRawF = {ICacheMemReadData[15:0], MisalignedHalfInstrF}; end end + -----/\----- EXCLUDED -----/\----- */ // Manage internal state and stall when necessary +/* -----\/----- EXCLUDED -----\/----- always_comb begin assign MisalignedStall = PCPMisalignedF & MisalignedState; assign NextMisalignedState = ~PCPMisalignedF | ~MisalignedState; end + -----/\----- EXCLUDED -----/\----- */ // Pick the correct address to read +/* -----\/----- EXCLUDED -----\/----- generate if (`XLEN == 32) begin assign ICacheMemReadLowerAdr = {LowerPCNextF[11:2] + (PCPMisalignedF & ~MisalignedState), 2'b00}; @@ -209,16 +297,15 @@ module icachecontroller #(parameter LINESIZE = 256) ( assign ICacheMemReadLowerAdr = {LowerPCNextF[11:3] + (PCPMisalignedF & ~MisalignedState), 3'b00}; end endgenerate + -----/\----- EXCLUDED -----/\----- */ // TODO Handle reading instructions that cross page boundaries - assign ICacheMemReadUpperPAdr = UpperPCNextPF; + //assign ICacheMemReadUpperPAdr = UpperPCNextPF; // Handle cache faults - localparam integer WORDSPERLINE = LINESIZE/`XLEN; - localparam integer LOGWPL = $clog2(WORDSPERLINE); - localparam integer OFFSETWIDTH = $clog2(LINESIZE/8); +/* -----\/----- EXCLUDED -----\/----- logic FetchState, BeginFetchState; logic [LOGWPL:0] FetchWordNum, NextFetchWordNum; logic [`XLEN-1:0] LineAlignedPCPF; @@ -226,12 +313,6 @@ module icachecontroller #(parameter LINESIZE = 256) ( flopr #(1) FetchStateFlop(clk, reset, BeginFetchState | (FetchState & ~EndFetchState), FetchState); flopr #(LOGWPL+1) FetchWordNumFlop(clk, reset, NextFetchWordNum, FetchWordNum); - genvar i; - generate - for (i=0; i < WORDSPERLINE; i++) begin - flopenr #(`XLEN) flop(clk, reset, FetchState & (i == FetchWordNum), InstrInF, ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN]); - end - endgenerate // Enter the fetch state when we hit a cache fault always_comb begin @@ -242,10 +323,10 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Machinery to request the correct addresses from main memory always_comb begin - InstrReadF = FetchState & ~EndFetchState & ~ICacheMemWriteEnable; - LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; - InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); - NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; + InstrReadF = FetchState & ~EndFetchState & ~ICacheMemWriteEnable; // next stage logic + LineAlignedPCPF = {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr[11:OFFSETWIDTH], {OFFSETWIDTH{1'b0}}}; // the fetch address for abh? + InstrPAdrF = LineAlignedPCPF + FetchWordNum*(`XLEN/8); // ? + NextFetchWordNum = FetchState ? FetchWordNum+InstrAckF : {LOGWPL+1{1'b0}}; // convert to enable end // Write to cache memory when we have the line here @@ -258,4 +339,255 @@ module icachecontroller #(parameter LINESIZE = 256) ( always_comb begin FaultStall = FetchState | ~ICacheMemReadValid; end + -----/\----- EXCLUDED -----/\----- */ + + // the FSM is always runing, do not stall. + flopr #(4) stateReg(.clk(clk), + .reset(reset), + .d(NextState), + .q(CurrState)); + + assign spill = PCPF[5:1] == 5'b1_1111 ? 1'b1 : 1'b0; + assign hit = ICacheMemReadValid; // note ICacheMemReadValid is hit. + assign FetchCountFlag = FetchCount == FetchCountThreshold; + + // Next state logic + always_comb begin + UnalignedSelect = 1'b0; + CntReset = 1'b0; + PreCntEn = 1'b0; + InstrReadF = 1'b0; + ICacheMemWriteEnable = 1'b0; + spillSave = 1'b0; + PCMux = 2'b00; + + case (CurrState) + + STATE_READY: begin + PCMux = 2'b00; + if (hit & ~spill) begin + NextState = STATE_READY; + end else if (hit & spill) begin + spillSave = 1'b1; + NextState = STATE_HIT_SPILL; + end else if (~hit & ~spill) begin + CntReset = 1'b1; + NextState = STATE_MISS_FETCH_WDV; + end else if (~hit & spill) begin + CntReset = 1'b1; + NextState = STATE_MISS_SPILL_FETCH_WDV; + end else begin + NextState = STATE_READY; + end + end + + // branch 1, hit spill and 2, miss spill hit + STATE_HIT_SPILL: begin + PCMux = 2'b10; + UnalignedSelect = 1'b1; + if (hit) begin + NextState = STATE_READY; + end else + CntReset = 1'b1; + NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; + end + STATE_HIT_SPILL_MISS_FETCH_WDV: begin + PCMux = 2'b10; + InstrReadF = 1'b1; + PreCntEn = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_HIT_SPILL_MISS_FETCH_DONE; + end else begin + NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; + end + end + STATE_HIT_SPILL_MISS_FETCH_DONE: begin + PCMux = 2'b10; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_HIT_SPILL_MERGE; + end + STATE_HIT_SPILL_MERGE: begin + PCMux = 2'b10; + UnalignedSelect = 1'b1; + NextState = STATE_READY; + end + + // branch 3 miss no spill + STATE_MISS_FETCH_WDV: begin + PCMux = 2'b01; + InstrReadF = 1'b1; + PreCntEn = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_FETCH_DONE; + end else begin + NextState = STATE_MISS_FETCH_WDV; + end + end + STATE_MISS_FETCH_DONE: begin + PCMux = 2'b01; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_READ; + end + STATE_MISS_READ: begin + PCMux = 2'b01; + NextState = STATE_READY; + end + + // branch 4 miss spill hit, and 5 miss spill miss + STATE_MISS_SPILL_FETCH_WDV: begin + PCMux = 2'b01; + PreCntEn = 1'b1; + InstrReadF = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_SPILL_FETCH_DONE; + end else begin + NextState = STATE_MISS_SPILL_FETCH_WDV; + end + end + STATE_MISS_SPILL_FETCH_DONE: begin + PCMux = 2'b01; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_SPILL_READ1; + end + STATE_MISS_SPILL_READ1: begin // always be a hit as we just wrote that cache block. + PCMux = 2'b10; // there is a 1 cycle delay after setting the address before the date arrives. + spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm. + NextState = STATE_MISS_SPILL_2; + end + STATE_MISS_SPILL_2: begin + PCMux = 2'b10; + UnalignedSelect = 1'b1; + if (~hit) begin + CntReset = 1'b1; + NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; + end else begin + NextState = STATE_READY; + end + end + STATE_MISS_SPILL_MISS_FETCH_WDV: begin + PCMux = 2'b10; + PreCntEn = 1'b1; + InstrReadF = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_SPILL_MISS_FETCH_DONE; + end else begin + NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; + end + end + STATE_MISS_SPILL_MISS_FETCH_DONE: begin + PCMux = 2'b10; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_SPILL_MERGE; + end + STATE_MISS_SPILL_MERGE: begin + PCMux = 2'b10; + UnalignedSelect = 1'b1; + NextState = STATE_READY; + end + default: begin + PCMux = 2'b01; + NextState = STATE_READY; + end + // *** add in error handling and invalidate/evict + endcase + end + + // fsm outputs + // stall CPU any time we are not in the ready state. any other state means the + // cache is either requesting data from the memory interface or handling a + // spill over two cycles. + assign ICacheStallF = (CurrState != STATE_READY) | reset_q ? 1'b1 : 1'b0; + // save the PC anytime we are in the ready state. The saved value will be used as the PC may not be stable. + assign SavePC = CurrState == STATE_READY ? 1'b1 : 1'b0; + assign CntEn = PreCntEn & InstrAckF; + + // to compute the fetch address we need to add the bit shifted + // counter output to the address. + + flopenr #(LOGWPL+1) + FetchCountReg(.clk(clk), + .reset(reset | CntReset), + .en(CntEn), + .d(NextFetchCount), + .q(FetchCount)); + + assign NextFetchCount = FetchCount + 1'b1; + + // This part is confusing. + // we need to remove the offset bits (PCPTrunkF). Because the AHB interface is XLEN wide + // we need to address on that number of bits so the PC is extended to the right by AHBByteLength with zeros. + // fetch count is already aligned to AHBByteLength, but we need to extend back to the full address width with + // more zeros after the addition. This will be the number of offset bits less the AHBByteLength. + assign InstrPAdrF = {{PCPTrunkF, {{LOGWPL}{1'b0}}} + FetchCount, {{OFFSETWIDTH-LOGWPL}{1'b0}}}; + + + // store read data from memory interface before writing into SRAM. + genvar i; + generate + for (i = 0; i < AHBByteLength; i++) begin + flopenr #(`XLEN) flop(.clk(clk), + .reset(reset), + .en(InstrAckF & (i == FetchCount)), + .d(InstrInF), + .q(ICacheMemWriteData[(i+1)*`XLEN-1:i*`XLEN])); + end + endgenerate + + // what address is used to write the SRAM? + + + // spills require storing the first cache block so it can merged + // with the second + // can optimize size, for now just make it the size of the data + // leaving the cache memory. + flopenr #(16) SpillInstrReg(.clk(clk), + .en(spillSave), + .reset(reset), + .d(ICacheMemReadData[15:0]), + .q(SpillDataBlock0)); + + // use the not quite final PC to do the final selection. + generate + if( `XLEN == 32) begin + logic [1:1] PCPreFinalF_q; + flop #(1) PCFReg(.clk(clk), + .d(PCPreFinalF[1]), + .q(PCPreFinalF_q[1])); + assign FinalInstrRawF = PCPreFinalF[1] ? {SpillDataBlock0, ICacheMemReadData[31:16]} : ICacheMemReadData; + end else begin + logic [2:1] PCPreFinalF_q; + flop #(2) PCFReg(.clk(clk), + .d(PCPreFinalF[2:1]), + .q(PCPreFinalF_q[2:1])); + mux4 #(32) AlignmentMux(.d0(ICacheMemReadData[31:0]), + .d1(ICacheMemReadData[47:16]), + .d2(ICacheMemReadData[63:32]), + .d3({SpillDataBlock0, ICacheMemReadData[63:48]}), + .s(PCPreFinalF[2:1]), + .y(FinalInstrRawF)); + end + endgenerate + + // There is a frustrating issue on the first access. + // The cache will not contain any valid data but will contain x's on + // reset. This makes FinalInstrRawF invalid. On the first cycle out of + // reset this register will pickup this x and it will propagate throughout + // the cpu causing simulation failure, most likely a trap for invalid instruction. + // Reset must be held 1 cycle longer to prevent this issue. additionally the + // reset should be to a NOP rather than 0. + + // register reset + flop #(1) resetReg (.clk(clk), + .d(reset), + .q(reset_q)); + + flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FinalInstrRawF, NOP, AlignedInstrRawD); + mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, FlushD, InstrRawD); + + assign {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr} = PCPFinalF; + + assign ICacheMemWritePAdr = PCPFinalF; + + + endmodule diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 5a2d1b42..58b144f5 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -77,6 +77,8 @@ module ifu ( logic [31:0] nop = 32'h00000013; // instruction for NOP // *** send this to the trap unit logic ITLBPageFaultF; + logic reset_q; // *** look at this later. + tlb #(3) itlb(.TLBAccess(1'b1), .VirtualAddress(PCF), .PageTableEntryWrite(PageTableEntryF), .PageTypeWrite(PageTypeF), @@ -87,7 +89,7 @@ module ifu ( // branch predictor signals logic SelBPPredF; - logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F; + logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F, PCNext2F; logic [3:0] InstrClassD, InstrClassE; @@ -98,10 +100,10 @@ module ifu ( // jarred 2021-03-14 Add instrution cache block to remove rd2 assign PCNextPF = PCNextF; // Temporary workaround until iTLB is live - icache ic( + icache icache( .*, - .UpperPCPF(PCPF[`XLEN-1:12]), - .LowerPCF(PCF[11:0]) + .UpperPCNextPF(PCNextPF[`XLEN-1:12]), + .LowerPCNextF(PCNextPF[11:0]) ); assign PrivilegedChangePCM = RetM | TrapM; @@ -120,7 +122,17 @@ module ifu ( mux2 #(`XLEN) pcmux2(.d0(PCNext1F), .d1(PrivilegedNextPCM), .s(PrivilegedChangePCM), + .y(PCNext2F)); + + mux2 #(`XLEN) pcmux3(.d0(PCNext2F), + .d1(`RESET_VECTOR), + .s(reset_q), .y(UnalignedPCNextF)); + + flop #(1) resetReg (.clk(clk), + .d(reset), + .q(reset_q)); + assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment flopenl #(`XLEN) pcreg(clk, reset, ~StallF & ~ICacheStallF, PCNextF, `RESET_VECTOR, PCF); diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 2d11bcc8..bd51596d 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -447,7 +447,7 @@ module testbench(); // Track names of instructions instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE, - dut.hart.ifu.ic.controller.AlignedInstrRawF, + dut.hart.ifu.icache.controller.FinalInstrRawF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE, dut.hart.ifu.InstrM, dut.hart.ifu.InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); From 99424fb9831b324576b080b289041a6fb9d877ad Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 20 Apr 2021 21:19:53 -0500 Subject: [PATCH 46/55] Progress on icache. Fixed some issues aligning the PC with instruction. Still broken. --- wally-pipelined/regression/wave.do | 19 ++++-- wally-pipelined/src/cache/dmapped.sv | 99 ++++++++++++++++++++++++++++ wally-pipelined/src/ifu/icache.sv | 85 ++++++++++++++---------- 3 files changed, 163 insertions(+), 40 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 36401fd9..eeb8a0ba 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -122,6 +122,7 @@ add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/ALURe add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcAE add wave -noupdate -group {alu execution stage} /testbench/dut/hart/ieu/dp/SrcBE add wave -noupdate /testbench/dut/hart/ieu/dp/ALUResultM +add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCNextF add wave -noupdate -expand -group PCS /testbench/dut/hart/PCF add wave -noupdate -expand -group PCS /testbench/dut/hart/ifu/PCD add wave -noupdate -expand -group PCS /testbench/dut/hart/PCE @@ -169,11 +170,12 @@ add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/cont add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LOGWPL add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LINESIZE add wave -noupdate /testbench/dut/hart/ifu/icache/controller/CurrState -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF +add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrInF add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr @@ -198,9 +200,18 @@ add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WritePAdr add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteSet add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteTag add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadAddr +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadData +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadPAdr +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheMemReadData +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/genblk2/PCPreFinalF_q +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheStallF +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/SavePC TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {237 ns} 0} -quietly wave cursor active 1 +WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {284 ns} 0} +quietly wave cursor active 2 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 configure wave -justifyvalue left @@ -215,4 +226,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {96 ns} {400 ns} +WaveRestoreZoom {139 ns} {443 ns} diff --git a/wally-pipelined/src/cache/dmapped.sv b/wally-pipelined/src/cache/dmapped.sv index fb6ce4c5..4f1cc2d3 100644 --- a/wally-pipelined/src/cache/dmapped.sv +++ b/wally-pipelined/src/cache/dmapped.sv @@ -125,6 +125,105 @@ module rodirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, par assign DataValid = DataValidBit && (DataTag == ReadTag); endmodule +module rodirectmappedmemre #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) ( + // Pipeline stuff + input logic clk, + input logic reset, + input logic re, + // If flush is high, invalidate the entire cache + input logic flush, + // Select which address to read (broken for efficiency's sake) + input logic [`XLEN-1:12] ReadUpperPAdr, + input logic [11:0] ReadLowerAdr, + // Write new data to the cache + input logic WriteEnable, + input logic [LINESIZE-1:0] WriteLine, + input logic [`XLEN-1:0] WritePAdr, + // Output the word, as well as if it is valid + output logic [WORDSIZE-1:0] DataWord, + output logic DataValid +); + + // Various compile-time constants + localparam integer WORDWIDTH = $clog2(WORDSIZE/8); + localparam integer OFFSETWIDTH = $clog2(LINESIZE/WORDSIZE); + localparam integer SETWIDTH = $clog2(NUMLINES); + localparam integer TAGWIDTH = `XLEN - OFFSETWIDTH - SETWIDTH - WORDWIDTH; + + localparam integer OFFSETBEGIN = WORDWIDTH; + localparam integer OFFSETEND = OFFSETBEGIN+OFFSETWIDTH-1; + localparam integer SETBEGIN = OFFSETEND+1; + localparam integer SETEND = SETBEGIN + SETWIDTH - 1; + localparam integer TAGBEGIN = SETEND + 1; + localparam integer TAGEND = TAGBEGIN + TAGWIDTH - 1; + + // Machinery to read from and write to the correct addresses in memory + logic [`XLEN-1:0] ReadPAdr; + logic [`XLEN-1:0] OldReadPAdr; + logic [OFFSETWIDTH-1:0] ReadOffset, WriteOffset; + logic [SETWIDTH-1:0] ReadSet, WriteSet; + logic [TAGWIDTH-1:0] ReadTag, WriteTag; + logic [LINESIZE-1:0] ReadLine; + logic [LINESIZE/WORDSIZE-1:0][WORDSIZE-1:0] ReadLineTransformed; + + // Machinery to check if a given read is valid and is the desired value + logic [TAGWIDTH-1:0] DataTag; + logic [NUMLINES-1:0] ValidOut; + logic DataValidBit; + + flopenr #(`XLEN) ReadPAdrFlop(clk, reset, re, ReadPAdr, OldReadPAdr); + + // Assign the read and write addresses in cache memory + always_comb begin + ReadOffset = OldReadPAdr[OFFSETEND:OFFSETBEGIN]; + ReadPAdr = {ReadUpperPAdr, ReadLowerAdr}; + ReadSet = ReadPAdr[SETEND:SETBEGIN]; + ReadTag = OldReadPAdr[TAGEND:TAGBEGIN]; + + WriteOffset = WritePAdr[OFFSETEND:OFFSETBEGIN]; + WriteSet = WritePAdr[SETEND:SETBEGIN]; + WriteTag = WritePAdr[TAGEND:TAGBEGIN]; + end + + // Depth is number of bits in one "word" of the memory, width is number of such words + Sram1Read1Write #(.DEPTH(LINESIZE), .WIDTH(NUMLINES)) cachemem ( + .*, + .ReadAddr(ReadSet), + .ReadData(ReadLine), + .WriteAddr(WriteSet), + .WriteData(WriteLine) + ); + Sram1Read1Write #(.DEPTH(TAGWIDTH), .WIDTH(NUMLINES)) cachetags ( + .*, + .ReadAddr(ReadSet), + .ReadData(DataTag), + .WriteAddr(WriteSet), + .WriteData(WriteTag) + ); + + // Pick the right bits coming out the read line + assign DataWord = ReadLineTransformed[ReadOffset]; + genvar i; + generate + for (i=0; i < LINESIZE/WORDSIZE; i++) begin + assign ReadLineTransformed[i] = ReadLine[(i+1)*WORDSIZE-1:i*WORDSIZE]; + end + endgenerate + + // Correctly handle the valid bits + always_ff @(posedge clk, posedge reset) begin + if (reset || flush) begin + ValidOut <= {NUMLINES{1'b0}}; + end else begin + if (WriteEnable) begin + ValidOut[WriteSet] <= 1; + end + end + DataValidBit <= ValidOut[ReadSet]; + end + assign DataValid = DataValidBit && (DataTag == ReadTag); +endmodule + // Write-through direct-mapped memory module wtdirectmappedmem #(parameter NUMLINES=512, parameter LINESIZE = 256, parameter WORDSIZE = `XLEN) ( // Pipeline stuff diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 573e885a..8c16b3a9 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -65,11 +65,14 @@ module icache( // Output signals from cache memory logic [`XLEN-1:0] ICacheMemReadData; logic ICacheMemReadValid; + logic ICacheReadEn; + - rodirectmappedmem #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES), .WORDSIZE(`XLEN)) cachemem( + rodirectmappedmemre #(.LINESIZE(ICACHELINESIZE), .NUMLINES(ICACHENUMLINES), .WORDSIZE(`XLEN)) + cachemem( .*, // Stall it if the pipeline is stalled, unless we're stalling it and we're ending our stall - .stall(StallF && (~ICacheStallF || ~EndFetchState)), + .re(ICacheReadEn), .flush(FlushMem), .ReadUpperPAdr(ICacheMemReadUpperPAdr), .ReadLowerAdr(ICacheMemReadLowerAdr), @@ -88,45 +91,46 @@ endmodule module icachecontroller #(parameter LINESIZE = 256) ( // Inputs from pipeline - input logic clk, reset, - input logic StallF, StallD, - input logic FlushD, + input logic clk, reset, + input logic StallF, StallD, + input logic FlushD, // Input the address to read // The upper bits of the physical pc - input logic [`XLEN-1:12] UpperPCNextPF, + input logic [`XLEN-1:12] UpperPCNextPF, // The lower bits of the virtual pc - input logic [11:0] LowerPCNextF, + input logic [11:0] LowerPCNextF, // Signals to/from cache memory // The read coming out of it - input logic [`XLEN-1:0] ICacheMemReadData, - input logic ICacheMemReadValid, + input logic [`XLEN-1:0] ICacheMemReadData, + input logic ICacheMemReadValid, // The address at which we want to search the cache memory - output logic [`XLEN-1:12] ICacheMemReadUpperPAdr, - output logic [11:0] ICacheMemReadLowerAdr, + output logic [`XLEN-1:12] ICacheMemReadUpperPAdr, + output logic [11:0] ICacheMemReadLowerAdr, + output logic ICacheReadEn, // Load data into the cache - output logic ICacheMemWriteEnable, + output logic ICacheMemWriteEnable, output logic [LINESIZE-1:0] ICacheMemWriteData, - output logic [`XLEN-1:0] ICacheMemWritePAdr, + output logic [`XLEN-1:0] ICacheMemWritePAdr, // Outputs to rest of ifu // High if the instruction in the fetch stage is compressed - output logic CompressedF, + output logic CompressedF, // The instruction that was requested // If this instruction is compressed, upper 16 bits may be the next 16 bits or may be zeros - output logic [31:0] InstrRawD, + output logic [31:0] InstrRawD, // Outputs to pipeline control stuff - output logic ICacheStallF, EndFetchState, + output logic ICacheStallF, EndFetchState, // Signals to/from ahblite interface // A read containing the requested data - input logic [`XLEN-1:0] InstrInF, - input logic InstrAckF, + input logic [`XLEN-1:0] InstrInF, + input logic InstrAckF, // The read we request from main memory - output logic [`XLEN-1:0] InstrPAdrF, - output logic InstrReadF + output logic [`XLEN-1:0] InstrPAdrF, + output logic InstrReadF ); // FSM states @@ -173,7 +177,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( logic [LOGWPL:0] FetchCount, NextFetchCount; - logic [`XLEN-1:0] PCPreFinalF, PCPFinalF, PCSpillF; + logic [`XLEN-1:0] PCPreFinalF, PCPFinalF, PCSpillF, PCNextPF; logic [`XLEN-1:OFFSETWIDTH] PCPTrunkF; @@ -200,15 +204,16 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Cache fault signals //logic FaultStall; - - flopenr #(`XLEN) PCPFFlop(clk, reset, SavePC, {UpperPCNextPF, LowerPCNextF}, PCPF); + assign PCNextPF = {UpperPCNextPF, LowerPCNextF}; + + flopenl #(`XLEN) PCPFFlop(clk, reset, SavePC, PCPFinalF, `RESET_VECTOR, PCPF); // on spill we want to get the first 2 bytes of the next cache block. // the spill only occurs if the PCPF mod BlockByteLength == -2. Therefore we can // simply add 2 to land on the next cache block. assign PCSpillF = PCPF + 2'b10; // now we have to select between these three PCs - assign PCPreFinalF = PCMux[0] ? PCPF : {UpperPCNextPF, LowerPCNextF}; + assign PCPreFinalF = PCMux[0] ? PCPF : PCNextPF; assign PCPFinalF = PCMux[1] ? PCSpillF : PCPreFinalF; @@ -353,18 +358,20 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Next state logic always_comb begin - UnalignedSelect = 1'b0; - CntReset = 1'b0; - PreCntEn = 1'b0; - InstrReadF = 1'b0; - ICacheMemWriteEnable = 1'b0; - spillSave = 1'b0; - PCMux = 2'b00; + UnalignedSelect = 1'b0; + CntReset = 1'b0; + PreCntEn = 1'b0; + InstrReadF = 1'b0; + ICacheMemWriteEnable = 1'b0; + spillSave = 1'b0; + PCMux = 2'b00; + ICacheReadEn = 1'b0; case (CurrState) STATE_READY: begin PCMux = 2'b00; + ICacheReadEn = 1'b1; if (hit & ~spill) begin NextState = STATE_READY; end else if (hit & spill) begin @@ -384,7 +391,8 @@ module icachecontroller #(parameter LINESIZE = 256) ( // branch 1, hit spill and 2, miss spill hit STATE_HIT_SPILL: begin PCMux = 2'b10; - UnalignedSelect = 1'b1; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; if (hit) begin NextState = STATE_READY; end else @@ -409,6 +417,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( STATE_HIT_SPILL_MERGE: begin PCMux = 2'b10; UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; NextState = STATE_READY; end @@ -430,6 +439,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( end STATE_MISS_READ: begin PCMux = 2'b01; + ICacheReadEn = 1'b1; NextState = STATE_READY; end @@ -452,6 +462,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( STATE_MISS_SPILL_READ1: begin // always be a hit as we just wrote that cache block. PCMux = 2'b10; // there is a 1 cycle delay after setting the address before the date arrives. spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm. + ICacheReadEn = 1'b1; NextState = STATE_MISS_SPILL_2; end STATE_MISS_SPILL_2: begin @@ -482,6 +493,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( STATE_MISS_SPILL_MERGE: begin PCMux = 2'b10; UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; NextState = STATE_READY; end default: begin @@ -496,9 +508,9 @@ module icachecontroller #(parameter LINESIZE = 256) ( // stall CPU any time we are not in the ready state. any other state means the // cache is either requesting data from the memory interface or handling a // spill over two cycles. - assign ICacheStallF = (CurrState != STATE_READY) | reset_q ? 1'b1 : 1'b0; + assign ICacheStallF = ((CurrState != STATE_READY) & hit) | reset_q ? 1'b1 : 1'b0; // save the PC anytime we are in the ready state. The saved value will be used as the PC may not be stable. - assign SavePC = CurrState == STATE_READY ? 1'b1 : 1'b0; + assign SavePC = (CurrState == STATE_READY) & hit ? 1'b1 : 1'b0; assign CntEn = PreCntEn & InstrAckF; // to compute the fetch address we need to add the bit shifted @@ -518,6 +530,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( // we need to address on that number of bits so the PC is extended to the right by AHBByteLength with zeros. // fetch count is already aligned to AHBByteLength, but we need to extend back to the full address width with // more zeros after the addition. This will be the number of offset bits less the AHBByteLength. + // *** now a bug need to mux between PCPF and PCPF+2 assign InstrPAdrF = {{PCPTrunkF, {{LOGWPL}{1'b0}}} + FetchCount, {{OFFSETWIDTH-LOGWPL}{1'b0}}}; @@ -553,7 +566,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( flop #(1) PCFReg(.clk(clk), .d(PCPreFinalF[1]), .q(PCPreFinalF_q[1])); - assign FinalInstrRawF = PCPreFinalF[1] ? {SpillDataBlock0, ICacheMemReadData[31:16]} : ICacheMemReadData; + assign FinalInstrRawF = PCPreFinalF_q[1] ? {SpillDataBlock0, ICacheMemReadData[31:16]} : ICacheMemReadData; end else begin logic [2:1] PCPreFinalF_q; flop #(2) PCFReg(.clk(clk), @@ -563,7 +576,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( .d1(ICacheMemReadData[47:16]), .d2(ICacheMemReadData[63:32]), .d3({SpillDataBlock0, ICacheMemReadData[63:48]}), - .s(PCPreFinalF[2:1]), + .s(PCPreFinalF_q[2:1]), .y(FinalInstrRawF)); end endgenerate From f3093ac612fcbb08c8030a638e6b3ae3e781efc4 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Tue, 20 Apr 2021 22:06:12 -0500 Subject: [PATCH 47/55] Why was the linter messed up? There are a number of combo loops which need fixing outside the icache. They may be fixed in main. We get to instruction address 50 now! --- wally-pipelined/lint-wally | 24 +++++------------------- wally-pipelined/regression/wave.do | 4 ++-- wally-pipelined/src/ifu/icache.sv | 25 ++++++++++++++++++------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/wally-pipelined/lint-wally b/wally-pipelined/lint-wally index 791435ac..9d5a20ba 100755 --- a/wally-pipelined/lint-wally +++ b/wally-pipelined/lint-wally @@ -1,25 +1,11 @@ # check for warnings in Verilog code # The verilator lint tool is faster and better than Modelsim so it is best to run this first. -if [ -n "$1" ]; then - echo "rv64ic linting..." - if verilator --lint-only --top-module "$1" -Iconfig/rv64ic src/*/*.sv; then - echo "rv32ic linting..." - verilator --lint-only --top-module "$1" -Iconfig/rv32ic src/*/*.sv - else - echo "Skipping rv32ic because rv64ic had errors or warnings" - exit 1 - fi -else - echo "rv64ic linting..." - if verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv; then - echo "rv32ic linting..." - verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv - else - echo "Skipping rv32ic because rv64ic had errors or warnings" - exit 1 - fi -fi +echo "rv64ic linting..." +verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv +echo "rv32ic linting..." +verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv +#verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv src/*/div/*.sv # --lint-only just runs lint rather than trying to compile and simulate # -I points to the include directory where files such as `include wally-config.vh are found diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index eeb8a0ba..5174a350 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -210,7 +210,7 @@ add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheStallF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/SavePC TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {284 ns} 0} +WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {566 ns} 0} quietly wave cursor active 2 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -226,4 +226,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {139 ns} {443 ns} +WaveRestoreZoom {458 ns} {674 ns} diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 8c16b3a9..09dab7a8 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -361,7 +361,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( UnalignedSelect = 1'b0; CntReset = 1'b0; PreCntEn = 1'b0; - InstrReadF = 1'b0; + //InstrReadF = 1'b0; ICacheMemWriteEnable = 1'b0; spillSave = 1'b0; PCMux = 2'b00; @@ -401,7 +401,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( end STATE_HIT_SPILL_MISS_FETCH_WDV: begin PCMux = 2'b10; - InstrReadF = 1'b1; + //InstrReadF = 1'b1; PreCntEn = 1'b1; if (FetchCountFlag & InstrAckF) begin NextState = STATE_HIT_SPILL_MISS_FETCH_DONE; @@ -424,7 +424,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( // branch 3 miss no spill STATE_MISS_FETCH_WDV: begin PCMux = 2'b01; - InstrReadF = 1'b1; + //InstrReadF = 1'b1; PreCntEn = 1'b1; if (FetchCountFlag & InstrAckF) begin NextState = STATE_MISS_FETCH_DONE; @@ -447,7 +447,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( STATE_MISS_SPILL_FETCH_WDV: begin PCMux = 2'b01; PreCntEn = 1'b1; - InstrReadF = 1'b1; + //InstrReadF = 1'b1; if (FetchCountFlag & InstrAckF) begin NextState = STATE_MISS_SPILL_FETCH_DONE; end else begin @@ -478,7 +478,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( STATE_MISS_SPILL_MISS_FETCH_WDV: begin PCMux = 2'b10; PreCntEn = 1'b1; - InstrReadF = 1'b1; + //InstrReadF = 1'b1; if (FetchCountFlag & InstrAckF) begin NextState = STATE_MISS_SPILL_MISS_FETCH_DONE; end else begin @@ -508,11 +508,16 @@ module icachecontroller #(parameter LINESIZE = 256) ( // stall CPU any time we are not in the ready state. any other state means the // cache is either requesting data from the memory interface or handling a // spill over two cycles. - assign ICacheStallF = ((CurrState != STATE_READY) & hit) | reset_q ? 1'b1 : 1'b0; + assign ICacheStallF = ((CurrState != STATE_READY) | ~hit) | reset_q ? 1'b1 : 1'b0; // save the PC anytime we are in the ready state. The saved value will be used as the PC may not be stable. assign SavePC = (CurrState == STATE_READY) & hit ? 1'b1 : 1'b0; assign CntEn = PreCntEn & InstrAckF; + assign InstrReadF = (CurrState == STATE_HIT_SPILL_MISS_FETCH_WDV) || + (CurrState == STATE_MISS_FETCH_WDV) || + (CurrState == STATE_MISS_SPILL_FETCH_WDV) || + (CurrState == STATE_MISS_SPILL_MISS_FETCH_WDV); + // to compute the fetch address we need to add the bit shifted // counter output to the address. @@ -595,7 +600,13 @@ module icachecontroller #(parameter LINESIZE = 256) ( .q(reset_q)); flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FinalInstrRawF, NOP, AlignedInstrRawD); - mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, FlushD, InstrRawD); + // cannot have this mux as it creates a combo loop. + // This flop doesn't stall if StallF is high because we should output a nop + // when FlushD happens, even if the pipeline is also stalled. + flopr #(1) flushDLastCycleFlop(clk, reset, ~FlushD & (FlushDLastCyclen | ~StallF), FlushDLastCyclen); + mux2 #(32) InstrRawDMux(AlignedInstrRawD, NOP, ~FlushDLastCyclen, InstrRawD); + //assign InstrRawD = AlignedInstrRawD; + assign {ICacheMemReadUpperPAdr, ICacheMemReadLowerAdr} = PCPFinalF; From 532c8771bafb20f720d51fdc9869c97876690050 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 21 Apr 2021 08:39:54 -0500 Subject: [PATCH 48/55] major progress. It's running the icache is imperas tests now. Compressed does not work yet. --- wally-pipelined/regression/wave.do | 86 +++++++++++++++--------------- wally-pipelined/src/ifu/icache.sv | 20 ++++--- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 5174a350..816c566c 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -162,55 +162,55 @@ add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/N add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/D add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/Q add wave -noupdate -group divider /testbench/dut/hart/mdu/genblk1/div/rem0 -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/AHBByteLength -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/AHBOFFETWIDTH -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/BlockByteLength -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/OFFSETWIDTH -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/WORDSPERLINE -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LOGWPL -add wave -noupdate -expand -group parameters /testbench/dut/hart/ifu/icache/controller/LINESIZE -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/CurrState -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrInF -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData -add wave -noupdate -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr +add wave -noupdate -expand -group icache -color Orange /testbench/dut/hart/ifu/icache/controller/CurrState +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/hit +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/spill +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/ICacheStallF +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/SavePC +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/spillSave +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/UnalignedSelect +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/PCMux +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/AHBByteLength +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/AHBOFFETWIDTH +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/BlockByteLength +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/OFFSETWIDTH +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/WORDSPERLINE +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/LOGWPL +add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/LINESIZE +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrInF +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData +add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataValidBit +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataValid +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/ReadTag +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataTag +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadAddr +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadData +add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/ReadPAdr +add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteEnable +add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteLine +add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WritePAdr +add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteSet +add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteTag +add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData +add wave -noupdate -expand -group icache -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/FinalInstrRawF +add wave -noupdate -expand -group icache -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/AlignedInstrRawD +add wave -noupdate -expand -group icache -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/InstrRawD add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF -add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/FinalInstrRawF -add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/AlignedInstrRawD -add wave -noupdate -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/InstrRawD -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/hit -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/spill -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/spillSave -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/UnalignedSelect -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCMux add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPFinalF -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataValidBit -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataValid -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadTag -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/DataTag -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteEnable -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteLine -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WritePAdr -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteSet -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/WriteTag -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadAddr -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadData -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadPAdr -add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheMemReadData add wave -noupdate /testbench/dut/hart/ifu/icache/controller/genblk2/PCPreFinalF_q add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheStallF -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/SavePC TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {566 ns} 0} +WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {1598 ns} 0} quietly wave cursor active 2 configure wave -namecolwidth 250 configure wave -valuecolwidth 229 @@ -226,4 +226,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {458 ns} {674 ns} +WaveRestoreZoom {1559 ns} {1783 ns} diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 09dab7a8..f836afb6 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -206,14 +206,14 @@ module icachecontroller #(parameter LINESIZE = 256) ( assign PCNextPF = {UpperPCNextPF, LowerPCNextF}; - flopenl #(`XLEN) PCPFFlop(clk, reset, SavePC, PCPFinalF, `RESET_VECTOR, PCPF); + flopenl #(`XLEN) PCPFFlop(clk, reset, SavePC & ~StallF, PCPFinalF, `RESET_VECTOR, PCPF); // on spill we want to get the first 2 bytes of the next cache block. // the spill only occurs if the PCPF mod BlockByteLength == -2. Therefore we can // simply add 2 to land on the next cache block. assign PCSpillF = PCPF + 2'b10; // now we have to select between these three PCs - assign PCPreFinalF = PCMux[0] ? PCPF : PCNextPF; + assign PCPreFinalF = PCMux[0] | StallF ? PCPF : PCNextPF; // *** don't like the stallf assign PCPFinalF = PCMux[1] ? PCSpillF : PCPreFinalF; @@ -568,15 +568,19 @@ module icachecontroller #(parameter LINESIZE = 256) ( generate if( `XLEN == 32) begin logic [1:1] PCPreFinalF_q; - flop #(1) PCFReg(.clk(clk), - .d(PCPreFinalF[1]), - .q(PCPreFinalF_q[1])); + flopenr #(1) PCFReg(.clk(clk), + .reset(reset), + .en(~StallF), + .d(PCPreFinalF[1]), + .q(PCPreFinalF_q[1])); assign FinalInstrRawF = PCPreFinalF_q[1] ? {SpillDataBlock0, ICacheMemReadData[31:16]} : ICacheMemReadData; end else begin logic [2:1] PCPreFinalF_q; - flop #(2) PCFReg(.clk(clk), - .d(PCPreFinalF[2:1]), - .q(PCPreFinalF_q[2:1])); + flopenr #(2) PCFReg(.clk(clk), + .reset(reset), + .en(~StallF), + .d(PCPreFinalF[2:1]), + .q(PCPreFinalF_q[2:1])); mux4 #(32) AlignmentMux(.d0(ICacheMemReadData[31:0]), .d1(ICacheMemReadData[47:16]), .d2(ICacheMemReadData[63:32]), From 7b3735fc25f0d51ef977d0e9caf5c017cf5e550f Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Wed, 21 Apr 2021 16:47:05 -0500 Subject: [PATCH 49/55] Fixed for the instruction spills. --- wally-pipelined/regression/wave.do | 57 +++++++++++++++------------- wally-pipelined/src/cache/dmapped.sv | 28 +++++++++++++- wally-pipelined/src/ifu/icache.sv | 35 +++++------------ 3 files changed, 66 insertions(+), 54 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 816c566c..bdbb9ec2 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -1,4 +1,5 @@ onerror {resume} +quietly virtual function -install /testbench/dut/hart/ifu/icache/cachemem -env /testbench/dut/hart/ifu/icache/cachemem { &{/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[4], /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[3], /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[2], /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[1], /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[0] }} offset quietly WaveActivateNextPane {} 0 add wave -noupdate /testbench/clk add wave -noupdate /testbench/reset @@ -8,19 +9,19 @@ add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/fun add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InterruptM add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM @@ -59,15 +60,15 @@ add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNextF -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCF -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCPlus2or4F -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredPCF -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext0F -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE -add wave -noupdate -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/PCNextF +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/PCF +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/PCPlus2or4F +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredPCF +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext0F +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/PCNext1F +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/SelBPPredF +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/BPPredWrongE +add wave -noupdate -expand -group {PCNext Generation} /testbench/dut/hart/ifu/PrivilegedChangePCM add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ifu/InstrD add wave -noupdate -group {Decode Stage} /testbench/InstrDName add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD @@ -207,13 +208,17 @@ add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPFinalF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheMemReadData -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/genblk2/PCPreFinalF_q add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadLine +add wave -noupdate -radix hexadecimal -childformat {{{/testbench/dut/hart/ifu/icache/cachemem/ReadOffset[1]} -radix hexadecimal} {{/testbench/dut/hart/ifu/icache/cachemem/ReadOffset[0]} -radix hexadecimal}} -subitemconfig {{/testbench/dut/hart/ifu/icache/cachemem/ReadOffset[1]} {-height 16 -radix hexadecimal} {/testbench/dut/hart/ifu/icache/cachemem/ReadOffset[0]} {-height 16 -radix hexadecimal}} /testbench/dut/hart/ifu/icache/cachemem/ReadOffset +add wave -noupdate -label {read offset} -radix unsigned -childformat {{(4) -radix unsigned} {(3) -radix unsigned} {(2) -radix unsigned} {(1) -radix unsigned} {(0) -radix unsigned}} -subitemconfig {{/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[4]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[3]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[2]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[1]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[0]} {-radix unsigned}} /testbench/dut/hart/ifu/icache/cachemem/offset +add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr +add wave -noupdate /testbench/dut/hart/ifu/CompressedF TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {1598 ns} 0} +WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {9098514 ns} 0} quietly wave cursor active 2 configure wave -namecolwidth 250 -configure wave -valuecolwidth 229 +configure wave -valuecolwidth 513 configure wave -justifyvalue left configure wave -signalnamewidth 1 configure wave -snapdistance 10 @@ -226,4 +231,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {1559 ns} {1783 ns} +WaveRestoreZoom {9098483 ns} {9098569 ns} diff --git a/wally-pipelined/src/cache/dmapped.sv b/wally-pipelined/src/cache/dmapped.sv index 4f1cc2d3..34864d39 100644 --- a/wally-pipelined/src/cache/dmapped.sv +++ b/wally-pipelined/src/cache/dmapped.sv @@ -140,7 +140,7 @@ module rodirectmappedmemre #(parameter NUMLINES=512, parameter LINESIZE = 256, p input logic [LINESIZE-1:0] WriteLine, input logic [`XLEN-1:0] WritePAdr, // Output the word, as well as if it is valid - output logic [WORDSIZE-1:0] DataWord, + output logic [31:0] DataWord, // *** was WORDSIZE-1 output logic DataValid ); @@ -202,7 +202,31 @@ module rodirectmappedmemre #(parameter NUMLINES=512, parameter LINESIZE = 256, p ); // Pick the right bits coming out the read line - assign DataWord = ReadLineTransformed[ReadOffset]; + //assign DataWord = ReadLineTransformed[ReadOffset]; + //logic [31:0] tempRD; + always_comb begin + case (OldReadPAdr[4:1]) + 0: DataWord = ReadLine[31:0]; + 1: DataWord = ReadLine[47:16]; + 2: DataWord = ReadLine[63:32]; + 3: DataWord = ReadLine[79:48]; + + 4: DataWord = ReadLine[95:64]; + 5: DataWord = ReadLine[111:80]; + 6: DataWord = ReadLine[127:96]; + 7: DataWord = ReadLine[143:112]; + + 8: DataWord = ReadLine[159:128]; + 9: DataWord = ReadLine[175:144]; + 10: DataWord = ReadLine[191:160]; + 11: DataWord = ReadLine[207:176]; + + 12: DataWord = ReadLine[223:192]; + 13: DataWord = ReadLine[239:208]; + 14: DataWord = ReadLine[255:224]; + 15: DataWord = {16'b0, ReadLine[255:240]}; + endcase + end genvar i; generate for (i=0; i < LINESIZE/WORDSIZE; i++) begin diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index f836afb6..b14ae516 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -103,12 +103,12 @@ module icachecontroller #(parameter LINESIZE = 256) ( // Signals to/from cache memory // The read coming out of it - input logic [`XLEN-1:0] ICacheMemReadData, + input logic [31:0] ICacheMemReadData, input logic ICacheMemReadValid, // The address at which we want to search the cache memory output logic [`XLEN-1:12] ICacheMemReadUpperPAdr, output logic [11:0] ICacheMemReadLowerAdr, - output logic ICacheReadEn, + output logic ICacheReadEn, // Load data into the cache output logic ICacheMemWriteEnable, output logic [LINESIZE-1:0] ICacheMemWriteData, @@ -565,30 +565,13 @@ module icachecontroller #(parameter LINESIZE = 256) ( .q(SpillDataBlock0)); // use the not quite final PC to do the final selection. - generate - if( `XLEN == 32) begin - logic [1:1] PCPreFinalF_q; - flopenr #(1) PCFReg(.clk(clk), - .reset(reset), - .en(~StallF), - .d(PCPreFinalF[1]), - .q(PCPreFinalF_q[1])); - assign FinalInstrRawF = PCPreFinalF_q[1] ? {SpillDataBlock0, ICacheMemReadData[31:16]} : ICacheMemReadData; - end else begin - logic [2:1] PCPreFinalF_q; - flopenr #(2) PCFReg(.clk(clk), - .reset(reset), - .en(~StallF), - .d(PCPreFinalF[2:1]), - .q(PCPreFinalF_q[2:1])); - mux4 #(32) AlignmentMux(.d0(ICacheMemReadData[31:0]), - .d1(ICacheMemReadData[47:16]), - .d2(ICacheMemReadData[63:32]), - .d3({SpillDataBlock0, ICacheMemReadData[63:48]}), - .s(PCPreFinalF_q[2:1]), - .y(FinalInstrRawF)); - end - endgenerate + logic [1:1] PCPreFinalF_q; + flopenr #(1) PCFReg(.clk(clk), + .reset(reset), + .en(~StallF), + .d(PCPreFinalF[1]), + .q(PCPreFinalF_q[1])); + assign FinalInstrRawF = PCPreFinalF_q[1] ? {ICacheMemReadData[31:16], SpillDataBlock0} : ICacheMemReadData; // There is a frustrating issue on the first access. // The cache will not contain any valid data but will contain x's on From d8ab7a5de2fc20e7bd839ff67135546b0c8fcb03 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Thu, 22 Apr 2021 10:20:36 -0500 Subject: [PATCH 50/55] Partially working icache. The current issue is a StallF is required to halt the icache from getting an updated PCF. However if the dmemory is the reason for a stall it is possible for the icache stall to hold the d memory request continuously causing d memory to repeatedly read from memory. This keeps StallF high and the icache FSM is never allowed to complete. --- wally-pipelined/regression/wave.do | 101 +++++++++++++++-------------- wally-pipelined/src/ifu/icache.sv | 90 ++++++++++++++++++------- wally-pipelined/src/ifu/ifu.sv | 15 ++++- 3 files changed, 133 insertions(+), 73 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index bdbb9ec2..280042de 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -9,26 +9,26 @@ add wave -noupdate -expand -group {Execution Stage} /testbench/functionRadix/fun add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/EcallFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/StorePageFaultM -add wave -noupdate -expand -group HDU -expand -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/MulDivStallD +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/IllegalInstrFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/BreakpointFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreMisalignedFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StoreAccessFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/EcallFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InstrPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM +add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/MulDivStallD add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE @@ -172,6 +172,8 @@ add wave -noupdate -expand -group icache -expand -group {fsm out and control} /t add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/spillSave add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/UnalignedSelect add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/PCMux +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/spillSave +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/CntReset add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/AHBByteLength add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/AHBOFFETWIDTH add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/BlockByteLength @@ -179,34 +181,35 @@ add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/i add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/WORDSPERLINE add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/LOGWPL add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/LINESIZE -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/InstrInF -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData -add wave -noupdate -expand -group icache -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataValidBit -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataValid -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/ReadTag -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataTag -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadAddr -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadData -add wave -noupdate -expand -group icache -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/ReadPAdr -add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteEnable -add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteLine -add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WritePAdr -add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteSet -add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteTag -add wave -noupdate -expand -group icache -group memory -expand -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCountFlag +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/FetchCount +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrPAdrF +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrReadF +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrAckF +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/InstrInF +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteEnable +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWriteData +add wave -noupdate -expand -group icache -expand -group memory /testbench/dut/hart/ifu/icache/controller/ICacheMemWritePAdr +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataValidBit +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataValid +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/ReadTag +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/DataTag +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadAddr +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/cachetags/ReadData +add wave -noupdate -expand -group icache -expand -group memory -group {tag read} /testbench/dut/hart/ifu/icache/cachemem/ReadPAdr +add wave -noupdate -expand -group icache -expand -group memory -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteEnable +add wave -noupdate -expand -group icache -expand -group memory -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteLine +add wave -noupdate -expand -group icache -expand -group memory -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WritePAdr +add wave -noupdate -expand -group icache -expand -group memory -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteSet +add wave -noupdate -expand -group icache -expand -group memory -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/WriteTag +add wave -noupdate -expand -group icache -expand -group memory -group {tag write} /testbench/dut/hart/ifu/icache/cachemem/cachetags/StoredData add wave -noupdate -expand -group icache -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/FinalInstrRawF add wave -noupdate -expand -group icache -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/AlignedInstrRawD add wave -noupdate -expand -group icache -expand -group {instr to cpu} /testbench/dut/hart/ifu/icache/controller/InstrRawD -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPF -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF -add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPFinalF +add wave -noupdate -expand -group pc /testbench/dut/hart/ifu/icache/controller/PCNextPF +add wave -noupdate -expand -group pc /testbench/dut/hart/ifu/icache/controller/PCPF +add wave -noupdate -expand -group pc /testbench/dut/hart/ifu/icache/controller/PCPreFinalF +add wave -noupdate -expand -group pc /testbench/dut/hart/ifu/icache/controller/PCPFinalF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/ICacheMemReadData add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/ReadLine @@ -214,9 +217,11 @@ add wave -noupdate -radix hexadecimal -childformat {{{/testbench/dut/hart/ifu/ic add wave -noupdate -label {read offset} -radix unsigned -childformat {{(4) -radix unsigned} {(3) -radix unsigned} {(2) -radix unsigned} {(1) -radix unsigned} {(0) -radix unsigned}} -subitemconfig {{/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[4]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[3]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[2]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[1]} {-radix unsigned} {/testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr[0]} {-radix unsigned}} /testbench/dut/hart/ifu/icache/cachemem/offset add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr add wave -noupdate /testbench/dut/hart/ifu/CompressedF +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/SpillDataBlock0 +add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF_q TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {44 ns} 0} {{Cursor 2} {9098514 ns} 0} -quietly wave cursor active 2 +WaveRestoreCursors {{Cursor 2} {9808584 ns} 0} {{Cursor 3} {9808065 ns} 0} {{Cursor 4} {535 ns} 0} +quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 513 configure wave -justifyvalue left @@ -231,4 +236,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {9098483 ns} {9098569 ns} +WaveRestoreZoom {9808255 ns} {9808913 ns} diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index b14ae516..6f0437e2 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -140,19 +140,41 @@ module icachecontroller #(parameter LINESIZE = 256) ( localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 3; // write data into SRAM/LUT localparam STATE_HIT_SPILL_MERGE = 4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL. - localparam STATE_MISS_FETCH_WDV = 5; // aligned miss, issue read to AHB and wait for data. - localparam STATE_MISS_FETCH_DONE = 6; // write data into SRAM/LUT - localparam STATE_MISS_READ = 7; // read block 1 from SRAM/LUT + // a challenge is the spill signal gets us out of the ready state and moves us to + // 1 of the 2 spill branches. However the original fsm design had us return to + // the ready state when the spill + hits/misses were fully resolved. The problem + // is the spill signal is based on PCPF so when we return to READY to check if the + // cache has a hit it still expresses spill. We can fix in 1 of two ways. + // 1. we can add 1 extra state at the end of each spill branch to returns the instruction + // to the CPU advancing the CPU and icache to the next instruction. + // 2. We can assert a signal which is delayed 1 cycle to suppress the spill when we get + // to the READY state. + // The first first option is more robust and increases the number of states by 2. The + // second option is seams like it should work, but I worry there is a hidden interaction + // between CPU stalling and that register. + // Picking option 1. - localparam STATE_MISS_SPILL_FETCH_WDV = 8; // spill, miss on block 0, issue read to AHB and wait - localparam STATE_MISS_SPILL_FETCH_DONE = 9; // write data into SRAM/LUT - localparam STATE_MISS_SPILL_READ1 = 10; // read block 0 from SRAM/LUT - localparam STATE_MISS_SPILL_2 = 11; // return to ready if hit or do second block update. - localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 12; // miss on block 1, issue read to AHB and wait - localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 13; // write data to SRAM/LUT - localparam STATE_MISS_SPILL_MERGE = 14; // read block 0 of CPU access, + localparam STATE_HIT_SPILL_FINAL = 5; // this state replicates STATE_READY's replay of the + // spill access but does nto consider spill. It also does not do another operation. + - localparam STATE_INVALIDATE = 15; // *** not sure if invalidate or evict? invalidate by cache block or address? + localparam STATE_MISS_FETCH_WDV = 6; // aligned miss, issue read to AHB and wait for data. + localparam STATE_MISS_FETCH_DONE = 7; // write data into SRAM/LUT + localparam STATE_MISS_READ = 8; // read block 1 from SRAM/LUT + + localparam STATE_MISS_SPILL_FETCH_WDV = 9; // spill, miss on block 0, issue read to AHB and wait + localparam STATE_MISS_SPILL_FETCH_DONE = 10; // write data into SRAM/LUT + localparam STATE_MISS_SPILL_READ1 = 11; // read block 0 from SRAM/LUT + localparam STATE_MISS_SPILL_2 = 12; // return to ready if hit or do second block update. + localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 13; // miss on block 1, issue read to AHB and wait + localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 14; // write data to SRAM/LUT + localparam STATE_MISS_SPILL_MERGE = 15; // read block 0 of CPU access, + + localparam STATE_MISS_SPILL_FINAL = 16; // this state replicates STATE_READY's replay of the + // spill access but does nto consider spill. It also does not do another operation. + + + localparam STATE_INVALIDATE = 17; // *** not sure if invalidate or evict? invalidate by cache block or address? localparam AHBByteLength = `XLEN / 8; localparam AHBOFFETWIDTH = $clog2(AHBByteLength); @@ -164,7 +186,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( localparam WORDSPERLINE = LINESIZE/`XLEN; localparam LOGWPL = $clog2(WORDSPERLINE); - logic [3:0] CurrState, NextState; + logic [4:0] CurrState, NextState; logic hit, spill; logic SavePC; logic [1:0] PCMux; @@ -213,7 +235,8 @@ module icachecontroller #(parameter LINESIZE = 256) ( assign PCSpillF = PCPF + 2'b10; // now we have to select between these three PCs - assign PCPreFinalF = PCMux[0] | StallF ? PCPF : PCNextPF; // *** don't like the stallf + assign PCPreFinalF = PCMux[0] | StallF ? PCPF : PCNextPF; // *** don't like the stallf + //assign PCPreFinalF = PCMux[0] ? PCPF : PCNextPF; // *** don't like the stallf assign PCPFinalF = PCMux[1] ? PCSpillF : PCPreFinalF; @@ -347,12 +370,12 @@ module icachecontroller #(parameter LINESIZE = 256) ( -----/\----- EXCLUDED -----/\----- */ // the FSM is always runing, do not stall. - flopr #(4) stateReg(.clk(clk), + flopr #(5) stateReg(.clk(clk), .reset(reset), .d(NextState), .q(CurrState)); - assign spill = PCPF[5:1] == 5'b1_1111 ? 1'b1 : 1'b0; + assign spill = PCPF[4:1] == 4'b1111 ? 1'b1 : 1'b0; assign hit = ICacheMemReadValid; // note ICacheMemReadValid is hit. assign FetchCountFlag = FetchCount == FetchCountThreshold; @@ -366,6 +389,8 @@ module icachecontroller #(parameter LINESIZE = 256) ( spillSave = 1'b0; PCMux = 2'b00; ICacheReadEn = 1'b0; + SavePC = 1'b0; + ICacheStallF = 1'b1; case (CurrState) @@ -373,15 +398,19 @@ module icachecontroller #(parameter LINESIZE = 256) ( PCMux = 2'b00; ICacheReadEn = 1'b1; if (hit & ~spill) begin + SavePC = 1'b1; + ICacheStallF = 1'b0; NextState = STATE_READY; end else if (hit & spill) begin spillSave = 1'b1; + PCMux = 2'b10; NextState = STATE_HIT_SPILL; end else if (~hit & ~spill) begin CntReset = 1'b1; NextState = STATE_MISS_FETCH_WDV; end else if (~hit & spill) begin CntReset = 1'b1; + PCMux = 2'b10; NextState = STATE_MISS_SPILL_FETCH_WDV; end else begin NextState = STATE_READY; @@ -394,7 +423,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( UnalignedSelect = 1'b1; ICacheReadEn = 1'b1; if (hit) begin - NextState = STATE_READY; + NextState = STATE_HIT_SPILL_FINAL; end else CntReset = 1'b1; NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; @@ -418,7 +447,15 @@ module icachecontroller #(parameter LINESIZE = 256) ( PCMux = 2'b10; UnalignedSelect = 1'b1; ICacheReadEn = 1'b1; - NextState = STATE_READY; + NextState = STATE_HIT_SPILL_FINAL; + end + STATE_HIT_SPILL_FINAL: begin + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + NextState = STATE_READY; + ICacheStallF = 1'b0; end // branch 3 miss no spill @@ -472,7 +509,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( CntReset = 1'b1; NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; end else begin - NextState = STATE_READY; + NextState = STATE_MISS_SPILL_FINAL; end end STATE_MISS_SPILL_MISS_FETCH_WDV: begin @@ -494,7 +531,15 @@ module icachecontroller #(parameter LINESIZE = 256) ( PCMux = 2'b10; UnalignedSelect = 1'b1; ICacheReadEn = 1'b1; - NextState = STATE_READY; + NextState = STATE_MISS_SPILL_FINAL; + end + STATE_MISS_SPILL_FINAL: begin + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + ICacheStallF = 1'b0; + NextState = STATE_READY; end default: begin PCMux = 2'b01; @@ -508,9 +553,10 @@ module icachecontroller #(parameter LINESIZE = 256) ( // stall CPU any time we are not in the ready state. any other state means the // cache is either requesting data from the memory interface or handling a // spill over two cycles. - assign ICacheStallF = ((CurrState != STATE_READY) | ~hit) | reset_q ? 1'b1 : 1'b0; + // *** BUG this logic will need to change + //assign ICacheStallF = ((CurrState != STATE_READY) | ~hit | spill) | reset_q ? 1'b1 : 1'b0; // save the PC anytime we are in the ready state. The saved value will be used as the PC may not be stable. - assign SavePC = (CurrState == STATE_READY) & hit ? 1'b1 : 1'b0; + //assign SavePC = ((CurrState == STATE_READY) & hit) & ~spill ? 1'b1 : 1'b0; assign CntEn = PreCntEn & InstrAckF; assign InstrReadF = (CurrState == STATE_HIT_SPILL_MISS_FETCH_WDV) || @@ -571,7 +617,7 @@ module icachecontroller #(parameter LINESIZE = 256) ( .en(~StallF), .d(PCPreFinalF[1]), .q(PCPreFinalF_q[1])); - assign FinalInstrRawF = PCPreFinalF_q[1] ? {ICacheMemReadData[31:16], SpillDataBlock0} : ICacheMemReadData; + assign FinalInstrRawF = spill ? {ICacheMemReadData[15:0], SpillDataBlock0} : ICacheMemReadData; // There is a frustrating issue on the first access. // The cache will not contain any valid data but will contain x's on diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 58b144f5..5d728764 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -89,7 +89,7 @@ module ifu ( // branch predictor signals logic SelBPPredF; - logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F, PCNext2F; + logic [`XLEN-1:0] BPPredPCF, PCCorrectE, PCNext0F, PCNext1F, PCNext2F, PCNext3F; logic [3:0] InstrClassD, InstrClassE; @@ -124,11 +124,20 @@ module ifu ( .s(PrivilegedChangePCM), .y(PCNext2F)); + // *** try to remove this in the future as it can add a long path. + // StallF may arrive late. +/* -----\/----- EXCLUDED -----\/----- mux2 #(`XLEN) pcmux3(.d0(PCNext2F), + .d1(PCF), + .s(StallF), + .y(PCNext3F)); + -----/\----- EXCLUDED -----/\----- */ + + mux2 #(`XLEN) pcmux4(.d0(PCNext2F), .d1(`RESET_VECTOR), .s(reset_q), - .y(UnalignedPCNextF)); - + .y(UnalignedPCNextF)); + flop #(1) resetReg (.clk(clk), .d(reset), .q(reset_q)); From c42399bdb5b5bc99f41f9638f8aa056a43e12e54 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Thu, 22 Apr 2021 15:22:56 -0500 Subject: [PATCH 51/55] Yes. The hack to not repeat the d memory operation fixed this issue. --- wally-pipelined/regression/wave.do | 25 ++++++++++++++++++-- wally-pipelined/src/dmem/dmem.sv | 37 ++++++++++++++++++++++++++++-- wally-pipelined/src/ebu/ahblite.sv | 4 +++- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 280042de..0dbdf5de 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -101,6 +101,9 @@ add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate /testbench/InstrFName +add wave -noupdate -expand -group {dcache memory} /testbench/dut/hart/dmem/MemReadM +add wave -noupdate -expand -group {dcache memory} /testbench/dut/hart/dmem/MemWriteM +add wave -noupdate -expand -group {dcache memory} /testbench/dut/hart/dmem/MemAckW add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM @@ -174,6 +177,8 @@ add wave -noupdate -expand -group icache -expand -group {fsm out and control} /t add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/PCMux add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/spillSave add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/CntReset +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/PreCntEn +add wave -noupdate -expand -group icache -expand -group {fsm out and control} /testbench/dut/hart/ifu/icache/controller/CntEn add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/AHBByteLength add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/AHBOFFETWIDTH add wave -noupdate -expand -group icache -group parameters /testbench/dut/hart/ifu/icache/controller/BlockByteLength @@ -219,8 +224,24 @@ add wave -noupdate /testbench/dut/hart/ifu/icache/cachemem/OldReadPAdr add wave -noupdate /testbench/dut/hart/ifu/CompressedF add wave -noupdate /testbench/dut/hart/ifu/icache/controller/SpillDataBlock0 add wave -noupdate /testbench/dut/hart/ifu/icache/controller/PCPreFinalF_q +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/BusState +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HCLK +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HRDATA +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HREADY +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HRESP +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HADDR +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HWDATA +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HWRITE +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HSIZE +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HBURST +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HPROT +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HTRANS +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HMASTLOCK +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HADDRD +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HSIZED +add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HWRITED TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {9808584 ns} 0} {{Cursor 3} {9808065 ns} 0} {{Cursor 4} {535 ns} 0} +WaveRestoreCursors {{Cursor 2} {9808206 ns} 0} {{Cursor 3} {9807791 ns} 0} {{Cursor 4} {85 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 513 @@ -236,4 +257,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {9808255 ns} {9808913 ns} +WaveRestoreZoom {9807926 ns} {9808486 ns} diff --git a/wally-pipelined/src/dmem/dmem.sv b/wally-pipelined/src/dmem/dmem.sv index 75559c3f..8836972b 100644 --- a/wally-pipelined/src/dmem/dmem.sv +++ b/wally-pipelined/src/dmem/dmem.sv @@ -63,6 +63,14 @@ module dmem ( // *** needs to be sent to trap unit logic DTLBPageFaultM; + logic [1:0] CurrState, NextState; + + localparam STATE_READY = 0; + localparam STATE_FETCH = 1; + localparam STATE_STALLED = 2; + + + tlb #(3) dtlb(.TLBAccess(MemAccessM), .VirtualAddress(MemAdrM), .PageTableEntryWrite(PageTableEntryM), .PageTypeWrite(PageTypeM), .TLBWrite(DTLBWriteM), .TLBFlush(DTLBFlushM), @@ -81,8 +89,8 @@ module dmem ( // Squash unaligned data accesses and failed store conditionals // *** this is also the place to squash if the cache is hit - assign MemReadM = MemRWM[1] & ~DataMisalignedM; - assign MemWriteM = MemRWM[0] & ~DataMisalignedM && ~SquashSCM; + assign MemReadM = MemRWM[1] & ~DataMisalignedM & CurrState != STATE_STALLED; + assign MemWriteM = MemRWM[0] & ~DataMisalignedM && ~SquashSCM & CurrState != STATE_STALLED; assign MemAccessM = |MemRWM; // Determine if address is valid @@ -119,5 +127,30 @@ module dmem ( // Data stall //assign DataStall = 0; + // Ross Thompson April 22, 2021 + // for now we need to handle the issue where the data memory interface repeately + // requests data from memory rather than issuing a single request. + + + flopr #(2) stateReg(.clk(clk), + .reset(reset), + .d(NextState), + .q(CurrState)); + + always_comb begin + case (CurrState) + STATE_READY: if (MemAccessM & ~DataMisalignedM) NextState = STATE_FETCH; + else NextState = STATE_READY; + STATE_FETCH: if (MemAckW & ~StallW) NextState = STATE_READY; + else if (MemAckW & StallW) NextState = STATE_STALLED; + else NextState = STATE_FETCH; + STATE_STALLED: if (~StallW) NextState = STATE_READY; + else NextState = STATE_STALLED; + default: NextState = STATE_READY; + endcase // case (CurrState) + end + + + endmodule diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index e71a94f9..c2121714 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -75,7 +75,8 @@ module ahblite ( output logic [3:0] HSIZED, output logic HWRITED, // Stalls - output logic /*InstrUpdate, */DataStall + output logic /*InstrUpdate, */DataStall, + output logic MemAckW // *** add a chip-level ready signal as part of handshake ); @@ -175,6 +176,7 @@ module ahblite ( assign InstrRData = HRDATA; assign InstrAckF = (BusState == INSTRREAD) && (NextBusState != INSTRREAD) || (BusState == INSTRREADC) && (NextBusState != INSTRREADC); + assign MemAckW = (BusState == MEMREAD) && (NextBusState != MEMREAD) || (BusState == MEMWRITE) && (NextBusState != MEMWRITE); assign MMUReadPTE = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || From 27ef10df07a03c62142dbd535c1cb4744c90815b Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Fri, 23 Apr 2021 16:47:23 -0500 Subject: [PATCH 52/55] almost working icache. --- wally-pipelined/regression/wave.do | 61 +++++++++++-------- wally-pipelined/src/dmem/dmem.sv | 14 +++-- wally-pipelined/src/ebu/ahblite.sv | 10 +-- .../src/wally/wallypipelinedhart.sv | 1 + 4 files changed, 52 insertions(+), 34 deletions(-) diff --git a/wally-pipelined/regression/wave.do b/wally-pipelined/regression/wave.do index 7c61d468..42596464 100644 --- a/wally-pipelined/regression/wave.do +++ b/wally-pipelined/regression/wave.do @@ -22,13 +22,13 @@ add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/LoadPageFaultM add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/StorePageFaultM add wave -noupdate -expand -group HDU -group traps /testbench/dut/hart/priv/trap/InterruptM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/BPPredWrongE -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/RetM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/TrapM -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/LoadStallD -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/hzu/DataStall -add wave -noupdate -expand -group HDU -expand -group hazards /testbench/dut/hart/MulDivStallD +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/BPPredWrongE +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/CSRWritePendingDEM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/RetM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/TrapM +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/LoadStallD +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/hzu/DataStall +add wave -noupdate -expand -group HDU -group hazards /testbench/dut/hart/MulDivStallD add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/hzu/FlushF add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushD add wave -noupdate -expand -group HDU -expand -group Flush -color Yellow /testbench/dut/hart/FlushE @@ -57,6 +57,7 @@ add wave -noupdate -group Bpred -group BTB -divider Lookup add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/TargetPC add wave -noupdate -group Bpred -group BTB /testbench/dut/hart/ifu/bpred/TargetPredictor/Valid add wave -noupdate -group Bpred /testbench/dut/hart/ifu/bpred/BPPredWrongE +add wave -noupdate -expand -group {instruction pipeline} /testbench/InstrFName add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrD add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrE add wave -noupdate -expand -group {instruction pipeline} /testbench/dut/hart/ifu/InstrM @@ -88,26 +89,33 @@ add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/CSRReadValW add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultSrcW add wave -noupdate -group RegFile -group {write regfile mux} /testbench/dut/hart/ieu/dp/ResultW -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/a -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/b -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/result -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/flags -add wave -noupdate -group alu -divider internals -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/overflow -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/carry -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/zero -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/neg -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/lt -add wave -noupdate -group alu /testbench/dut/hart/ieu/dp/alu/ltu -add wave -noupdate /testbench/InstrFName +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/a +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/b +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/alucontrol +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/result +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/flags +add wave -noupdate -expand -group alu -divider internals +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/overflow +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/carry +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/zero +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/neg +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/lt +add wave -noupdate -expand -group alu /testbench/dut/hart/ieu/dp/alu/ltu add wave -noupdate -expand -group {dcache memory} /testbench/dut/hart/dmem/MemReadM add wave -noupdate -expand -group {dcache memory} /testbench/dut/hart/dmem/MemWriteM add wave -noupdate -expand -group {dcache memory} /testbench/dut/hart/dmem/MemAckW -add wave -noupdate -group dcache /testbench/dut/hart/MemAdrM -add wave -noupdate -group dcache /testbench/dut/hart/MemPAdrM -add wave -noupdate -group dcache /testbench/dut/hart/WriteDataM -add wave -noupdate -group dcache /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -expand -group dcache -expand -group {cpu request} /testbench/dut/hart/dmem/MemRWM +add wave -noupdate -expand -group dcache -expand -group {cpu request} /testbench/dut/hart/dmem/AtomicM +add wave -noupdate -expand -group dcache -expand -group {cpu request} /testbench/dut/hart/MemAdrM +add wave -noupdate -expand -group dcache -expand -group {cpu request} /testbench/dut/hart/dmem/ReadDataW +add wave -noupdate -expand -group dcache -expand -group {cpu request} /testbench/dut/hart/WriteDataM +add wave -noupdate -expand -group dcache -color Gray90 /testbench/dut/hart/dmem/CurrState +add wave -noupdate -expand -group dcache /testbench/dut/hart/MemPAdrM +add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemAccessM +add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/AtomicMaskedM +add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/MemAckW +add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/genblk1/lrM +add wave -noupdate -expand -group dcache /testbench/dut/hart/dmem/genblk1/scM add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs2D add wave -noupdate -group Forward /testbench/dut/hart/ieu/fw/Rs1E @@ -231,8 +239,9 @@ add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HMASTLOCK add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HADDRD add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HSIZED add wave -noupdate -expand -group AHB /testbench/dut/hart/ebu/HWRITED +add wave -noupdate /testbench/dut/hart/dmem/genblk1/scM TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 2} {9808206 ns} 0} {{Cursor 3} {9807791 ns} 0} {{Cursor 4} {85 ns} 0} +WaveRestoreCursors {{Cursor 2} {12215488 ns} 0} {{Cursor 4} {12211487 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 250 configure wave -valuecolwidth 513 @@ -248,4 +257,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {0 ns} {1829700 ns} +WaveRestoreZoom {12215315 ns} {12215675 ns} diff --git a/wally-pipelined/src/dmem/dmem.sv b/wally-pipelined/src/dmem/dmem.sv index 16813629..d8dad8bb 100644 --- a/wally-pipelined/src/dmem/dmem.sv +++ b/wally-pipelined/src/dmem/dmem.sv @@ -27,6 +27,7 @@ `include "wally-config.vh" +// *** Ross Thompson amo misalignment check? module dmem ( input logic clk, reset, input logic StallW, FlushW, @@ -40,6 +41,7 @@ module dmem ( input logic [1:0] AtomicM, output logic [`XLEN-1:0] MemPAdrM, output logic MemReadM, MemWriteM, + output logic [1:0] AtomicMaskedM, output logic DataMisalignedM, // Writeback Stage input logic MemAckW, @@ -68,8 +70,8 @@ module dmem ( localparam STATE_READY = 0; localparam STATE_FETCH = 1; - localparam STATE_STALLED = 2; - + localparam STATE_FETCH_AMO = 2; + localparam STATE_STALLED = 3; tlb #(.ENTRY_BITS(3), .ITLB(0)) dtlb(.TLBAccessType(MemRWM), .VirtualAddress(MemAdrM), .PageTableEntryWrite(PageTableEntryM), .PageTypeWrite(PageTypeM), @@ -95,6 +97,7 @@ module dmem ( // *** this is also the place to squash if the cache is hit assign MemReadM = MemRWM[1] & ~DataMisalignedM & CurrState != STATE_STALLED; assign MemWriteM = MemRWM[0] & ~DataMisalignedM && ~SquashSCM & CurrState != STATE_STALLED; + assign AtomicMaskedM = CurrState != STATE_STALLED ? AtomicM : 2'b00 ; assign MemAccessM = |MemRWM; // Determine if address is valid @@ -143,8 +146,11 @@ module dmem ( always_comb begin case (CurrState) - STATE_READY: if (MemAccessM & ~DataMisalignedM) NextState = STATE_FETCH; - else NextState = STATE_READY; + STATE_READY: if (MemRWM[1] & MemRWM[0]) NextState = STATE_FETCH_AMO; // *** should be some misalign check + else if (MemAccessM & ~DataMisalignedM) NextState = STATE_FETCH; + else NextState = STATE_READY; + STATE_FETCH_AMO: if (MemAckW) NextState = STATE_FETCH; + else NextState = STATE_FETCH_AMO; STATE_FETCH: if (MemAckW & ~StallW) NextState = STATE_READY; else if (MemAckW & StallW) NextState = STATE_STALLED; else NextState = STATE_FETCH; diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index b14e7bcb..31b9e9c6 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -39,7 +39,7 @@ module ahblite ( input logic StallW, FlushW, // Load control input logic UnsignedLoadM, - input logic [1:0] AtomicM, + input logic [1:0] AtomicMaskedM, input logic [6:0] Funct7M, // Signals from Instruction Cache input logic [`XLEN-1:0] InstrPAdrF, // *** rename these to match block diagram @@ -114,7 +114,7 @@ module ahblite ( always_comb case (BusState) IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE; - else if (AtomicM[1]) NextBusState = ATOMICREAD; + else if (AtomicMaskedM[1]) NextBusState = ATOMICREAD; else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions else if (MemWriteM) NextBusState = MEMWRITE; else if (InstrReadF) NextBusState = INSTRREAD; @@ -188,7 +188,8 @@ module ahblite ( assign InstrRData = HRDATA; assign InstrAckF = (BusState == INSTRREAD) && (NextBusState != INSTRREAD) || (BusState == INSTRREADC) && (NextBusState != INSTRREADC); - assign MemAckW = (BusState == MEMREAD) && (NextBusState != MEMREAD) || (BusState == MEMWRITE) && (NextBusState != MEMWRITE); + assign MemAckW = (BusState == MEMREAD) && (NextBusState != MEMREAD) || (BusState == MEMWRITE) && (NextBusState != MEMWRITE) || + ((BusState == ATOMICREAD) && (NextBusState != ATOMICREAD)) || ((BusState == ATOMICWRITE) && (NextBusState != ATOMICWRITE)); assign MMUReadPTE = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || @@ -199,6 +200,7 @@ module ahblite ( flopenr #(`XLEN) ReadDataNewWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataNewW); flopenr #(`XLEN) ReadDataOldWReg(clk, reset, CaptureDataM, ReadDataNewW, ReadDataOldW); assign ReadDataW = (BusState == INSTRREADC) ? ReadDataOldW : ReadDataNewW; + //assign ReadDataW = (BusState == INSTRREADC) ? ReadDataOldW : ReadDataNewW; // Extract and sign-extend subwords if necessary subwordread swr(.*); @@ -211,7 +213,7 @@ module ahblite ( // .result(AMOResult)); amoalu amoalu(.srca(ReadDataW), .srcb(WriteDataM), .funct(Funct7M), .width(MemSizeM), .result(AMOResult)); - mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, AtomicM[1], WriteData); + mux2 #(`XLEN) wdmux(WriteDataM, AMOResult, AtomicMaskedM[1], WriteData); end else assign WriteData = WriteDataM; endgenerate diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 69275e9c..5526976a 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -124,6 +124,7 @@ module wallypipelinedhart ( // bus interface to dmem logic MemReadM, MemWriteM; + logic [1:0] AtomicMaskedM; logic [2:0] Funct3M; logic [`XLEN-1:0] MemAdrM, MemPAdrM, WriteDataM; logic [`XLEN-1:0] ReadDataW; From 1cc0dcc83fab4412aac4b3a8a906804fd4f88c03 Mon Sep 17 00:00:00 2001 From: bbracker Date: Mon, 26 Apr 2021 07:43:16 -0400 Subject: [PATCH 53/55] progress on bus and lrsc --- .../regression/wave-dos/cache-waves.do | 26 ++++++---------- wally-pipelined/src/dmem/dmem.sv | 4 +-- wally-pipelined/src/ebu/ahblite.sv | 31 +++++++++++++------ wally-pipelined/src/ebu/pmachecker.sv | 3 +- wally-pipelined/src/ifu/icache.sv | 2 +- wally-pipelined/src/ifu/ifu.sv | 3 +- wally-pipelined/src/privileged/privileged.sv | 3 +- .../testbench/testbench-busybear.sv | 21 +++++++------ 8 files changed, 50 insertions(+), 43 deletions(-) diff --git a/wally-pipelined/regression/wave-dos/cache-waves.do b/wally-pipelined/regression/wave-dos/cache-waves.do index c7b32e1e..f8d98d3d 100644 --- a/wally-pipelined/regression/wave-dos/cache-waves.do +++ b/wally-pipelined/regression/wave-dos/cache-waves.do @@ -21,18 +21,6 @@ add wave -hex /testbench/dut/hart/ifu/PCD add wave -hex /testbench/dut/hart/ifu/InstrD add wave /testbench/InstrDName -add wave -hex /testbench/dut/hart/ifu/ic/InstrRawD -add wave -hex /testbench/dut/hart/ifu/ic/controller/AlignedInstrRawD -add wave -divider -add wave -hex /testbench/dut/hart/ifu/ic/controller/FetchState -add wave -hex /testbench/dut/hart/ifu/ic/controller/FetchWordNum -add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWriteEnable -add wave -hex /testbench/dut/hart/ifu/ic/InstrPAdrF -add wave -hex /testbench/dut/hart/ifu/ic/InstrAckF -add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWriteData -add wave -hex /testbench/dut/hart/ifu/ic/controller/ICacheMemWritePAdr -add wave -hex /testbench/dut/hart/ifu/ic/controller/MisalignedState -add wave -hex /testbench/dut/hart/ifu/ic/controller/MisalignedHalfInstrF add wave -divider @@ -63,12 +51,15 @@ add wave -hex /testbench/dut/hart/ebu/HTRANS add wave -hex /testbench/dut/hart/ebu/HRDATA add wave -hex /testbench/dut/hart/ebu/HWRITE add wave -hex /testbench/dut/hart/ebu/HWDATA -add wave -hex /testbench/dut/hart/ebu/CaptureDataM -add wave -divider - -add wave -hex /testbench/dut/uncore/dtim/* +add wave -hex /testbench/dut/hart/ebu/ReadDataM add wave -divider +add wave /testbench/dut/hart/ebu/CaptureDataM +add wave /testbench/dut/hart/ebu/CapturedDataAvailable +add wave /testbench/dut/hart/StallW +add wave -hex /testbench/dut/hart/ebu/CapturedData +add wave -hex /testbench/dut/hart/ebu/ReadDataWnext +add wave -hex /testbench/dut/hart/ebu/ReadDataW add wave -hex /testbench/dut/hart/ifu/PCW add wave -hex /testbench/dut/hart/ifu/InstrW add wave /testbench/InstrWName @@ -78,7 +69,8 @@ add wave -hex /testbench/dut/hart/ieu/dp/ResultW add wave -hex /testbench/dut/hart/ieu/dp/RdW add wave -divider -add wave -hex /testbench/dut/uncore/dtim/* +add wave -hex /testbench/dut/hart/dmem/* +add wave -hex /testbench/dut/hart/dmem/genblk1/* add wave -divider add wave -hex -r /testbench/* diff --git a/wally-pipelined/src/dmem/dmem.sv b/wally-pipelined/src/dmem/dmem.sv index d8dad8bb..506583a0 100644 --- a/wally-pipelined/src/dmem/dmem.sv +++ b/wally-pipelined/src/dmem/dmem.sv @@ -122,8 +122,8 @@ module dmem ( else if (scM || WriteAdrMatchM) ReservationValidM = 0; // clear valid on store to same address or any sc else ReservationValidM = ReservationValidW; // otherwise don't change valid end - flopenrc #(`XLEN-2) resadrreg(clk, reset, FlushW, ~StallW && lrM, MemPAdrM[`XLEN-1:2], ReservationPAdrW); // could drop clear on this one but not valid - flopenrc #(1) resvldreg(clk, reset, FlushW, ~StallW, ReservationValidM, ReservationValidW); + flopenrc #(`XLEN-2) resadrreg(clk, reset, FlushW, lrM, MemPAdrM[`XLEN-1:2], ReservationPAdrW); // could drop clear on this one but not valid + flopenrc #(1) resvldreg(clk, reset, FlushW, lrM, ReservationValidM, ReservationValidW); flopenrc #(1) squashreg(clk, reset, FlushW, ~StallW, SquashSCM, SquashSCW); end else begin // Atomic operations not supported assign SquashSCM = 0; diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 31b9e9c6..23ae2eb6 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -86,9 +86,9 @@ module ahblite ( logic GrantData; logic [31:0] AccessAddress; logic [2:0] AccessSize, PTESize, ISize; - logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataNewW, ReadDataOldW, WriteData; + logic [`AHBW-1:0] HRDATAMasked, ReadDataM, CapturedData, ReadDataWnext, WriteData; logic IReady, DReady; - logic CaptureDataM; + logic CaptureDataM,CapturedDataAvailable; // Describes type of access logic Atomic, Execute, Write, Read; @@ -192,15 +192,26 @@ module ahblite ( ((BusState == ATOMICREAD) && (NextBusState != ATOMICREAD)) || ((BusState == ATOMICWRITE) && (NextBusState != ATOMICWRITE)); assign MMUReadPTE = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 + // Carefully decide when to update ReadDataW + // ReadDataMstored holds the most recent memory read. + // We need to wait until the pipeline actually advances before we can update the contents of ReadDataW + // (or else the W stage will accidentally get the M stage's data when the pipeline does advance). assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || - ((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE)); - // We think this introduces an unnecessary cycle of latency in memory accesses - // *** can the following be simplified down to one register? - // *** examine more closely over summer? - flopenr #(`XLEN) ReadDataNewWReg(clk, reset, CaptureDataM, ReadDataM, ReadDataNewW); - flopenr #(`XLEN) ReadDataOldWReg(clk, reset, CaptureDataM, ReadDataNewW, ReadDataOldW); - assign ReadDataW = (BusState == INSTRREADC) ? ReadDataOldW : ReadDataNewW; - //assign ReadDataW = (BusState == INSTRREADC) ? ReadDataOldW : ReadDataNewW; + ((BusState == ATOMICREAD) && (NextBusState != ATOMICREAD)); + flopenr #(`XLEN) ReadDataNewWReg(clk, reset, CaptureDataM, ReadDataM, CapturedData); + + always @(posedge HCLK, negedge HRESETn) + if (~HRESETn) + CapturedDataAvailable <= #1 1'b0; + else + CapturedDataAvailable <= #1 (StallW) ? (CaptureDataM | CapturedDataAvailable) : 1'b0; + always_comb + casez({StallW && (BusState != ATOMICREAD),CapturedDataAvailable}) + 2'b00: ReadDataWnext = ReadDataM; + 2'b01: ReadDataWnext = CapturedData; + 2'b1?: ReadDataWnext = ReadDataW; + endcase + flopr #(`XLEN) ReadDataOldWReg(clk, reset, ReadDataWnext, ReadDataW); // Extract and sign-extend subwords if necessary subwordread swr(.*); diff --git a/wally-pipelined/src/ebu/pmachecker.sv b/wally-pipelined/src/ebu/pmachecker.sv index bb2a124c..3f434d67 100644 --- a/wally-pipelined/src/ebu/pmachecker.sv +++ b/wally-pipelined/src/ebu/pmachecker.sv @@ -29,9 +29,8 @@ module pmachecker ( input logic [31:0] HADDR, - input logic HSIZE, + input logic [2:0] HSIZE, HBURST, input logic HWRITE, - input logic HBURST, input logic Atomic, Execute, Write, Read, diff --git a/wally-pipelined/src/ifu/icache.sv b/wally-pipelined/src/ifu/icache.sv index 71856463..98dc985d 100644 --- a/wally-pipelined/src/ifu/icache.sv +++ b/wally-pipelined/src/ifu/icache.sv @@ -63,7 +63,7 @@ module icache( logic [`XLEN-1:0] ICacheMemWritePAdr; logic EndFetchState; // Output signals from cache memory - logic [`XLEN-1:0] ICacheMemReadData; + logic [31:0] ICacheMemReadData; logic ICacheMemReadValid; logic ICacheReadEn; diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 22af97ac..58c1852b 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -77,7 +77,8 @@ module ifu ( logic CompressedF; logic [31:0] InstrRawD, InstrE, InstrW; localparam [31:0] nop = 32'h00000013; // instruction for NOP - logic reset_q; // *** look at this later. + logic reset_q; // *** look at this later. + logic [`XLEN-1:0] PCPF; tlb #(.ENTRY_BITS(3), .ITLB(1)) itlb(.TLBAccessType(2'b10), .VirtualAddress(PCF), .PageTableEntryWrite(PageTableEntryF), .PageTypeWrite(PageTypeF), diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index f4b9e74c..fc075cb1 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -56,7 +56,8 @@ module privileged ( // PMA checker signals input logic [31:0] HADDR, - input logic HSIZE, HWRITE, HBURST, + input logic HWRITE, + input logic [2:0] HSIZE, HBURST, input logic Atomic, Execute, Write, Read, output logic Cacheable, Idempotent, AtomicAllowed, output logic SquashAHBAccess, diff --git a/wally-pipelined/testbench/testbench-busybear.sv b/wally-pipelined/testbench/testbench-busybear.sv index 0f5c9e2f..5ce8d761 100644 --- a/wally-pipelined/testbench/testbench-busybear.sv +++ b/wally-pipelined/testbench/testbench-busybear.sv @@ -1,5 +1,9 @@ `include "wally-config.vh" +package ahbliteState; + typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE} statetype; +endpackage + module testbench_busybear(); logic clk, reset; @@ -504,11 +508,11 @@ module testbench_busybear(); // Track names of instructions string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; logic [31:0] InstrW; - instrNameDecTB dec(dut.hart.ifu.ic.InstrF, InstrFName); - instrTrackerTB it(clk, reset, dut.hart.ieu.dp.FlushE, + instrTrackerTB it(clk, reset, + dut.hart.ifu.icache.controller.FinalInstrRawF, dut.hart.ifu.InstrD, dut.hart.ifu.InstrE, - dut.hart.ifu.InstrM, InstrW, - InstrDName, InstrEName, InstrMName, InstrWName); + dut.hart.ifu.InstrM, dut.hart.ifu.InstrW, + InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // generate clock to sequence tests always @@ -518,15 +522,14 @@ module testbench_busybear(); endmodule module instrTrackerTB( - input logic clk, reset, FlushE, - input logic [31:0] InstrD, - input logic [31:0] InstrE, InstrM, - output logic [31:0] InstrW, - output string InstrDName, InstrEName, InstrMName, InstrWName); + input logic clk, reset, + input logic [31:0] InstrF,InstrD,InstrE,InstrM,InstrW, + output string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // stage Instr to Writeback for visualization //flopr #(32) InstrWReg(clk, reset, InstrM, InstrW); + instrNameDecTB fdec(InstrF, InstrFName); instrNameDecTB ddec(InstrD, InstrDName); instrNameDecTB edec(InstrE, InstrEName); instrNameDecTB mdec(InstrM, InstrMName); From 31a03871367851f953b5eafb87e215de5cf52746 Mon Sep 17 00:00:00 2001 From: bbracker Date: Mon, 26 Apr 2021 08:00:17 -0400 Subject: [PATCH 54/55] merge cleanup; mem init is broken --- wally-pipelined/src/ifu/ifu.sv | 1 - wally-pipelined/testbench/testbench-imperas.sv | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 56f400a5..ad7deb76 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -81,7 +81,6 @@ module ifu ( logic [31:0] InstrRawD, InstrE, InstrW; localparam [31:0] nop = 32'h00000013; // instruction for NOP logic reset_q; // *** look at this later. - logic [`XLEN-1:0] PCPF; logic BPPredDirWrongE, BTBPredPCWrongE, RASPredPCWrongE, BPPredClassNonCFIWrongE; diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 6ddb59e3..c67e73a2 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -471,9 +471,10 @@ module testbench(); // the design. if (`XLEN == 32) meminit = 32'hFEDC0123; else meminit = 64'hFEDCBA9876543210; - for (i=MemStartAddr; i Date: Mon, 26 Apr 2021 10:44:27 -0500 Subject: [PATCH 55/55] Reverted back the exe2memfile.pl script changes. Something I changed broke the load tests. --- wally-pipelined/bin/exe2memfile.pl | 129 ++++++++--------------------- 1 file changed, 34 insertions(+), 95 deletions(-) diff --git a/wally-pipelined/bin/exe2memfile.pl b/wally-pipelined/bin/exe2memfile.pl index 8f210c95..79b975c7 100755 --- a/wally-pipelined/bin/exe2memfile.pl +++ b/wally-pipelined/bin/exe2memfile.pl @@ -18,7 +18,7 @@ my $maxaddress = 0; STDOUT->autoflush(1); # *** Ross Thompson I think there is a bug here needs to be +1 -print ("Processing $#ARGV memfiles: \n"); +print ("Processing $#ARGV memfiles: "); my $frac = $#ARGV/10; for(my $i=0; $i<=$#ARGV; $i++) { if ($i < 10 || $i % $frac == 0) { print ("$i ") }; @@ -40,113 +40,60 @@ for(my $i=0; $i<=$#ARGV; $i++) { if ($needsprocessing == 1) { open(FILE, $ofile) || die("Can't read $ofile"); my $mode = 0; # parse for code - my $section = ""; - my $data = ""; my $address; - my $first = 0; - my $firstAddress; # initialize to all zeros; - # *** need to fix the zeroing range. Not always 64K for (my $i=0; $i < 65536*4; $i++) { $memfilebytes[$i] = "00"; } while() { - # objdump fill is divided into several .sections of which only some we want to actually process. - # In general we want everything except the .comment and .*attributes - if (/Disassembly of section (.*):/) { - $section = $1; - print ("setting section to $section\n"); - } else { - # now check if the section is one we are interested in processing. - #if ($section ne ".comment" && $section ne ".riscv.attributes" && $section =~ /\.debug.*/) { - if ($section =~ "\.init|\.text|\..*data|\..*bss") { - # the structure is: possible space(s) hex number: possible space(s) hex number space(s) junk - # there are also lines we need to skip: possible space(s) hex number : - if (/^\s*([0-9A-Fa-f]{1,16}):\s+([0-9A-Fa-f]+).*$/) { - $address = &fixadr($1); - if ($first == 0) { - $first = 1; - $firstAddress = $address; - } - $data = $2; - &emitData($address, $data); - # my $len = length($data); - # for (my $i=0; $i<$len/2; $i++) { - # $memfilebytes[$address+$i] = substr($data, $len-2-2*$i, 2); - # } -# print ("Addr $address $data\n"); -# } elsif (/^\s*\.\.\./) { -# print ("Got ...\n"); -# } else { -# print ("No match\n"); - } - } - } -# # *** this mode stuff does not work if a section is missing or reordered. -# if ($mode == 0) { # Parse code -# # print("Examining $_\n"); -# if (/^\s*(\S{1,16}):\s+(\S+)\s+/) { -# $address = &fixadr($1); -# my $instr = $2; -# my $len = length($instr); -# for (my $i=0; $i<$len/2; $i++) { -# $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); -# } -# print ("address $address $instr\n"); -# } -# if (/Disassembly of section .data:/) { $mode = 1;} -# } elsif ($mode == 1) { # Parse data segment -# if (/^\s*(\S{1,16}):\s+(.*)/) { -# $address = &fixadr($1); -# # print "addresss $address maxaddress $maxaddress\n"; -# if ($address > $maxaddress) { $maxaddress = $address; } -# my $line = $2; -# # merge chunks with spaces -# # *** might need to change -# $line =~ s/(\S)\s(\S)/$1$2/g; -# # strip off comments -# $line =~ /^(\S*)/; -# $payload = $1; -# &emitData($address, $payload); -# } -# if (/Disassembly of section .comment:/) { $mode = 2; } -# } elsif ($mode == 2) { # parse the comment section -# if (/Disassembly of section .riscv.attributes:/) { $mode = 3; } -# } + if ($mode == 0) { # Parse code + # print("Examining $_\n"); + if (/^\s*(\S\S\S\S\S\S\S\S):\s+(\S+)\s+/) { + $address = &fixadr($1); + my $instr = $2; + my $len = length($instr); + for (my $i=0; $i<$len/2; $i++) { + $memfilebytes[$address+$i] = substr($instr, $len-2-2*$i, 2); + } + # print ("address $address $instr\n"); + } + if (/Disassembly of section .data:/) { $mode = 1;} + } elsif ($mode == 1) { # Parse data segment + if (/^\s*(\S\S\S\S\S\S\S\S):\s+(.*)/) { + $address = &fixadr($1); + # print "addresss $address maxaddress $maxaddress\n"; + if ($address > $maxaddress) { $maxaddress = $address; } + my $line = $2; + # merge chunks with spaces + $line =~ s/(\S)\s(\S)/$1$2/g; + # strip off comments + $line =~ /^(\S*)/; + $payload = $1; + &emitData($address, $payload); + } + if (/Disassembly of section .riscv.attributes:/) { $mode = 2; } + } } close(FILE); - $maxaddress = $address + 32; # pad some zeros at the end + $maxaddress += 32; # pad some zeros at the end # print to memory file - # *** this is a problem if ($fname =~ /rv32/) { open(MEMFILE, ">$memfile") || die("Can't write $memfile"); - for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 4) { + for (my $i=0; $i<= $maxaddress; $i = $i + 4) { for ($j=3; $j>=0; $j--) { - no warnings 'uninitialized'; - my $value = $memfilebytes[$i+$j]; - if ($value eq ""){ - print MEMFILE "00"; - } else { - print MEMFILE "$memfilebytes[$i+$j]"; - } + print MEMFILE "$memfilebytes[$i+$j]"; } print MEMFILE "\n"; } close(MEMFILE); } else { open(MEMFILE, ">$memfile") || die("Can't write $memfile"); - for (my $i=$firstAddress; $i<= $maxaddress; $i = $i + 8) { + for (my $i=0; $i<= $maxaddress; $i = $i + 8) { for ($j=7; $j>=0; $j--) { - no warnings 'uninitialized'; - my $value = $memfilebytes[$i+$j]; - if ($value eq ""){ - print MEMFILE "00"; - } else { - print MEMFILE "$memfilebytes[$i+$j]"; - } + print MEMFILE "$memfilebytes[$i+$j]"; } print MEMFILE "\n"; } @@ -186,15 +133,7 @@ sub emitData { sub fixadr { # strip off leading 8 from address and convert to decimal - # if the leading 8 is not present don't remove. my $adr = shift; - #print "addr $adr\n"; - - # start at 0 - #return hex($adr); - - # start at 8 if ($adr =~ s/^8/0/) { return hex($adr); } - else { return hex($adr) } - + else { die("address $adr lacks leading 8\n"); } }