@ -0,0 +1,3 @@ | |||||
cmake-build-debug | |||||
build | |||||
.idea |
@ -0,0 +1,16 @@ | |||||
cmake_minimum_required(VERSION 3.16) | |||||
project(CsappLearning C) | |||||
set(CMAKE_C_STANDARD 11) | |||||
set(BUILD_PATH ${CMAKE_SOURCE_DIR}/build) # 自定义路径变量 | |||||
set(LAB_PATH ${CMAKE_SOURCE_DIR}/labs) | |||||
set(EXECUTABLE_OUTPUT_PATH ${BUILD_PATH}) # EXE | |||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BUILD_PATH}) # LIB | |||||
add_executable(TestQuiz quiz/test_quiz.c) | |||||
if(CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug")) | |||||
add_definitions(-DDEBUG) | |||||
endif() |
@ -0,0 +1,20 @@ | |||||
# CsappLearning | |||||
这是一个本人学习 csapp 的 learning 库 | |||||
其中包括: | |||||
* labs - csapp 的各项来自官网的 lab | |||||
* quiz - csapp 的部分练习与课堂作业 | |||||
* csapp.txt - 由本人 E-note 项目生成的笔记 | |||||
各 lab 得分 | |||||
* Datalab - 62 / 62 | |||||
* 项目目录下运行 ```./labs/data_lab/driver.pl -u GentleCold``` | |||||
注: | |||||
* 本人运行环境: WINDOWS10 - WSL2 | |||||
* 各 lab 由其自带的 Makefile 编译 | |||||
* ~~但为了保证 linux 环境,使用 cmake 调用 make 编译~~ | |||||
* cmake 调用失败,使用 wsl shell 手动 make | |||||
* quiz 由本人编写的 CMakeLists 编译 | |||||
* 所有 lab 尽可能的不参考他人代码,参考处会有 //TODO 标记 |
@ -0,0 +1,28 @@ | |||||
This file contains materials for one instance of the attacklab. | |||||
Files: | |||||
ctarget | |||||
Linux binary with code-injection vulnerability. To be used for phases | |||||
1-3 of the assignment. | |||||
rtarget | |||||
Linux binary with return-oriented programming vulnerability. To be | |||||
used for phases 4-5 of the assignment. | |||||
cookie.txt | |||||
Text file containing 4-byte signature required for this lab instance. | |||||
farm.c | |||||
Source code for gadget farm present in this instance of rtarget. You | |||||
can compile (use flag -Og) and disassemble it to look for gadgets. | |||||
hex2raw | |||||
Utility program to generate byte sequences. See documentation in lab | |||||
handout. | |||||
@ -0,0 +1 @@ | |||||
0x59b997fa |
@ -0,0 +1,223 @@ | |||||
/* This function marks the start of the farm */ | |||||
int start_farm() | |||||
{ | |||||
return 1; | |||||
} | |||||
unsigned getval_142() | |||||
{ | |||||
return 2425387259U; | |||||
} | |||||
unsigned addval_273(unsigned x) | |||||
{ | |||||
return x + 3284633928U; | |||||
} | |||||
unsigned addval_219(unsigned x) | |||||
{ | |||||
return x + 2421715793U; | |||||
} | |||||
void setval_237(unsigned *p) | |||||
{ | |||||
*p = 3351742792U; | |||||
} | |||||
void setval_424(unsigned *p) | |||||
{ | |||||
*p = 2455290452U; | |||||
} | |||||
void setval_470(unsigned *p) | |||||
{ | |||||
*p = 3347925091U; | |||||
} | |||||
void setval_426(unsigned *p) | |||||
{ | |||||
*p = 2428995912U; | |||||
} | |||||
unsigned getval_280() | |||||
{ | |||||
return 3281016873U; | |||||
} | |||||
/* This function marks the middle of the farm */ | |||||
int mid_farm() | |||||
{ | |||||
return 1; | |||||
} | |||||
/* Add two arguments */ | |||||
long add_xy(long x, long y) | |||||
{ | |||||
return x+y; | |||||
} | |||||
unsigned getval_481() | |||||
{ | |||||
return 2428668252U; | |||||
} | |||||
void setval_296(unsigned *p) | |||||
{ | |||||
*p = 2425409945U; | |||||
} | |||||
unsigned addval_113(unsigned x) | |||||
{ | |||||
return x + 3380137609U; | |||||
} | |||||
unsigned addval_490(unsigned x) | |||||
{ | |||||
return x + 3676361101U; | |||||
} | |||||
unsigned getval_226() | |||||
{ | |||||
return 3225997705U; | |||||
} | |||||
void setval_384(unsigned *p) | |||||
{ | |||||
*p = 3229929857U; | |||||
} | |||||
unsigned addval_190(unsigned x) | |||||
{ | |||||
return x + 3767093313U; | |||||
} | |||||
void setval_276(unsigned *p) | |||||
{ | |||||
*p = 3372794504U; | |||||
} | |||||
unsigned addval_436(unsigned x) | |||||
{ | |||||
return x + 2425409161U; | |||||
} | |||||
unsigned getval_345() | |||||
{ | |||||
return 3252717896U; | |||||
} | |||||
unsigned addval_479(unsigned x) | |||||
{ | |||||
return x + 3372270217U; | |||||
} | |||||
unsigned addval_187(unsigned x) | |||||
{ | |||||
return x + 3224948361U; | |||||
} | |||||
void setval_248(unsigned *p) | |||||
{ | |||||
*p = 3674787457U; | |||||
} | |||||
unsigned getval_159() | |||||
{ | |||||
return 3375944073U; | |||||
} | |||||
unsigned addval_110(unsigned x) | |||||
{ | |||||
return x + 3286272456U; | |||||
} | |||||
unsigned addval_487(unsigned x) | |||||
{ | |||||
return x + 3229926025U; | |||||
} | |||||
unsigned addval_201(unsigned x) | |||||
{ | |||||
return x + 3353381192U; | |||||
} | |||||
unsigned getval_272() | |||||
{ | |||||
return 3523793305U; | |||||
} | |||||
unsigned getval_155() | |||||
{ | |||||
return 3385115273U; | |||||
} | |||||
void setval_299(unsigned *p) | |||||
{ | |||||
*p = 2447411528U; | |||||
} | |||||
unsigned addval_404(unsigned x) | |||||
{ | |||||
return x + 3281178249U; | |||||
} | |||||
unsigned getval_311() | |||||
{ | |||||
return 3674788233U; | |||||
} | |||||
void setval_167(unsigned *p) | |||||
{ | |||||
*p = 3281113481U; | |||||
} | |||||
void setval_328(unsigned *p) | |||||
{ | |||||
*p = 3526935169U; | |||||
} | |||||
void setval_450(unsigned *p) | |||||
{ | |||||
*p = 3372797449U; | |||||
} | |||||
unsigned addval_358(unsigned x) | |||||
{ | |||||
return x + 2430634248U; | |||||
} | |||||
unsigned addval_124(unsigned x) | |||||
{ | |||||
return x + 1019724425U; | |||||
} | |||||
unsigned getval_169() | |||||
{ | |||||
return 3223375496U; | |||||
} | |||||
void setval_181(unsigned *p) | |||||
{ | |||||
*p = 3269495112U; | |||||
} | |||||
unsigned addval_184(unsigned x) | |||||
{ | |||||
return x + 3529556617U; | |||||
} | |||||
unsigned getval_472() | |||||
{ | |||||
return 3525365389U; | |||||
} | |||||
void setval_350(unsigned *p) | |||||
{ | |||||
*p = 2430634312U; | |||||
} | |||||
/* This function marks the end of the farm */ | |||||
int end_farm() | |||||
{ | |||||
return 1; | |||||
} |
@ -0,0 +1,33 @@ | |||||
# | |||||
# Student makefile for Cache Lab | |||||
# Note: requires a 64-bit x86-64 system | |||||
# | |||||
CC = gcc | |||||
CFLAGS = -g -Wall -Werror -std=c99 -m64 | |||||
all: csim test-trans tracegen | |||||
# Generate a handin tar file each time you compile | |||||
-tar -cvf ${USER}-handin.tar csim.c trans.c | |||||
csim: csim.c cachelab.c cachelab.h | |||||
$(CC) $(CFLAGS) -o csim csim.c cachelab.c -lm | |||||
test-trans: test-trans.c trans.o cachelab.c cachelab.h | |||||
$(CC) $(CFLAGS) -o test-trans test-trans.c cachelab.c trans.o | |||||
tracegen: tracegen.c trans.o cachelab.c | |||||
$(CC) $(CFLAGS) -O0 -o tracegen tracegen.c trans.o cachelab.c | |||||
trans.o: trans.c | |||||
$(CC) $(CFLAGS) -O0 -c trans.c | |||||
# | |||||
# Clean the src dirctory | |||||
# | |||||
clean: | |||||
rm -rf *.o | |||||
rm -f *.tar | |||||
rm -f csim | |||||
rm -f test-trans tracegen | |||||
rm -f trace.all trace.f* | |||||
rm -f .csim_results .marker |
@ -0,0 +1,39 @@ | |||||
This is the handout directory for the CS:APP Cache Lab. | |||||
************************ | |||||
Running the autograders: | |||||
************************ | |||||
Before running the autograders, compile your code: | |||||
linux> make | |||||
Check the correctness of your simulator: | |||||
linux> ./test-csim | |||||
Check the correctness and performance of your transpose functions: | |||||
linux> ./test-trans -M 32 -N 32 | |||||
linux> ./test-trans -M 64 -N 64 | |||||
linux> ./test-trans -M 61 -N 67 | |||||
Check everything at once (this is the program that your instructor runs): | |||||
linux> ./driver.py | |||||
****** | |||||
Files: | |||||
****** | |||||
# You will modifying and handing in these two files | |||||
csim.c Your cache simulator | |||||
trans.c Your transpose function | |||||
# Tools for evaluating your simulator and transpose function | |||||
Makefile Builds the simulator and tools | |||||
README This file | |||||
driver.py* The driver program, runs test-csim and test-trans | |||||
cachelab.c Required helper functions | |||||
cachelab.h Required header file | |||||
csim-ref* The executable reference cache simulator | |||||
test-csim* Tests your cache simulator | |||||
test-trans.c Tests your transpose function | |||||
tracegen.c Helper program used by test-trans | |||||
traces/ Trace files used by test-csim.c |
@ -0,0 +1,83 @@ | |||||
/* | |||||
* cachelab.c - Cache Lab helper functions | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <assert.h> | |||||
#include "cachelab.h" | |||||
#include <time.h> | |||||
trans_func_t func_list[MAX_TRANS_FUNCS]; | |||||
int func_counter = 0; | |||||
/* | |||||
* printSummary - Summarize the cache simulation statistics. Student cache simulators | |||||
* must call this function in order to be properly autograded. | |||||
*/ | |||||
void printSummary(int hits, int misses, int evictions) | |||||
{ | |||||
printf("hits:%d misses:%d evictions:%d\n", hits, misses, evictions); | |||||
FILE* output_fp = fopen(".csim_results", "w"); | |||||
assert(output_fp); | |||||
fprintf(output_fp, "%d %d %d\n", hits, misses, evictions); | |||||
fclose(output_fp); | |||||
} | |||||
/* | |||||
* initMatrix - Initialize the given matrix | |||||
*/ | |||||
void initMatrix(int M, int N, int A[N][M], int B[M][N]) | |||||
{ | |||||
int i, j; | |||||
srand(time(NULL)); | |||||
for (i = 0; i < N; i++){ | |||||
for (j = 0; j < M; j++){ | |||||
// A[i][j] = i+j; /* The matrix created this way is symmetric */ | |||||
A[i][j]=rand(); | |||||
B[j][i]=rand(); | |||||
} | |||||
} | |||||
} | |||||
void randMatrix(int M, int N, int A[N][M]) { | |||||
int i, j; | |||||
srand(time(NULL)); | |||||
for (i = 0; i < N; i++){ | |||||
for (j = 0; j < M; j++){ | |||||
// A[i][j] = i+j; /* The matrix created this way is symmetric */ | |||||
A[i][j]=rand(); | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* correctTrans - baseline transpose function used to evaluate correctness | |||||
*/ | |||||
void correctTrans(int M, int N, int A[N][M], int B[M][N]) | |||||
{ | |||||
int i, j, tmp; | |||||
for (i = 0; i < N; i++){ | |||||
for (j = 0; j < M; j++){ | |||||
tmp = A[i][j]; | |||||
B[j][i] = tmp; | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* registerTransFunction - Add the given trans function into your list | |||||
* of functions to be tested | |||||
*/ | |||||
void registerTransFunction(void (*trans)(int M, int N, int[N][M], int[M][N]), | |||||
char* desc) | |||||
{ | |||||
func_list[func_counter].func_ptr = trans; | |||||
func_list[func_counter].description = desc; | |||||
func_list[func_counter].correct = 0; | |||||
func_list[func_counter].num_hits = 0; | |||||
func_list[func_counter].num_misses = 0; | |||||
func_list[func_counter].num_evictions =0; | |||||
func_counter++; | |||||
} |
@ -0,0 +1,37 @@ | |||||
/* | |||||
* cachelab.h - Prototypes for Cache Lab helper functions | |||||
*/ | |||||
#ifndef CACHELAB_TOOLS_H | |||||
#define CACHELAB_TOOLS_H | |||||
#define MAX_TRANS_FUNCS 100 | |||||
typedef struct trans_func{ | |||||
void (*func_ptr)(int M,int N,int[N][M],int[M][N]); | |||||
char* description; | |||||
char correct; | |||||
unsigned int num_hits; | |||||
unsigned int num_misses; | |||||
unsigned int num_evictions; | |||||
} trans_func_t; | |||||
/* | |||||
* printSummary - This function provides a standard way for your cache | |||||
* simulator * to display its final hit and miss statistics | |||||
*/ | |||||
void printSummary(int hits, /* number of hits */ | |||||
int misses, /* number of misses */ | |||||
int evictions); /* number of evictions */ | |||||
/* Fill the matrix with data */ | |||||
void initMatrix(int M, int N, int A[N][M], int B[M][N]); | |||||
/* The baseline trans function that produces correct results. */ | |||||
void correctTrans(int M, int N, int A[N][M], int B[M][N]); | |||||
/* Add the given function to the function list */ | |||||
void registerTransFunction( | |||||
void (*trans)(int M,int N,int[N][M],int[M][N]), char* desc); | |||||
#endif /* CACHELAB_TOOLS_H */ |
@ -0,0 +1,7 @@ | |||||
#include "cachelab.h" | |||||
int main() | |||||
{ | |||||
printSummary(0, 0, 0); | |||||
return 0; | |||||
} |
@ -0,0 +1,138 @@ | |||||
#!/usr//bin/python | |||||
# | |||||
# driver.py - The driver tests the correctness of the student's cache | |||||
# simulator and the correctness and performance of their transpose | |||||
# function. It uses ./test-csim to check the correctness of the | |||||
# simulator and it runs ./test-trans on three different sized | |||||
# matrices (32x32, 64x64, and 61x67) to test the correctness and | |||||
# performance of the transpose function. | |||||
# | |||||
import subprocess; | |||||
import re; | |||||
import os; | |||||
import sys; | |||||
import optparse; | |||||
# | |||||
# computeMissScore - compute the score depending on the number of | |||||
# cache misses | |||||
# | |||||
def computeMissScore(miss, lower, upper, full_score): | |||||
if miss <= lower: | |||||
return full_score | |||||
if miss >= upper: | |||||
return 0 | |||||
score = (miss - lower) * 1.0 | |||||
range = (upper- lower) * 1.0 | |||||
return round((1 - score / range) * full_score, 1) | |||||
# | |||||
# main - Main function | |||||
# | |||||
def main(): | |||||
# Configure maxscores here | |||||
maxscore= {}; | |||||
maxscore['csim'] = 27 | |||||
maxscore['transc'] = 1 | |||||
maxscore['trans32'] = 8 | |||||
maxscore['trans64'] = 8 | |||||
maxscore['trans61'] = 10 | |||||
# Parse the command line arguments | |||||
p = optparse.OptionParser() | |||||
p.add_option("-A", action="store_true", dest="autograde", | |||||
help="emit autoresult string for Autolab"); | |||||
opts, args = p.parse_args() | |||||
autograde = opts.autograde | |||||
# Check the correctness of the cache simulator | |||||
print "Part A: Testing cache simulator" | |||||
print "Running ./test-csim" | |||||
p = subprocess.Popen("./test-csim", | |||||
shell=True, stdout=subprocess.PIPE) | |||||
stdout_data = p.communicate()[0] | |||||
# Emit the output from test-csim | |||||
stdout_data = re.split('\n', stdout_data) | |||||
for line in stdout_data: | |||||
if re.match("TEST_CSIM_RESULTS", line): | |||||
resultsim = re.findall(r'(\d+)', line) | |||||
else: | |||||
print "%s" % (line) | |||||
# Check the correctness and performance of the transpose function | |||||
# 32x32 transpose | |||||
print "Part B: Testing transpose function" | |||||
print "Running ./test-trans -M 32 -N 32" | |||||
p = subprocess.Popen("./test-trans -M 32 -N 32 | grep TEST_TRANS_RESULTS", | |||||
shell=True, stdout=subprocess.PIPE) | |||||
stdout_data = p.communicate()[0] | |||||
result32 = re.findall(r'(\d+)', stdout_data) | |||||
# 64x64 transpose | |||||
print "Running ./test-trans -M 64 -N 64" | |||||
p = subprocess.Popen("./test-trans -M 64 -N 64 | grep TEST_TRANS_RESULTS", | |||||
shell=True, stdout=subprocess.PIPE) | |||||
stdout_data = p.communicate()[0] | |||||
result64 = re.findall(r'(\d+)', stdout_data) | |||||
# 61x67 transpose | |||||
print "Running ./test-trans -M 61 -N 67" | |||||
p = subprocess.Popen("./test-trans -M 61 -N 67 | grep TEST_TRANS_RESULTS", | |||||
shell=True, stdout=subprocess.PIPE) | |||||
stdout_data = p.communicate()[0] | |||||
result61 = re.findall(r'(\d+)', stdout_data) | |||||
# Compute the scores for each step | |||||
csim_cscore = map(int, resultsim[0:1]) | |||||
trans_cscore = int(result32[0]) * int(result64[0]) * int(result61[0]); | |||||
miss32 = int(result32[1]) | |||||
miss64 = int(result64[1]) | |||||
miss61 = int(result61[1]) | |||||
trans32_score = computeMissScore(miss32, 300, 600, maxscore['trans32']) * int(result32[0]) | |||||
trans64_score = computeMissScore(miss64, 1300, 2000, maxscore['trans64']) * int(result64[0]) | |||||
trans61_score = computeMissScore(miss61, 2000, 3000, maxscore['trans61']) * int(result61[0]) | |||||
total_score = csim_cscore[0] + trans32_score + trans64_score + trans61_score | |||||
# Summarize the results | |||||
print "\nCache Lab summary:" | |||||
print "%-22s%8s%10s%12s" % ("", "Points", "Max pts", "Misses") | |||||
print "%-22s%8.1f%10d" % ("Csim correctness", csim_cscore[0], | |||||
maxscore['csim']) | |||||
misses = str(miss32) | |||||
if miss32 == 2**31-1 : | |||||
misses = "invalid" | |||||
print "%-22s%8.1f%10d%12s" % ("Trans perf 32x32", trans32_score, | |||||
maxscore['trans32'], misses) | |||||
misses = str(miss64) | |||||
if miss64 == 2**31-1 : | |||||
misses = "invalid" | |||||
print "%-22s%8.1f%10d%12s" % ("Trans perf 64x64", trans64_score, | |||||
maxscore['trans64'], misses) | |||||
misses = str(miss61) | |||||
if miss61 == 2**31-1 : | |||||
misses = "invalid" | |||||
print "%-22s%8.1f%10d%12s" % ("Trans perf 61x67", trans61_score, | |||||
maxscore['trans61'], misses) | |||||
print "%22s%8.1f%10d" % ("Total points", total_score, | |||||
maxscore['csim'] + | |||||
maxscore['trans32'] + | |||||
maxscore['trans64'] + | |||||
maxscore['trans61']) | |||||
# Emit autoresult string for Autolab if called with -A option | |||||
if autograde: | |||||
autoresult="%.1f:%d:%d:%d" % (total_score, miss32, miss64, miss61) | |||||
print "\nAUTORESULT_STRING=%s" % autoresult | |||||
# execute main only if called as a script | |||||
if __name__ == "__main__": | |||||
main() | |||||
@ -0,0 +1,261 @@ | |||||
/* | |||||
* test-trans.c - Checks the correctness and performance of all of the | |||||
* student's transpose functions and records the results for their | |||||
* official submitted version as well. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <assert.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <signal.h> | |||||
#include <getopt.h> | |||||
#include <sys/types.h> | |||||
#include "cachelab.h" | |||||
#include <sys/wait.h> // fir WEXITSTATUS | |||||
#include <limits.h> // for INT_MAX | |||||
/* Maximum array dimension */ | |||||
#define MAXN 256 | |||||
/* The description string for the transpose_submit() function that the | |||||
student submits for credit */ | |||||
#define SUBMIT_DESCRIPTION "Transpose submission" | |||||
/* External function defined in trans.c */ | |||||
extern void registerFunctions(); | |||||
/* External variables defined in cachelab-tools.c */ | |||||
extern trans_func_t func_list[MAX_TRANS_FUNCS]; | |||||
extern int func_counter; | |||||
/* Globals set on the command line */ | |||||
static int M = 0; | |||||
static int N = 0; | |||||
/* The correctness and performance for the submitted transpose function */ | |||||
struct results { | |||||
int funcid; | |||||
int correct; | |||||
int misses; | |||||
}; | |||||
static struct results results = {-1, 0, INT_MAX}; | |||||
/* | |||||
* eval_perf - Evaluate the performance of the registered transpose functions | |||||
*/ | |||||
void eval_perf(unsigned int s, unsigned int E, unsigned int b) | |||||
{ | |||||
int i,flag; | |||||
unsigned int len, hits, misses, evictions; | |||||
unsigned long long int marker_start, marker_end, addr; | |||||
char buf[1000], cmd[255]; | |||||
char filename[128]; | |||||
registerFunctions(); | |||||
/* Open the complete trace file */ | |||||
FILE* full_trace_fp; | |||||
FILE* part_trace_fp; | |||||
/* Evaluate the performance of each registered transpose function */ | |||||
for (i=0; i<func_counter; i++) { | |||||
if (strcmp(func_list[i].description, SUBMIT_DESCRIPTION) == 0 ) | |||||
results.funcid = i; /* remember which function is the submission */ | |||||
printf("\nFunction %d (%d total)\nStep 1: Validating and generating memory traces\n",i,func_counter); | |||||
/* Use valgrind to generate the trace */ | |||||
sprintf(cmd, "valgrind --tool=lackey --trace-mem=yes --log-fd=1 -v ./tracegen -M %d -N %d -F %d > trace.tmp", M, N,i); | |||||
flag=WEXITSTATUS(system(cmd)); | |||||
if (0!=flag) { | |||||
printf("Validation error at function %d! Run ./tracegen -M %d -N %d -F %d for details.\nSkipping performance evaluation for this function.\n",flag-1,M,N,i); | |||||
continue; | |||||
} | |||||
/* Get the start and end marker addresses */ | |||||
FILE* marker_fp = fopen(".marker", "r"); | |||||
assert(marker_fp); | |||||
fscanf(marker_fp, "%llx %llx", &marker_start, &marker_end); | |||||
fclose(marker_fp); | |||||
func_list[i].correct=1; | |||||
/* Save the correctness of the transpose submission */ | |||||
if (results.funcid == i ) { | |||||
results.correct = 1; | |||||
} | |||||
full_trace_fp = fopen("trace.tmp", "r"); | |||||
assert(full_trace_fp); | |||||
/* Filtered trace for each transpose function goes in a separate file */ | |||||
sprintf(filename, "trace.f%d", i); | |||||
part_trace_fp = fopen(filename, "w"); | |||||
assert(part_trace_fp); | |||||
/* Locate trace corresponding to the trans function */ | |||||
flag = 0; | |||||
while (fgets(buf, 1000, full_trace_fp) != NULL) { | |||||
/* We are only interested in memory access instructions */ | |||||
if (buf[0]==' ' && buf[2]==' ' && | |||||
(buf[1]=='S' || buf[1]=='M' || buf[1]=='L' )) { | |||||
sscanf(buf+3, "%llx,%u", &addr, &len); | |||||
/* If start marker found, set flag */ | |||||
if (addr == marker_start) | |||||
flag = 1; | |||||
/* Valgrind creates many spurious accesses to the | |||||
stack that have nothing to do with the students | |||||
code. At the moment, we are ignoring all stack | |||||
accesses by using the simple filter of recording | |||||
accesses to only the low 32-bit portion of the | |||||
address space. At some point it would be nice to | |||||
try to do more informed filtering so that would | |||||
eliminate the valgrind stack references while | |||||
include the student stack references. */ | |||||
if (flag && addr < 0xffffffff) { | |||||
fputs(buf, part_trace_fp); | |||||
} | |||||
/* if end marker found, close trace file */ | |||||
if (addr == marker_end) { | |||||
flag = 0; | |||||
fclose(part_trace_fp); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
fclose(full_trace_fp); | |||||
/* Run the reference simulator */ | |||||
printf("Step 2: Evaluating performance (s=%d, E=%d, b=%d)\n", s, E, b); | |||||
char cmd[255]; | |||||
sprintf(cmd, "./csim-ref -s %u -E %u -b %u -t trace.f%d > /dev/null", | |||||
s, E, b, i); | |||||
system(cmd); | |||||
/* Collect results from the reference simulator */ | |||||
FILE* in_fp = fopen(".csim_results","r"); | |||||
assert(in_fp); | |||||
fscanf(in_fp, "%u %u %u", &hits, &misses, &evictions); | |||||
fclose(in_fp); | |||||
func_list[i].num_hits = hits; | |||||
func_list[i].num_misses = misses; | |||||
func_list[i].num_evictions = evictions; | |||||
printf("func %u (%s): hits:%u, misses:%u, evictions:%u\n", | |||||
i, func_list[i].description, hits, misses, evictions); | |||||
/* If it is transpose_submit(), record number of misses */ | |||||
if (results.funcid == i) { | |||||
results.misses = misses; | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* usage - Print usage info | |||||
*/ | |||||
void usage(char *argv[]){ | |||||
printf("Usage: %s [-h] -M <rows> -N <cols>\n", argv[0]); | |||||
printf("Options:\n"); | |||||
printf(" -h Print this help message.\n"); | |||||
printf(" -M <rows> Number of matrix rows (max %d)\n", MAXN); | |||||
printf(" -N <cols> Number of matrix columns (max %d)\n", MAXN); | |||||
printf("Example: %s -M 8 -N 8\n", argv[0]); | |||||
} | |||||
/* | |||||
* sigsegv_handler - SIGSEGV handler | |||||
*/ | |||||
void sigsegv_handler(int signum){ | |||||
printf("Error: Segmentation Fault.\n"); | |||||
printf("TEST_TRANS_RESULTS=0:0\n"); | |||||
fflush(stdout); | |||||
exit(1); | |||||
} | |||||
/* | |||||
* sigalrm_handler - SIGALRM handler | |||||
*/ | |||||
void sigalrm_handler(int signum){ | |||||
printf("Error: Program timed out.\n"); | |||||
printf("TEST_TRANS_RESULTS=0:0\n"); | |||||
fflush(stdout); | |||||
exit(1); | |||||
} | |||||
/* | |||||
* main - Main routine | |||||
*/ | |||||
int main(int argc, char* argv[]) | |||||
{ | |||||
char c; | |||||
while ((c = getopt(argc,argv,"M:N:h")) != -1) { | |||||
switch(c) { | |||||
case 'M': | |||||
M = atoi(optarg); | |||||
break; | |||||
case 'N': | |||||
N = atoi(optarg); | |||||
break; | |||||
case 'h': | |||||
usage(argv); | |||||
exit(0); | |||||
default: | |||||
usage(argv); | |||||
exit(1); | |||||
} | |||||
} | |||||
if (M == 0 || N == 0) { | |||||
printf("Error: Missing required argument\n"); | |||||
usage(argv); | |||||
exit(1); | |||||
} | |||||
if (M > MAXN || N > MAXN) { | |||||
printf("Error: M or N exceeds %d\n", MAXN); | |||||
usage(argv); | |||||
exit(1); | |||||
} | |||||
/* Install SIGSEGV and SIGALRM handlers */ | |||||
if (signal(SIGSEGV, sigsegv_handler) == SIG_ERR) { | |||||
fprintf(stderr, "Unable to install SIGALRM handler\n"); | |||||
exit(1); | |||||
} | |||||
if (signal(SIGALRM, sigalrm_handler) == SIG_ERR) { | |||||
fprintf(stderr, "Unable to install SIGALRM handler\n"); | |||||
exit(1); | |||||
} | |||||
/* Time out and give up after a while */ | |||||
alarm(120); | |||||
/* Check the performance of the student's transpose function */ | |||||
eval_perf(5, 1, 5); | |||||
/* Emit the results for this particular test */ | |||||
if (results.funcid == -1) { | |||||
printf("\nError: We could not find your transpose_submit() function\n"); | |||||
printf("Error: Please ensure that description field is exactly \"%s\"\n", | |||||
SUBMIT_DESCRIPTION); | |||||
printf("\nTEST_TRANS_RESULTS=0:0\n"); | |||||
} | |||||
else { | |||||
printf("\nSummary for official submission (func %d): correctness=%d misses=%d\n", | |||||
results.funcid, results.correct, results.misses); | |||||
printf("\nTEST_TRANS_RESULTS=%d:%d\n", results.correct, results.misses); | |||||
} | |||||
return 0; | |||||
} |
@ -0,0 +1,107 @@ | |||||
/* | |||||
* tracegen.c - Running the binary tracegen with valgrind produces | |||||
* a memory trace of all of the registered transpose functions. | |||||
* | |||||
* The beginning and end of each registered transpose function's trace | |||||
* is indicated by reading from "marker" addresses. These two marker | |||||
* addresses are recorded in file for later use. | |||||
*/ | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <assert.h> | |||||
#include <unistd.h> | |||||
#include <getopt.h> | |||||
#include "cachelab.h" | |||||
#include <string.h> | |||||
/* External variables declared in cachelab.c */ | |||||
extern trans_func_t func_list[MAX_TRANS_FUNCS]; | |||||
extern int func_counter; | |||||
/* External function from trans.c */ | |||||
extern void registerFunctions(); | |||||
/* Markers used to bound trace regions of interest */ | |||||
volatile char MARKER_START, MARKER_END; | |||||
static int A[256][256]; | |||||
static int B[256][256]; | |||||
static int M; | |||||
static int N; | |||||
int validate(int fn,int M, int N, int A[N][M], int B[M][N]) { | |||||
int C[M][N]; | |||||
memset(C,0,sizeof(C)); | |||||
correctTrans(M,N,A,C); | |||||
for(int i=0;i<M;i++) { | |||||
for(int j=0;j<N;j++) { | |||||
if(B[i][j]!=C[i][j]) { | |||||
printf("Validation failed on function %d! Expected %d but got %d at B[%d][%d]\n",fn,C[i][j],B[i][j],i,j); | |||||
return 0; | |||||
} | |||||
} | |||||
} | |||||
return 1; | |||||
} | |||||
int main(int argc, char* argv[]){ | |||||
int i; | |||||
char c; | |||||
int selectedFunc=-1; | |||||
while( (c=getopt(argc,argv,"M:N:F:")) != -1){ | |||||
switch(c){ | |||||
case 'M': | |||||
M = atoi(optarg); | |||||
break; | |||||
case 'N': | |||||
N = atoi(optarg); | |||||
break; | |||||
case 'F': | |||||
selectedFunc = atoi(optarg); | |||||
break; | |||||
case '?': | |||||
default: | |||||
printf("./tracegen failed to parse its options.\n"); | |||||
exit(1); | |||||
} | |||||
} | |||||
/* Register transpose functions */ | |||||
registerFunctions(); | |||||
/* Fill A with data */ | |||||
initMatrix(M,N, A, B); | |||||
/* Record marker addresses */ | |||||
FILE* marker_fp = fopen(".marker","w"); | |||||
assert(marker_fp); | |||||
fprintf(marker_fp, "%llx %llx", | |||||
(unsigned long long int) &MARKER_START, | |||||
(unsigned long long int) &MARKER_END ); | |||||
fclose(marker_fp); | |||||
if (-1==selectedFunc) { | |||||
/* Invoke registered transpose functions */ | |||||
for (i=0; i < func_counter; i++) { | |||||
MARKER_START = 33; | |||||
(*func_list[i].func_ptr)(M, N, A, B); | |||||
MARKER_END = 34; | |||||
if (!validate(i,M,N,A,B)) | |||||
return i+1; | |||||
} | |||||
} else { | |||||
MARKER_START = 33; | |||||
(*func_list[selectedFunc].func_ptr)(M, N, A, B); | |||||
MARKER_END = 34; | |||||
if (!validate(selectedFunc,M,N,A,B)) | |||||
return selectedFunc+1; | |||||
} | |||||
return 0; | |||||
} | |||||
@ -0,0 +1,5 @@ | |||||
L 10,4 | |||||
S 18,4 | |||||
L 20,4 | |||||
S 28,4 | |||||
S 50,4 |
@ -0,0 +1,596 @@ | |||||
S 00600aa0,1 | |||||
I 004005b6,5 | |||||
I 004005bb,5 | |||||
I 004005c0,5 | |||||
S 7ff000398,8 | |||||
I 0040051e,1 | |||||
S 7ff000390,8 | |||||
I 0040051f,3 | |||||
I 00400522,4 | |||||
S 7ff000378,8 | |||||
I 00400526,4 | |||||
S 7ff000370,8 | |||||
I 0040052a,7 | |||||
S 7ff000384,4 | |||||
I 00400531,2 | |||||
I 00400581,4 | |||||
L 7ff000384,4 | |||||
I 00400585,2 | |||||
I 00400533,7 | |||||
S 7ff000388,4 | |||||
I 0040053a,2 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a20,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a60,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a24,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a70,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a28,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a80,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a2c,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a90,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040057d,4 | |||||
M 7ff000384,4 | |||||
I 00400581,4 | |||||
L 7ff000384,4 | |||||
I 00400585,2 | |||||
I 00400533,7 | |||||
S 7ff000388,4 | |||||
I 0040053a,2 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a30,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a64,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a34,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a74,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a38,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a84,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a3c,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a94,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040057d,4 | |||||
M 7ff000384,4 | |||||
I 00400581,4 | |||||
L 7ff000384,4 | |||||
I 00400585,2 | |||||
I 00400533,7 | |||||
S 7ff000388,4 | |||||
I 0040053a,2 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a40,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a68,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a44,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a78,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a48,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a88,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a4c,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a98,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040057d,4 | |||||
M 7ff000384,4 | |||||
I 00400581,4 | |||||
L 7ff000384,4 | |||||
I 00400585,2 | |||||
I 00400533,7 | |||||
S 7ff000388,4 | |||||
I 0040053a,2 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a50,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a6c,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a54,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a7c,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a58,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a8c,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040053c,3 | |||||
L 7ff000384,4 | |||||
I 0040053f,2 | |||||
I 00400541,4 | |||||
I 00400545,3 | |||||
I 00400548,4 | |||||
L 7ff000378,8 | |||||
I 0040054c,3 | |||||
L 7ff000388,4 | |||||
I 0040054f,2 | |||||
I 00400551,3 | |||||
L 00600a5c,4 | |||||
I 00400554,3 | |||||
S 7ff00038c,4 | |||||
I 00400557,3 | |||||
L 7ff000388,4 | |||||
I 0040055a,2 | |||||
I 0040055c,4 | |||||
I 00400560,3 | |||||
I 00400563,4 | |||||
L 7ff000370,8 | |||||
I 00400567,3 | |||||
L 7ff000384,4 | |||||
I 0040056a,3 | |||||
I 0040056d,3 | |||||
L 7ff00038c,4 | |||||
I 00400570,3 | |||||
S 00600a9c,4 | |||||
I 00400573,4 | |||||
M 7ff000388,4 | |||||
I 00400577,4 | |||||
L 7ff000388,4 | |||||
I 0040057b,2 | |||||
I 0040057d,4 | |||||
M 7ff000384,4 | |||||
I 00400581,4 | |||||
L 7ff000384,4 | |||||
I 00400585,2 | |||||
I 00400587,1 | |||||
L 7ff000390,8 | |||||
I 00400588,1 | |||||
L 7ff000398,8 | |||||
I 004005c5,7 | |||||
L 00600aa0,1 |
@ -0,0 +1,7 @@ | |||||
L 10,1 | |||||
M 20,1 | |||||
L 22,1 | |||||
S 18,1 | |||||
L 110,1 | |||||
L 210,1 | |||||
M 12,1 |
@ -0,0 +1,16 @@ | |||||
L 0,1 | |||||
L 1,1 | |||||
L 2,1 | |||||
L 3,1 | |||||
S 4,1 | |||||
L 5,1 | |||||
S 6,1 | |||||
L 7,1 | |||||
S 8,1 | |||||
L 9,1 | |||||
S a,1 | |||||
L b,1 | |||||
S c,1 | |||||
L d,1 | |||||
S e,1 | |||||
M f,1 |
@ -0,0 +1,84 @@ | |||||
/* | |||||
* trans.c - Matrix transpose B = A^T | |||||
* | |||||
* Each transpose function must have a prototype of the form: | |||||
* void trans(int M, int N, int A[N][M], int B[M][N]); | |||||
* | |||||
* A transpose function is evaluated by counting the number of misses | |||||
* on a 1KB direct mapped cache with a block size of 32 bytes. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include "cachelab.h" | |||||
int is_transpose(int M, int N, int A[N][M], int B[M][N]); | |||||
/* | |||||
* transpose_submit - This is the solution transpose function that you | |||||
* will be graded on for Part B of the assignment. Do not change | |||||
* the description string "Transpose submission", as the driver | |||||
* searches for that string to identify the transpose function to | |||||
* be graded. | |||||
*/ | |||||
char transpose_submit_desc[] = "Transpose submission"; | |||||
void transpose_submit(int M, int N, int A[N][M], int B[M][N]) | |||||
{ | |||||
} | |||||
/* | |||||
* You can define additional transpose functions below. We've defined | |||||
* a simple one below to help you get started. | |||||
*/ | |||||
/* | |||||
* trans - A simple baseline transpose function, not optimized for the cache. | |||||
*/ | |||||
char trans_desc[] = "Simple row-wise scan transpose"; | |||||
void trans(int M, int N, int A[N][M], int B[M][N]) | |||||
{ | |||||
int i, j, tmp; | |||||
for (i = 0; i < N; i++) { | |||||
for (j = 0; j < M; j++) { | |||||
tmp = A[i][j]; | |||||
B[j][i] = tmp; | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
* registerFunctions - This function registers your transpose | |||||
* functions with the driver. At runtime, the driver will | |||||
* evaluate each of the registered functions and summarize their | |||||
* performance. This is a handy way to experiment with different | |||||
* transpose strategies. | |||||
*/ | |||||
void registerFunctions() | |||||
{ | |||||
/* Register your solution function */ | |||||
registerTransFunction(transpose_submit, transpose_submit_desc); | |||||
/* Register any additional transpose functions */ | |||||
registerTransFunction(trans, trans_desc); | |||||
} | |||||
/* | |||||
* is_transpose - This helper function checks if B is the transpose of | |||||
* A. You can check the correctness of your transpose by calling | |||||
* it before returning from the transpose function. | |||||
*/ | |||||
int is_transpose(int M, int N, int A[N][M], int B[M][N]) | |||||
{ | |||||
int i, j; | |||||
for (i = 0; i < N; i++) { | |||||
for (j = 0; j < M; ++j) { | |||||
if (A[i][j] != B[j][i]) { | |||||
return 0; | |||||
} | |||||
} | |||||
} | |||||
return 1; | |||||
} | |||||
@ -0,0 +1,12 @@ | |||||
# | |||||
# This file contains configuration variables for drivers. | |||||
# It was generated by genhdrs.pl. Do not modify it. | |||||
# | |||||
package Driverhdrs; | |||||
$LAB = "datalab"; | |||||
$SERVER_NAME = "changeme.ics.cs.cmu.edu"; | |||||
$SERVER_PORT = 8081; | |||||
$COURSE_NAME = "csapp"; | |||||
$AUTOGRADE_TIMEOUT = 0; | |||||
1; |
@ -0,0 +1,138 @@ | |||||
############################################################### | |||||
# Driverlib.pm - A package of helper functions for Perl drivers | |||||
# | |||||
# Copyright (c) 2005 David R. O'Hallaron, All rights reserved. | |||||
############################################################### | |||||
package Driverlib; | |||||
use Socket; | |||||
# Autogenerated header file with lab-specific constants | |||||
use lib "."; | |||||
use Driverhdrs; | |||||
require Exporter; | |||||
@ISA = qw(Exporter); | |||||
@EXPORT = qw( | |||||
driver_post | |||||
); | |||||
use strict; | |||||
##### | |||||
# Public functions | |||||
# | |||||
# | |||||
# driver_post - This is the routine that a driver calls when | |||||
# it needs to transmit an autoresult string to the result server. | |||||
# | |||||
sub driver_post ($$) { | |||||
my $userid = shift; # User id for this submission | |||||
my $result = shift; # Autoresult string | |||||
my $autograded = shift; # Set if called by an autograder | |||||
# Echo the autoresult string to stdout if the driver was called | |||||
# by an autograder | |||||
if ($autograded) { | |||||
print "\n"; | |||||
print "AUTORESULT_STRING=$result\n"; | |||||
return; | |||||
} | |||||
# If the driver was called with a specific userid, then submit | |||||
# the autoresult string to the result server over the Internet. | |||||
if ($userid) { | |||||
my $status = submitr($Driverhdrs::SERVER_NAME, | |||||
$Driverhdrs::SERVER_PORT, | |||||
$Driverhdrs::COURSE_NAME, | |||||
$userid, | |||||
$Driverhdrs::LAB, | |||||
$result); | |||||
# Print the status of the transfer | |||||
if (!($status =~ /OK/)) { | |||||
print "$status\n"; | |||||
print "Did not send autoresult string to the result server.\n"; | |||||
exit(1); | |||||
} | |||||
print "Success: Sent autoresult string for $userid to the result server.\n"; | |||||
} | |||||
} | |||||
##### | |||||
# Private functions | |||||
# | |||||
# | |||||
# submitr - Sends an autoresult string to the result server | |||||
# | |||||
sub submitr ($$$$$$) { | |||||
my $hostname = shift; | |||||
my $port = shift; | |||||
my $course = shift; | |||||
my $userid = shift; | |||||
my $lab = shift; | |||||
my $result = shift; | |||||
my $internet_addr; | |||||
my $enc_result; | |||||
my $paddr; | |||||
my $line; | |||||
my $http_version; | |||||
my $errcode; | |||||
my $errmsg; | |||||
# Establish the connection to the server | |||||
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); | |||||
$internet_addr = inet_aton($hostname) | |||||
or die "Could not convert $hostname to an internet address: $!\n"; | |||||
$paddr = sockaddr_in($port, $internet_addr); | |||||
connect(SERVER, $paddr) | |||||
or die "Could not connect to $hostname:$port:$!\n"; | |||||
select((select(SERVER), $| = 1)[0]); # enable command buffering | |||||
# Send HTTP request to server | |||||
$enc_result = url_encode($result); | |||||
print SERVER "GET /$course/submitr.pl/?userid=$userid&lab=$lab&result=$enc_result&submit=submit HTTP/1.0\r\n\r\n"; | |||||
# Get first HTTP response line | |||||
$line = <SERVER>; | |||||
chomp($line); | |||||
($http_version, $errcode, $errmsg) = split(/\s+/, $line); | |||||
if ($errcode != 200) { | |||||
return "Error: HTTP request failed with error $errcode: $errmsg"; | |||||
} | |||||
# Read the remaining HTTP response header lines | |||||
while ($line = <SERVER>) { | |||||
if ($line =~ /^\r\n/) { | |||||
last; | |||||
} | |||||
} | |||||
# Read and return the response from the result server | |||||
$line = <SERVER>; | |||||
chomp($line); | |||||
close SERVER; | |||||
return $line; | |||||
} | |||||
# | |||||
# url_encode - Encode text string so it can be included in URI of GET request | |||||
# | |||||
sub url_encode ($) { | |||||
my $value = shift; | |||||
$value =~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg; | |||||
return $value; | |||||
} | |||||
# Always end a module with a 1 so that it returns TRUE | |||||
1; | |||||
@ -0,0 +1,26 @@ | |||||
# | |||||
# Makefile that builds btest and other helper programs for the CS:APP data lab | |||||
# | |||||
CC = gcc | |||||
CFLAGS = -O -Wall -m32 | |||||
LIBS = -lm | |||||
all: btest fshow ishow | |||||
btest: btest.c bits.c decl.c tests.c btest.h bits.h | |||||
$(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c | |||||
fshow: fshow.c | |||||
$(CC) $(CFLAGS) -o fshow fshow.c | |||||
ishow: ishow.c | |||||
$(CC) $(CFLAGS) -o ishow ishow.c | |||||
# Forces a recompile. Used by the driver program. | |||||
btestexplicit: | |||||
$(CC) $(CFLAGS) $(LIBS) -o btest bits.c btest.c decl.c tests.c | |||||
clean: | |||||
rm -f *.o btest fshow ishow *~ | |||||
@ -0,0 +1,140 @@ | |||||
*********************** | |||||
The CS:APP Data Lab | |||||
Directions to Students | |||||
*********************** | |||||
Your goal is to modify your copy of bits.c so that it passes all the | |||||
tests in btest without violating any of the coding guidelines. | |||||
********* | |||||
0. Files: | |||||
********* | |||||
Makefile - Makes btest, fshow, and ishow | |||||
README - This file | |||||
bits.c - The file you will be modifying and handing in | |||||
bits.h - Header file | |||||
btest.c - The main btest program | |||||
btest.h - Used to build btest | |||||
decl.c - Used to build btest | |||||
tests.c - Used to build btest | |||||
tests-header.c- Used to build btest | |||||
dlc* - Rule checking compiler binary (data lab compiler) | |||||
driver.pl* - Driver program that uses btest and dlc to autograde bits.c | |||||
Driverhdrs.pm - Header file for optional "Beat the Prof" contest | |||||
fshow.c - Utility for examining floating-point representations | |||||
ishow.c - Utility for examining integer representations | |||||
*********************************************************** | |||||
1. Modifying bits.c and checking it for compliance with dlc | |||||
*********************************************************** | |||||
IMPORTANT: Carefully read the instructions in the bits.c file before | |||||
you start. These give the coding rules that you will need to follow if | |||||
you want full credit. | |||||
Use the dlc compiler (./dlc) to automatically check your version of | |||||
bits.c for compliance with the coding guidelines: | |||||
unix> ./dlc bits.c | |||||
dlc returns silently if there are no problems with your code. | |||||
Otherwise it prints messages that flag any problems. Running dlc with | |||||
the -e switch: | |||||
unix> ./dlc -e bits.c | |||||
causes dlc to print counts of the number of operators used by each function. | |||||
Once you have a legal solution, you can test it for correctness using | |||||
the ./btest program. | |||||
********************* | |||||
2. Testing with btest | |||||
********************* | |||||
The Makefile in this directory compiles your version of bits.c with | |||||
additional code to create a program (or test harness) named btest. | |||||
To compile and run the btest program, type: | |||||
unix> make btest | |||||
unix> ./btest [optional cmd line args] | |||||
You will need to recompile btest each time you change your bits.c | |||||
program. When moving from one platform to another, you will want to | |||||
get rid of the old version of btest and generate a new one. Use the | |||||
commands: | |||||
unix> make clean | |||||
unix> make btest | |||||
Btest tests your code for correctness by running millions of test | |||||
cases on each function. It tests wide swaths around well known corner | |||||
cases such as Tmin and zero for integer puzzles, and zero, inf, and | |||||
the boundary between denormalized and normalized numbers for floating | |||||
point puzzles. When btest detects an error in one of your functions, | |||||
it prints out the test that failed, the incorrect result, and the | |||||
expected result, and then terminates the testing for that function. | |||||
Here are the command line options for btest: | |||||
unix> ./btest -h | |||||
Usage: ./btest [-hg] [-r <n>] [-f <name> [-1|-2|-3 <val>]*] [-T <time limit>] | |||||
-1 <val> Specify first function argument | |||||
-2 <val> Specify second function argument | |||||
-3 <val> Specify third function argument | |||||
-f <name> Test only the named function | |||||
-g Format output for autograding with no error messages | |||||
-h Print this message | |||||
-r <n> Give uniform weight of n for all problems | |||||
-T <lim> Set timeout limit to lim | |||||
Examples: | |||||
Test all functions for correctness and print out error messages: | |||||
unix> ./btest | |||||
Test all functions in a compact form with no error messages: | |||||
unix> ./btest -g | |||||
Test function foo for correctness: | |||||
unix> ./btest -f foo | |||||
Test function foo for correctness with specific arguments: | |||||
unix> ./btest -f foo -1 27 -2 0xf | |||||
Btest does not check your code for compliance with the coding | |||||
guidelines. Use dlc to do that. | |||||
******************* | |||||
3. Helper Programs | |||||
******************* | |||||
We have included the ishow and fshow programs to help you decipher | |||||
integer and floating point representations respectively. Each takes a | |||||
single decimal or hex number as an argument. To build them type: | |||||
unix> make | |||||
Example usages: | |||||
unix> ./ishow 0x27 | |||||
Hex = 0x00000027, Signed = 39, Unsigned = 39 | |||||
unix> ./ishow 27 | |||||
Hex = 0x0000001b, Signed = 27, Unsigned = 27 | |||||
unix> ./fshow 0x15213243 | |||||
Floating point value 3.255334057e-26 | |||||
Bit Representation 0x15213243, sign = 0, exponent = 0x2a, fraction = 0x213243 | |||||
Normalized. +1.2593463659 X 2^(-85) | |||||
linux> ./fshow 15213243 | |||||
Floating point value 2.131829405e-38 | |||||
Bit Representation 0x00e822bb, sign = 0, exponent = 0x01, fraction = 0x6822bb | |||||
Normalized. +1.8135598898 X 2^(-126) | |||||
@ -0,0 +1,362 @@ | |||||
/* | |||||
* CS:APP Data Lab | |||||
* | |||||
* <GentleCold> | |||||
* | |||||
* bits.c - Source file with your solutions to the Lab. | |||||
* This is the file you will hand in to your instructor. | |||||
* | |||||
* WARNING: Do not include the <stdio.h> header; it confuses the dlc | |||||
* compiler. You can still use printf for debugging without including | |||||
* <stdio.h>, although you might get a compiler warning. In general, | |||||
* it's not good practice to ignore compiler warnings, but in this | |||||
* case it's OK. | |||||
*/ | |||||
#if 0 | |||||
/* | |||||
* Instructions to Students: | |||||
* | |||||
* STEP 1: Read the following instructions carefully. | |||||
*/ | |||||
You will provide your solution to the Data Lab by | |||||
editing the collection of functions in this source file. | |||||
INTEGER CODING RULES: | |||||
Replace the "return" statement in each function with one | |||||
or more lines of C code that implements the function. Your code | |||||
must conform to the following style: | |||||
int Funct(arg1, arg2, ...) { | |||||
/* brief description of how your implementation works */ | |||||
int var1 = Expr1; | |||||
... | |||||
int varM = ExprM; | |||||
varJ = ExprJ; | |||||
... | |||||
varN = ExprN; | |||||
return ExprR; | |||||
} | |||||
Each "Expr" is an expression using ONLY the following: | |||||
1. Integer constants 0 through 255 (0xFF), inclusive. You are | |||||
not allowed to use big constants such as 0xffffffff. | |||||
2. Function arguments and local variables (no global variables). | |||||
3. Unary integer operations ! ~ | |||||
4. Binary integer operations & ^ | + << >> | |||||
Some of the problems restrict the set of allowed operators even further. | |||||
Each "Expr" may consist of multiple operators. You are not restricted to | |||||
one operator per line. | |||||
You are expressly forbidden to: | |||||
1. Use any control constructs such as if, do, while, for, switch, etc. | |||||
2. Define or use any macros. | |||||
3. Define any additional functions in this file. | |||||
4. Call any functions. | |||||
5. Use any other operations, such as &&, ||, -, or ?: | |||||
6. Use any form of casting. | |||||
7. Use any data type other than int. This implies that you | |||||
cannot use arrays, structs, or unions. | |||||
You may assume that your machine: | |||||
1. Uses 2s complement, 32-bit representations of integers. | |||||
2. Performs right shifts arithmetically. | |||||
3. Has unpredictable behavior when shifting if the shift amount | |||||
is less than 0 or greater than 31. | |||||
EXAMPLES OF ACCEPTABLE CODING STYLE: | |||||
/* | |||||
* pow2plus1 - returns 2^x + 1, where 0 <= x <= 31 | |||||
*/ | |||||
int pow2plus1(int x) { | |||||
/* exploit ability of shifts to compute powers of 2 */ | |||||
return (1 << x) + 1; | |||||
} | |||||
/* | |||||
* pow2plus4 - returns 2^x + 4, where 0 <= x <= 31 | |||||
*/ | |||||
int pow2plus4(int x) { | |||||
/* exploit ability of shifts to compute powers of 2 */ | |||||
int result = (1 << x); | |||||
result += 4; | |||||
return result; | |||||
} | |||||
FLOATING POINT CODING RULES | |||||
For the problems that require you to implement floating-point operations, | |||||
the coding rules are less strict. You are allowed to use looping and | |||||
conditional control. You are allowed to use both ints and unsigneds. | |||||
You can use arbitrary integer and unsigned constants. You can use any arithmetic, | |||||
logical, or comparison operations on int or unsigned data. | |||||
You are expressly forbidden to: | |||||
1. Define or use any macros. | |||||
2. Define any additional functions in this file. | |||||
3. Call any functions. | |||||
4. Use any form of casting. | |||||
5. Use any data type other than int or unsigned. This means that you | |||||
cannot use arrays, structs, or unions. | |||||
6. Use any floating point data types, operations, or constants. | |||||
NOTES: | |||||
1. Use the dlc (data lab checker) compiler (described in the handout) to | |||||
check the legality of your solutions. | |||||
2. Each function has a maximum number of operations (integer, logical, | |||||
or comparison) that you are allowed to use for your implementation | |||||
of the function. The max operator count is checked by dlc. | |||||
Note that assignment ('=') is not counted; you may use as many of | |||||
these as you want without penalty. | |||||
3. Use the btest test harness to check your functions for correctness. | |||||
4. Use the BDD checker to formally verify your functions | |||||
5. The maximum number of ops for each function is given in the | |||||
header comment for each function. If there are any inconsistencies | |||||
between the maximum ops in the writeup and in this file, consider | |||||
this file the authoritative source. | |||||
/* | |||||
* STEP 2: Modify the following functions according the coding rules. | |||||
* | |||||
* IMPORTANT. TO AVOID GRADING SURPRISES: | |||||
* 1. Use the dlc compiler to check that your solutions conform | |||||
* to the coding rules. | |||||
* 2. Use the BDD checker to formally verify that your solutions produce | |||||
* the correct answers. | |||||
*/ | |||||
#endif | |||||
//1 | |||||
/* | |||||
* bitXor - x^y using only ~ and & | |||||
* Example: bitXor(4, 5) = 1 | |||||
* Legal ops: ~ & | |||||
* Max ops: 14 | |||||
* Rating: 1 | |||||
*/ | |||||
int bitXor(int x, int y) { | |||||
// make 0 ^ 1 to 1 & 1 and 0 & 1 equal to 1 0 | |||||
// make 0 ^ 0 to 1 & 0 and 0 & 1 equal to 0 0 | |||||
// make 1 0 to ~(0 & 1) equal to 1 | |||||
// make 0 0 to ~(1 & 1) equal to 0 | |||||
return ~(~(~x & y) & ~(x & ~y)); | |||||
} | |||||
/* | |||||
* tmin - return minimum two's complement integer | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 4 | |||||
* Rating: 1 | |||||
*/ | |||||
int tmin(void) { | |||||
return 1 << 31; | |||||
} | |||||
//2 | |||||
/* | |||||
* isTmax - returns 1 if x is the maximum, two's complement number, | |||||
* and 0 otherwise | |||||
* Legal ops: ! ~ & ^ | + | |||||
* Max ops: 10 | |||||
* Rating: 1 | |||||
*/ | |||||
int isTmax(int x) { | |||||
x += 1; | |||||
return !!(!!x & !((~x + 1) ^ x)); // attention to zero case | |||||
} | |||||
/* | |||||
* allOddBits - return 1 if all odd-numbered bits in word set to 1 | |||||
* where bits are numbered from 0 (least significant) to 31 (most significant) | |||||
* Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1 | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 12 | |||||
* Rating: 2 | |||||
*/ | |||||
int allOddBits(int x) { | |||||
// 0101 is stored as 1010 | |||||
int mask = 0xAA + (0xAA << 8) + (0xAA << 16) + (0xAA << 24); | |||||
return !((mask & x) ^ mask); | |||||
} | |||||
/* | |||||
* negate - return -x | |||||
* Example: negate(1) = -1. | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 5 | |||||
* Rating: 2 | |||||
*/ | |||||
int negate(int x) { | |||||
return ~x + 1; | |||||
} | |||||
//3 | |||||
/* | |||||
* isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9') | |||||
* Example: isAsciiDigit(0x35) = 1. | |||||
* isAsciiDigit(0x3a) = 0. | |||||
* isAsciiDigit(0x05) = 0. | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 15 | |||||
* Rating: 3 | |||||
*/ | |||||
int isAsciiDigit(int x) { | |||||
int i = !((1 << 31) & ((~0x30 + 1) + x)); | |||||
int j = !!((1 << 31) & ((~0x39) + x)); | |||||
return i & j; | |||||
} | |||||
/* | |||||
* conditional - same as x ? y : z | |||||
* Example: conditional(2,4,5) = 4 | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 16 | |||||
* Rating: 3 | |||||
*/ | |||||
int conditional(int x, int y, int z) { | |||||
int mask = ~(!x) + 1; | |||||
y &= ~mask; | |||||
z &= mask; | |||||
return y + z; | |||||
} | |||||
/* | |||||
* isLessOrEqual - if x <= y then return 1, else return 0 | |||||
* Example: isLessOrEqual(4,5) = 1. | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 24 | |||||
* Rating: 3 | |||||
*/ | |||||
int isLessOrEqual(int x, int y) { | |||||
// judge if positive or negative | |||||
int i = x >> 31 & 1; | |||||
int j = y >> 31 & 1; | |||||
// three cases | |||||
return !(!i & j) & ((i ^ j) | !(((~x + 1) + y) & (1 << 31))); | |||||
} | |||||
//4 | |||||
/* | |||||
* logicalNeg - implement the ! operator, using all of | |||||
* the legal operators except ! | |||||
* Examples: logicalNeg(3) = 0, logicalNeg(0) = 1 | |||||
* Legal ops: ~ & ^ | + << >> | |||||
* Max ops: 12 | |||||
* Rating: 4 | |||||
*/ | |||||
int logicalNeg(int x) { | |||||
int i = (x >> 31) & 1; | |||||
int j = ((~x + 1) >> 31) & 1; | |||||
return ~(i | j) + 2; | |||||
} | |||||
/* howManyBits - return the minimum number of bits required to represent x in | |||||
* two's complement | |||||
* Examples: howManyBits(12) = 5 | |||||
* howManyBits(298) = 10 | |||||
* howManyBits(-5) = 4 | |||||
* howManyBits(0) = 1 | |||||
* howManyBits(-1) = 1 | |||||
* howManyBits(0x80000000) = 32 | |||||
* Legal ops: ! ~ & ^ | + << >> | |||||
* Max ops: 90 | |||||
* Rating: 4 | |||||
*/ | |||||
int howManyBits(int x) { | |||||
// TODO reference from https://zhuanlan.zhihu.com/p/59534845 | |||||
int s = x >> 31, a1, a2, a3, a4, a5; // c99 | |||||
x = ((~s) & x) + (s & (~x)); | |||||
a1 = !!(x >> 16) << 4; | |||||
x >>= a1; | |||||
a2 = !!(x >> 8) << 3; | |||||
x >>= a2; | |||||
a3 = !!(x >> 4) << 2; | |||||
x >>= a3; | |||||
a4 = !!(x >> 2) << 1; | |||||
x >>= a4; | |||||
a5 = !!(x >> 1); | |||||
x >>= a5; | |||||
return a1 + a2 + a3 + a4 + a5 + x + 1; | |||||
} | |||||
//float | |||||
/* | |||||
* floatScale2 - Return bit-level equivalent of expression 2*f for | |||||
* floating point argument f. | |||||
* Both the argument and result are passed as unsigned int's, but | |||||
* they are to be interpreted as the bit-level representation of | |||||
* single-precision floating point values. | |||||
* When argument is NaN, return argument | |||||
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while | |||||
* Max ops: 30 | |||||
* Rating: 4 | |||||
*/ | |||||
unsigned floatScale2(unsigned uf) { | |||||
int s = (uf >> 31) & 1; | |||||
int e = ((uf >> 23) & 0x000000FF); | |||||
int f = uf & 0x007FFFFF; | |||||
if (e == 0) { | |||||
if (f == 0) return uf; // 0.0 * 2 | |||||
return s << 31 | f << 1; // still non-formatted | |||||
} | |||||
e += 1; // formatted | |||||
if ((e == 0x000000FF && f != 0) || e > 0x000000FF) return uf; // nan | |||||
return (s << 31) | (e << 23) | f; | |||||
} | |||||
/* | |||||
* floatFloat2Int - Return bit-level equivalent of expression (int) f | |||||
* for floating point argument f. | |||||
* Argument is passed as unsigned int, but | |||||
* it is to be interpreted as the bit-level representation of a | |||||
* single-precision floating point value. | |||||
* Anything out of range (including NaN and infinity) should return | |||||
* 0x80000000u. | |||||
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while | |||||
* Max ops: 30 | |||||
* Rating: 4 | |||||
*/ | |||||
int floatFloat2Int(unsigned uf) { | |||||
unsigned s = (uf >> 31) & 1; | |||||
unsigned e = ((uf >> 23) & 0x000000FF); | |||||
unsigned f = uf & 0x007FFFFF; | |||||
if (e < 0x7F) return 0; | |||||
if (e > 0x7F + 31) return 0x80000000u; // nan | |||||
e -= 0x7F; | |||||
if (s) | |||||
return ~((((f << e) & (~0x007FFFFF)) >> 23) + (1 << e)) + 1; | |||||
else | |||||
return ((((f << e) & (~0x007FFFFF)) >> 23) + (1 << e)); | |||||
} | |||||
/* | |||||
* floatPower2 - Return bit-level equivalent of the expression 2.0^x | |||||
* (2.0 raised to the power x) for any 32-bit integer x. | |||||
* | |||||
* The unsigned value that is returned should have the identical bit | |||||
* representation as the single-precision floating-point number 2.0^x. | |||||
* If the result is too small to be represented as a denorm, return | |||||
* 0. If too large, return +INF. | |||||
* | |||||
* Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while | |||||
* Max ops: 30 | |||||
* Rating: 4 | |||||
*/ | |||||
unsigned floatPower2(int x) { | |||||
unsigned s = 0; | |||||
unsigned e = 0x7F; | |||||
unsigned f = 0; | |||||
if (x >= 0x80) return 0x7F800000; // nan | |||||
if (x < 0) { | |||||
x = ~x + 1; | |||||
if (x >= 0x7F) return 0; | |||||
e -= x; | |||||
} else { | |||||
e += x; | |||||
} | |||||
return (s << 31) | (e << 23) | f; | |||||
} |
@ -0,0 +1,31 @@ | |||||
//1 | |||||
int bitXor(int, int); | |||||
int test_bitXor(int, int); | |||||
int tmin(); | |||||
int test_tmin(); | |||||
//2 | |||||
int isTmax(int); | |||||
int test_isTmax(int); | |||||
int allOddBits(); | |||||
int test_allOddBits(); | |||||
int negate(int); | |||||
int test_negate(int); | |||||
//3 | |||||
int isAsciiDigit(int); | |||||
int test_isAsciiDigit(int); | |||||
int conditional(int, int, int); | |||||
int test_conditional(int, int, int); | |||||
int isLessOrEqual(int, int); | |||||
int test_isLessOrEqual(int, int); | |||||
//4 | |||||
int logicalNeg(int); | |||||
int test_logicalNeg(int); | |||||
int howManyBits(int); | |||||
int test_howManyBits(int); | |||||
//float | |||||
unsigned floatScale2(unsigned); | |||||
unsigned test_floatScale2(unsigned); | |||||
int floatFloat2Int(unsigned); | |||||
int test_floatFloat2Int(unsigned); | |||||
unsigned floatPower2(int); | |||||
unsigned test_floatPower2(int); |
@ -0,0 +1,583 @@ | |||||
/* | |||||
* CS:APP Data Lab | |||||
* | |||||
* btest.c - A test harness that checks a student's solution in bits.c | |||||
* for correctness. | |||||
* | |||||
* Copyright (c) 2001-2011, R. Bryant and D. O'Hallaron, All rights | |||||
* reserved. May not be used, modified, or copied without permission. | |||||
* | |||||
* This is an improved version of btest that tests large windows | |||||
* around zero and tmin and tmax for integer puzzles, and zero, norm, | |||||
* and denorm boundaries for floating point puzzles. | |||||
* | |||||
* Note: not 64-bit safe. Always compile with gcc -m32 option. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <limits.h> | |||||
#include <signal.h> | |||||
#include <setjmp.h> | |||||
#include <math.h> | |||||
#include "btest.h" | |||||
/* Not declared in some stdlib.h files, so define here */ | |||||
float strtof(const char *nptr, char **endptr); | |||||
/************************* | |||||
* Configuration Constants | |||||
*************************/ | |||||
/* Handle infinite loops by setting upper limit on execution time, in | |||||
seconds */ | |||||
#define TIMEOUT_LIMIT 10 | |||||
/* For functions with a single argument, generate TEST_RANGE values | |||||
above and below the min and max test values, and above and below | |||||
zero. Functions with two or three args will use square and cube | |||||
roots of this value, respectively, to avoid combinatorial | |||||
explosion */ | |||||
#define TEST_RANGE 500000 | |||||
/* This defines the maximum size of any test value array. The | |||||
gen_vals() routine creates k test values for each value of | |||||
TEST_RANGE, thus MAX_TEST_VALS must be at least k*TEST_RANGE */ | |||||
#define MAX_TEST_VALS 13*TEST_RANGE | |||||
/********************************** | |||||
* Globals defined in other modules | |||||
**********************************/ | |||||
/* This characterizes the set of puzzles to test. | |||||
Defined in decl.c and generated from templates in ./puzzles dir */ | |||||
extern test_rec test_set[]; | |||||
/************************************************ | |||||
* Write-once globals defined by command line args | |||||
************************************************/ | |||||
/* Emit results in a format for autograding, without showing | |||||
and counter-examples */ | |||||
static int grade = 0; | |||||
/* Time out after this number of seconds */ | |||||
static int timeout_limit = TIMEOUT_LIMIT; /* -T */ | |||||
/* If non-NULL, test only one function (-f) */ | |||||
static char* test_fname = NULL; | |||||
/* Special case when only use fixed argument(s) (-1, -2, or -3) */ | |||||
static int has_arg[3] = {0,0,0}; | |||||
static unsigned argval[3] = {0,0,0}; | |||||
/* Use fixed weight for rating, and if so, what should it be? (-r) */ | |||||
static int global_rating = 0; | |||||
/****************** | |||||
* Helper functions | |||||
******************/ | |||||
/* | |||||
* Signal - installs a signal handler | |||||
*/ | |||||
typedef void handler_t(int); | |||||
handler_t *Signal(int signum, handler_t *handler) | |||||
{ | |||||
struct sigaction action, old_action; | |||||
action.sa_handler = handler; | |||||
sigemptyset(&action.sa_mask); /* block sigs of type being handled */ | |||||
action.sa_flags = SA_RESTART; /* restart syscalls if possible */ | |||||
if (sigaction(signum, &action, &old_action) < 0) | |||||
perror("Signal error"); | |||||
return (old_action.sa_handler); | |||||
} | |||||
/* | |||||
* timeout_handler - SIGALARM hander | |||||
*/ | |||||
sigjmp_buf envbuf; | |||||
void timeout_handler(int sig) { | |||||
siglongjmp(envbuf, 1); | |||||
} | |||||
/* | |||||
* random_val - Return random integer value between min and max | |||||
*/ | |||||
static int random_val(int min, int max) | |||||
{ | |||||
double weight = rand()/(double) RAND_MAX; | |||||
int result = min * (1-weight) + max * weight; | |||||
return result; | |||||
} | |||||
/* | |||||
* gen_vals - Generate the integer values we'll use to test a function | |||||
*/ | |||||
static int gen_vals(int test_vals[], int min, int max, int test_range, int arg) | |||||
{ | |||||
int i; | |||||
int test_count = 0; | |||||
/* Special case: If the user has specified a specific function | |||||
argument using the -1, -2, or -3 flags, then simply use this | |||||
argument and return */ | |||||
if (has_arg[arg]) { | |||||
test_vals[0] = argval[arg]; | |||||
return 1; | |||||
} | |||||
/* | |||||
* Special case: Generate test vals for floating point functions | |||||
* where the input argument is an unsigned bit-level | |||||
* representation of a float. For this case we want to test the | |||||
* regions around zero, the smallest normalized and largest | |||||
* denormalized numbers, one, and the largest normalized number, | |||||
* as well as inf and nan. | |||||
*/ | |||||
if ((min == 1 && max == 1)) { | |||||
unsigned smallest_norm = 0x00800000; | |||||
unsigned one = 0x3f800000; | |||||
unsigned largest_norm = 0x7f000000; | |||||
unsigned inf = 0x7f800000; | |||||
unsigned nan = 0x7fc00000; | |||||
unsigned sign = 0x80000000; | |||||
/* Test range should be at most 1/2 the range of one exponent | |||||
value */ | |||||
if (test_range > (1 << 23)) { | |||||
test_range = 1 << 23; | |||||
} | |||||
/* Functions where the input argument is an unsigned bit-level | |||||
representation of a float. The number of tests generated | |||||
inside this loop body is the value k referenced in the | |||||
comment for the global variable MAX_TEST_VALS. */ | |||||
for (i = 0; i < test_range; i++) { | |||||
/* Denorms around zero */ | |||||
test_vals[test_count++] = i; | |||||
test_vals[test_count++] = sign | i; | |||||
/* Region around norm to denorm transition */ | |||||
test_vals[test_count++] = smallest_norm + i; | |||||
test_vals[test_count++] = smallest_norm - i; | |||||
test_vals[test_count++] = sign | (smallest_norm + i); | |||||
test_vals[test_count++] = sign | (smallest_norm - i); | |||||
/* Region around one */ | |||||
test_vals[test_count++] = one + i; | |||||
test_vals[test_count++] = one - i; | |||||
test_vals[test_count++] = sign | (one + i); | |||||
test_vals[test_count++] = sign | (one - i); | |||||
/* Region below largest norm */ | |||||
test_vals[test_count++] = largest_norm - i; | |||||
test_vals[test_count++] = sign | (largest_norm - i); | |||||
} | |||||
/* special vals */ | |||||
test_vals[test_count++] = inf; /* inf */ | |||||
test_vals[test_count++] = sign | inf; /* -inf */ | |||||
test_vals[test_count++] = nan; /* nan */ | |||||
test_vals[test_count++] = sign | nan; /* -nan */ | |||||
return test_count; | |||||
} | |||||
/* | |||||
* Normal case: Generate test vals for integer functions | |||||
*/ | |||||
/* If the range is small enough, then do exhaustively */ | |||||
if (max - MAX_TEST_VALS <= min) { | |||||
for (i = min; i <= max; i++) | |||||
test_vals[test_count++] = i; | |||||
return test_count; | |||||
} | |||||
/* Otherwise, need to sample. Do so near the boundaries, around | |||||
zero, and for some random cases. */ | |||||
for (i = 0; i < test_range; i++) { | |||||
/* Test around the boundaries */ | |||||
test_vals[test_count++] = min + i; | |||||
test_vals[test_count++] = max - i; | |||||
/* If zero falls between min and max, then also test around zero */ | |||||
if (i >= min && i <= max) | |||||
test_vals[test_count++] = i; | |||||
if (-i >= min && -i <= max) | |||||
test_vals[test_count++] = -i; | |||||
/* Random case between min and max */ | |||||
test_vals[test_count++] = random_val(min, max); | |||||
} | |||||
return test_count; | |||||
} | |||||
/* | |||||
* test_0_arg - Test a function with zero arguments | |||||
*/ | |||||
static int test_0_arg(funct_t f, funct_t ft, char *name) | |||||
{ | |||||
int r = f(); | |||||
int rt = ft(); | |||||
int error = (r != rt); | |||||
if (error && !grade) | |||||
printf("ERROR: Test %s() failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, r, r, rt, rt); | |||||
return error; | |||||
} | |||||
/* | |||||
* test_1_arg - Test a function with one argument | |||||
*/ | |||||
static int test_1_arg(funct_t f, funct_t ft, int arg1, char *name) | |||||
{ | |||||
funct1_t f1 = (funct1_t) f; | |||||
funct1_t f1t = (funct1_t) ft; | |||||
int r, rt, error; | |||||
r = f1(arg1); | |||||
rt = f1t(arg1); | |||||
error = (r != rt); | |||||
if (error && !grade) | |||||
printf("ERROR: Test %s(%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, r, r, rt, rt); | |||||
return error; | |||||
} | |||||
/* | |||||
* test_2_arg - Test a function with two arguments | |||||
*/ | |||||
static int test_2_arg(funct_t f, funct_t ft, int arg1, int arg2, char *name) | |||||
{ | |||||
funct2_t f2 = (funct2_t) f; | |||||
funct2_t f2t = (funct2_t) ft; | |||||
int r = f2(arg1, arg2); | |||||
int rt = f2t(arg1, arg2); | |||||
int error = (r != rt); | |||||
if (error && !grade) | |||||
printf("ERROR: Test %s(%d[0x%x],%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, arg2, arg2, r, r, rt, rt); | |||||
return error; | |||||
} | |||||
/* | |||||
* test_3_arg - Test a function with three arguments | |||||
*/ | |||||
static int test_3_arg(funct_t f, funct_t ft, | |||||
int arg1, int arg2, int arg3, char *name) | |||||
{ | |||||
funct3_t f3 = (funct3_t) f; | |||||
funct3_t f3t = (funct3_t) ft; | |||||
int r = f3(arg1, arg2, arg3); | |||||
int rt = f3t(arg1, arg2, arg3); | |||||
int error = (r != rt); | |||||
if (error && !grade) | |||||
printf("ERROR: Test %s(%d[0x%x],%d[0x%x],%d[0x%x]) failed...\n...Gives %d[0x%x]. Should be %d[0x%x]\n", name, arg1, arg1, arg2, arg2, arg3, arg3, r, r, rt, rt); | |||||
return error; | |||||
} | |||||
/* | |||||
* test_function - Test a function. Return number of errors | |||||
*/ | |||||
static int test_function(test_ptr t) { | |||||
int test_counts[3]; /* number of test values for each arg */ | |||||
int args = t->args; /* number of function arguments */ | |||||
int arg_test_range[3]; /* test range for each argument */ | |||||
int i, a1, a2, a3; | |||||
int errors = 0; | |||||
/* These are the test values for each arg. Declared with the | |||||
static attribute so that the array will be allocated in bss | |||||
rather than the stack */ | |||||
static int arg_test_vals[3][MAX_TEST_VALS]; | |||||
/* Sanity check on the number of args */ | |||||
if (args < 0 || args > 3) { | |||||
printf("Configuration error: invalid number of args (%d) for function %s\n", args, t->name); | |||||
exit(1); | |||||
} | |||||
/* Assign range of argument test vals so as to conserve the total | |||||
number of tests, independent of the number of arguments */ | |||||
if (args == 1) { | |||||
arg_test_range[0] = TEST_RANGE; | |||||
} | |||||
else if (args == 2) { | |||||
arg_test_range[0] = pow((double)TEST_RANGE, 0.5); /* sqrt */ | |||||
arg_test_range[1] = arg_test_range[0]; | |||||
} | |||||
else { | |||||
arg_test_range[0] = pow((double)TEST_RANGE, 0.333); /* cbrt */ | |||||
arg_test_range[1] = arg_test_range[0]; | |||||
arg_test_range[2] = arg_test_range[0]; | |||||
} | |||||
/* Sanity check on the ranges */ | |||||
if (arg_test_range[0] < 1) | |||||
arg_test_range[0] = 1; | |||||
if (arg_test_range[1] < 1) | |||||
arg_test_range[1] = 1; | |||||
if (arg_test_range[2] < 1) | |||||
arg_test_range[2] = 1; | |||||
/* Create a test set for each argument */ | |||||
for (i = 0; i < args; i++) { | |||||
test_counts[i] = gen_vals(arg_test_vals[i], | |||||
t->arg_ranges[i][0], /* min */ | |||||
t->arg_ranges[i][1], /* max */ | |||||
arg_test_range[i], | |||||
i); | |||||
} | |||||
/* Handle timeouts in the test code */ | |||||
if (timeout_limit > 0) { | |||||
int rc; | |||||
rc = sigsetjmp(envbuf, 1); | |||||
if (rc) { | |||||
/* control will reach here if there is a timeout */ | |||||
errors = 1; | |||||
printf("ERROR: Test %s failed.\n Timed out after %d secs (probably infinite loop)\n", t->name, timeout_limit); | |||||
return errors; | |||||
} | |||||
alarm(timeout_limit); | |||||
} | |||||
/* Test function has no arguments */ | |||||
if (args == 0) { | |||||
errors += test_0_arg(t->solution_funct, t->test_funct, t->name); | |||||
return errors; | |||||
} | |||||
/* | |||||
* Test function has at least one argument | |||||
*/ | |||||
/* Iterate over the values for first argument */ | |||||
for (a1 = 0; a1 < test_counts[0]; a1++) { | |||||
if (args == 1) { | |||||
errors += test_1_arg(t->solution_funct, | |||||
t->test_funct, | |||||
arg_test_vals[0][a1], | |||||
t->name); | |||||
/* Stop testing if there is an error */ | |||||
if (errors) | |||||
return errors; | |||||
} | |||||
else { | |||||
/* if necessary, iterate over values for second argument */ | |||||
for (a2 = 0; a2 < test_counts[1]; a2++) { | |||||
if (args == 2) { | |||||
errors += test_2_arg(t->solution_funct, | |||||
t->test_funct, | |||||
arg_test_vals[0][a1], | |||||
arg_test_vals[1][a2], | |||||
t->name); | |||||
/* Stop testing if there is an error */ | |||||
if (errors) | |||||
return errors; | |||||
} | |||||
else { | |||||
/* if necessary, iterate over vals for third arg */ | |||||
for (a3 = 0; a3 < test_counts[2]; a3++) { | |||||
errors += test_3_arg(t->solution_funct, | |||||
t->test_funct, | |||||
arg_test_vals[0][a1], | |||||
arg_test_vals[1][a2], | |||||
arg_test_vals[2][a3], | |||||
t->name); | |||||
/* Stop testing if there is an error */ | |||||
if (errors) | |||||
return errors; | |||||
} /* a3 */ | |||||
} | |||||
} /* a2 */ | |||||
} | |||||
} /* a1 */ | |||||
return errors; | |||||
} | |||||
/* | |||||
* run_tests - Run series of tests. Return number of errors | |||||
*/ | |||||
static int run_tests() | |||||
{ | |||||
int i; | |||||
int errors = 0; | |||||
double points = 0.0; | |||||
double max_points = 0.0; | |||||
printf("Score\tRating\tErrors\tFunction\n"); | |||||
for (i = 0; test_set[i].solution_funct; i++) { | |||||
int terrors; | |||||
double tscore; | |||||
double tpoints; | |||||
if (!test_fname || strcmp(test_set[i].name,test_fname) == 0) { | |||||
int rating = global_rating ? global_rating : test_set[i].rating; | |||||
terrors = test_function(&test_set[i]); | |||||
errors += terrors; | |||||
tscore = terrors == 0 ? 1.0 : 0.0; | |||||
tpoints = rating * tscore; | |||||
points += tpoints; | |||||
max_points += rating; | |||||
if (grade || terrors < 1) | |||||
printf(" %.0f\t%d\t%d\t%s\n", | |||||
tpoints, rating, terrors, test_set[i].name); | |||||
} | |||||
} | |||||
printf("Total points: %.0f/%.0f\n", points, max_points); | |||||
return errors; | |||||
} | |||||
/* | |||||
* get_num_val - Extract hex/decimal/or float value from string | |||||
*/ | |||||
static int get_num_val(char *sval, unsigned *valp) { | |||||
char *endp; | |||||
/* See if it's an integer or floating point */ | |||||
int ishex = 0; | |||||
int isfloat = 0; | |||||
int i; | |||||
for (i = 0; sval[i]; i++) { | |||||
switch (sval[i]) { | |||||
case 'x': | |||||
case 'X': | |||||
ishex = 1; | |||||
break; | |||||
case 'e': | |||||
case 'E': | |||||
if (!ishex) | |||||
isfloat = 1; | |||||
break; | |||||
case '.': | |||||
isfloat = 1; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
if (isfloat) { | |||||
float fval = strtof(sval, &endp); | |||||
if (!*endp) { | |||||
*valp = *(unsigned *) &fval; | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} else { | |||||
long long int llval = strtoll(sval, &endp, 0); | |||||
long long int upperbits = llval >> 31; | |||||
/* will give -1 for negative, 0 or 1 for positive */ | |||||
if (!*valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) { | |||||
*valp = (unsigned) llval; | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} | |||||
} | |||||
/* | |||||
* usage - Display usage info | |||||
*/ | |||||
static void usage(char *cmd) { | |||||
printf("Usage: %s [-hg] [-r <n>] [-f <name> [-1|-2|-3 <val>]*] [-T <time limit>]\n", cmd); | |||||
printf(" -1 <val> Specify first function argument\n"); | |||||
printf(" -2 <val> Specify second function argument\n"); | |||||
printf(" -3 <val> Specify third function argument\n"); | |||||
printf(" -f <name> Test only the named function\n"); | |||||
printf(" -g Compact output for grading (with no error msgs)\n"); | |||||
printf(" -h Print this message\n"); | |||||
printf(" -r <n> Give uniform weight of n for all problems\n"); | |||||
printf(" -T <lim> Set timeout limit to lim\n"); | |||||
exit(1); | |||||
} | |||||
/************** | |||||
* Main routine | |||||
**************/ | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
char c; | |||||
/* parse command line args */ | |||||
while ((c = getopt(argc, argv, "hgf:r:T:1:2:3:")) != -1) | |||||
switch (c) { | |||||
case 'h': /* help */ | |||||
usage(argv[0]); | |||||
break; | |||||
case 'g': /* grading option for autograder */ | |||||
grade = 1; | |||||
break; | |||||
case 'f': /* test only one function */ | |||||
test_fname = strdup(optarg); | |||||
break; | |||||
case 'r': /* set global rating for each problem */ | |||||
global_rating = atoi(optarg); | |||||
if (global_rating < 0) | |||||
usage(argv[0]); | |||||
break; | |||||
case '1': /* Get first argument */ | |||||
has_arg[0] = get_num_val(optarg, &argval[0]); | |||||
if (!has_arg[0]) { | |||||
printf("Bad argument '%s'\n", optarg); | |||||
exit(0); | |||||
} | |||||
break; | |||||
case '2': /* Get first argument */ | |||||
has_arg[1] = get_num_val(optarg, &argval[1]); | |||||
if (!has_arg[1]) { | |||||
printf("Bad argument '%s'\n", optarg); | |||||
exit(0); | |||||
} | |||||
break; | |||||
case '3': /* Get first argument */ | |||||
has_arg[2] = get_num_val(optarg, &argval[2]); | |||||
if (!has_arg[2]) { | |||||
printf("Bad argument '%s'\n", optarg); | |||||
exit(0); | |||||
} | |||||
break; | |||||
case 'T': /* Set timeout limit */ | |||||
timeout_limit = atoi(optarg); | |||||
break; | |||||
default: | |||||
usage(argv[0]); | |||||
} | |||||
if (timeout_limit > 0) { | |||||
Signal(SIGALRM, timeout_handler); | |||||
} | |||||
/* test each function */ | |||||
run_tests(); | |||||
return 0; | |||||
} |
@ -0,0 +1,32 @@ | |||||
/* | |||||
* CS:APP Data Lab | |||||
*/ | |||||
/* Declare different function types */ | |||||
typedef int (*funct_t) (void); | |||||
typedef int (*funct1_t)(int); | |||||
typedef int (*funct2_t)(int, int); | |||||
typedef int (*funct3_t)(int, int, int); | |||||
/* Combine all the information about a function and its tests as structure */ | |||||
typedef struct { | |||||
char *name; /* String name */ | |||||
funct_t solution_funct; /* Function */ | |||||
funct_t test_funct; /* Test function */ | |||||
int args; /* Number of function arguments */ | |||||
char *ops; /* List of legal operators. Special case: "$" for floating point */ | |||||
int op_limit; /* Max number of ops allowed in solution */ | |||||
int rating; /* Problem rating (1 -- 4) */ | |||||
int arg_ranges[3][2]; /* Argument ranges. Always defined for 3 args, even if */ | |||||
/* the function takes fewer. Special case: First arg */ | |||||
/* must be set to {1,1} for f.p. puzzles */ | |||||
} test_rec, *test_ptr; | |||||
extern test_rec test_set[]; | |||||
@ -0,0 +1,57 @@ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <limits.h> | |||||
#define TMin INT_MIN | |||||
#define TMax INT_MAX | |||||
#include "btest.h" | |||||
#include "bits.h" | |||||
test_rec test_set[] = { | |||||
//1 | |||||
{"bitXor", (funct_t) bitXor, (funct_t) test_bitXor, 2, "& ~", 14, 1, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
{"tmin", (funct_t) tmin, (funct_t) test_tmin, 0, "! ~ & ^ | + << >>", 4, 1, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
//2 | |||||
{"isTmax", (funct_t) isTmax, (funct_t) test_isTmax, 1, "! ~ & ^ | +", 10, 1, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
{"allOddBits", (funct_t) allOddBits, (funct_t) test_allOddBits, 1, | |||||
"! ~ & ^ | + << >>", 12, 2, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
{"negate", (funct_t) negate, (funct_t) test_negate, 1, | |||||
"! ~ & ^ | + << >>", 5, 2, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
//3 | |||||
{"isAsciiDigit", (funct_t) isAsciiDigit, (funct_t) test_isAsciiDigit, 1, | |||||
"! ~ & ^ | + << >>", 15, 3, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
{"conditional", (funct_t) conditional, (funct_t) test_conditional, 3, "! ~ & ^ | << >>", 16, 3, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
{"isLessOrEqual", (funct_t) isLessOrEqual, (funct_t) test_isLessOrEqual, 2, | |||||
"! ~ & ^ | + << >>", 24, 3, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
//4 | |||||
{"logicalNeg", (funct_t) logicalNeg, (funct_t) test_logicalNeg, 1, | |||||
"~ & ^ | + << >>", 12, 4, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
{"howManyBits", (funct_t) howManyBits, (funct_t) test_howManyBits, 1, "! ~ & ^ | + << >>", 90, 4, | |||||
{{TMin, TMax},{TMin,TMax},{TMin,TMax}}}, | |||||
//float | |||||
{"floatScale2", (funct_t) floatScale2, (funct_t) test_floatScale2, 1, | |||||
"$", 30, 4, | |||||
{{1, 1},{1,1},{1,1}}}, | |||||
{"floatFloat2Int", (funct_t) floatFloat2Int, (funct_t) test_floatFloat2Int, 1, | |||||
"$", 30, 4, | |||||
{{1, 1},{1,1},{1,1}}}, | |||||
{"floatPower2", (funct_t) floatPower2, (funct_t) test_floatPower2, 1, | |||||
"$", 30, 4, | |||||
{{1, 1},{1,1},{1,1}}}, | |||||
{"", NULL, NULL, 0, "", 0, 0, | |||||
{{0, 0},{0,0},{0,0}}} | |||||
}; |
@ -0,0 +1,439 @@ | |||||
#!/usr/bin/perl | |||||
####################################################################### | |||||
# driver.pl - CS:APP Data Lab driver | |||||
# | |||||
# Copyright (c) 2004-2011, R. Bryant and D. O'Hallaron, All rights | |||||
# reserved. May not be used, modified, or copied without permission. | |||||
# | |||||
# Note: The driver can use either btest or the BDD checker to check | |||||
# puzzles for correctness. This version of the lab uses btest, which | |||||
# has been extended to do better testing of both integer and | |||||
# floating-point puzzles. | |||||
# | |||||
####################################################################### | |||||
use strict 'vars'; | |||||
use Getopt::Std; | |||||
use lib "."; | |||||
use Driverlib; | |||||
# Set to 1 to use btest, 0 to use the BDD checker. | |||||
my $USE_BTEST = 1; | |||||
# Generic settings | |||||
$| = 1; # Flush stdout each time | |||||
umask(0077); # Files created by the user in tmp readable only by that user | |||||
$ENV{PATH} = "/usr/local/bin:/usr/bin:/bin"; | |||||
# | |||||
# usage - print help message and terminate | |||||
# | |||||
sub usage { | |||||
printf STDERR "$_[0]\n"; | |||||
printf STDERR "Usage: $0 [-h] [-u \"nickname\"]\n"; | |||||
printf STDERR "Options:\n"; | |||||
printf STDERR " -h Print this message.\n"; | |||||
printf STDERR " -u \"nickname\" Send autoresult to server, using nickname on scoreboard)\n"; | |||||
die "\n"; | |||||
} | |||||
############## | |||||
# Main routine | |||||
############## | |||||
my $login = getlogin() || (getpwuid($<))[0] || "unknown"; | |||||
my $tmpdir = "/var/tmp/datalab.$login.$$"; | |||||
my $diemsg = "The files are in $tmpdir."; | |||||
my $driverfiles; | |||||
my $infile; | |||||
my $autograded; | |||||
my $status; | |||||
my $inpuzzles; | |||||
my $puzzlecnt; | |||||
my $line; | |||||
my $blank; | |||||
my $name; | |||||
my $c_points; | |||||
my $c_rating; | |||||
my $c_errors; | |||||
my $p_points; | |||||
my $p_rating; | |||||
my $p_errors; | |||||
my $total_c_points; | |||||
my $total_c_rating; | |||||
my $total_p_points; | |||||
my $total_p_rating; | |||||
my $tops; | |||||
my $tpoints; | |||||
my $trating; | |||||
my $foo; | |||||
my $name; | |||||
my $msg; | |||||
my $nickname; | |||||
my $autoresult; | |||||
my %puzzle_c_points; | |||||
my %puzzle_c_rating; | |||||
my %puzzle_c_errors; | |||||
my %puzzle_p_points; | |||||
my %puzzle_p_ops; | |||||
my %puzzle_p_maxops; | |||||
my %puzzle_number; | |||||
# Parse the command line arguments | |||||
no strict; | |||||
getopts('hu:f:A'); | |||||
if ($opt_h) { | |||||
usage(); | |||||
} | |||||
# The default input file is bits.c (change with -f) | |||||
$infile = "bits.c"; | |||||
$nickname = ""; | |||||
##### | |||||
# These are command line args that every driver must support | |||||
# | |||||
# Causes the driver to send an autoresult to the server on behalf of user | |||||
if ($opt_u) { | |||||
$nickname = $opt_u; | |||||
check_nickname($nickname); | |||||
} | |||||
# Hidden flag that indicates that the driver was invoked by an autograder | |||||
if ($opt_A) { | |||||
$autograded = $opt_A; | |||||
} | |||||
##### | |||||
# Drivers can also define an arbitary number of other command line args | |||||
# | |||||
# Optional hidden flag used by the autograder | |||||
if ($opt_f) { | |||||
$infile = $opt_f; | |||||
} | |||||
use strict 'vars'; | |||||
################################################ | |||||
# Compute the correctness and performance scores | |||||
################################################ | |||||
# Make sure that an executable dlc (data lab compiler) exists | |||||
(-e "./dlc" and -x "./dlc") | |||||
or die "$0: ERROR: No executable dlc binary.\n"; | |||||
# If using the bdd checker, then make sure it exists | |||||
if (!$USE_BTEST) { | |||||
(-e "./bddcheck/cbit/cbit" and -x "./bddcheck/cbit/cbit") | |||||
or die "$0: ERROR: No executable cbit binary.\n"; | |||||
} | |||||
# | |||||
# Set up the contents of the scratch directory | |||||
# | |||||
system("mkdir $tmpdir") == 0 | |||||
or die "$0: Could not make scratch directory $tmpdir.\n"; | |||||
# Copy the student's work to the scratch directory | |||||
unless (system("cp $infile $tmpdir/bits.c") == 0) { | |||||
clean($tmpdir); | |||||
die "$0: Could not copy file $infile to scratch directory $tmpdir.\n"; | |||||
} | |||||
# Copy the various autograding files to the scratch directory | |||||
if ($USE_BTEST) { | |||||
$driverfiles = "Makefile dlc btest.c decl.c tests.c btest.h bits.h"; | |||||
unless (system("cp -r $driverfiles $tmpdir") == 0) { | |||||
clean($tmpdir); | |||||
die "$0: Could not copy autogradingfiles to $tmpdir.\n"; | |||||
} | |||||
} | |||||
else { | |||||
$driverfiles = "dlc tests.c bddcheck"; | |||||
unless (system("cp -r $driverfiles $tmpdir") == 0) { | |||||
clean($tmpdir); | |||||
die "$0: Could not copy support files to $tmpdir.\n"; | |||||
} | |||||
} | |||||
# Change the current working directory to the scratch directory | |||||
unless (chdir($tmpdir)) { | |||||
clean($tmpdir); | |||||
die "$0: Could not change directory to $tmpdir.\n"; | |||||
} | |||||
# | |||||
# Generate a zapped (for coding rules) version of bits.c. In this | |||||
# zapped version of bits.c, any functions with illegal operators are | |||||
# transformed to have empty function bodies. | |||||
# | |||||
print "1. Running './dlc -z' to identify coding rules violations.\n"; | |||||
system("cp bits.c save-bits.c") == 0 | |||||
or die "$0: ERROR: Could not create backup copy of bits.c. $diemsg\n"; | |||||
system("./dlc -z -o zap-bits.c bits.c") == 0 | |||||
or die "$0: ERROR: zapped bits.c did not compile. $diemsg\n"; | |||||
# | |||||
# Run btest or BDD checker to determine correctness score | |||||
# | |||||
if ($USE_BTEST) { | |||||
print "\n2. Compiling and running './btest -g' to determine correctness score.\n"; | |||||
system("cp zap-bits.c bits.c"); | |||||
# Compile btest | |||||
system("make btestexplicit") == 0 | |||||
or die "$0: Could not make btest in $tmpdir. $diemsg\n"; | |||||
# Run btest | |||||
$status = system("./btest -g > btest-zapped.out 2>&1"); | |||||
if ($status != 0) { | |||||
die "$0: ERROR: btest check failed. $diemsg\n"; | |||||
} | |||||
} | |||||
else { | |||||
print "\n2. Running './bddcheck/check.pl -g' to determine correctness score.\n"; | |||||
system("cp zap-bits.c bits.c"); | |||||
$status = system("./bddcheck/check.pl -g > btest-zapped.out 2>&1"); | |||||
if ($status != 0) { | |||||
die "$0: ERROR: BDD check failed. $diemsg\n"; | |||||
} | |||||
} | |||||
# | |||||
# Run dlc to identify operator count violations. | |||||
# | |||||
print "\n3. Running './dlc -Z' to identify operator count violations.\n"; | |||||
system("./dlc -Z -o Zap-bits.c save-bits.c") == 0 | |||||
or die "$0: ERROR: dlc unable to generated Zapped bits.c file.\n"; | |||||
# | |||||
# Run btest or the bdd checker to compute performance score | |||||
# | |||||
if ($USE_BTEST) { | |||||
print "\n4. Compiling and running './btest -g -r 2' to determine performance score.\n"; | |||||
system("cp Zap-bits.c bits.c"); | |||||
# Compile btest | |||||
system("make btestexplicit") == 0 | |||||
or die "$0: Could not make btest in $tmpdir. $diemsg\n"; | |||||
print "\n"; | |||||
# Run btest | |||||
$status = system("./btest -g -r 2 > btest-Zapped.out 2>&1"); | |||||
if ($status != 0) { | |||||
die "$0: ERROR: Zapped btest failed. $diemsg\n"; | |||||
} | |||||
} | |||||
else { | |||||
print "\n4. Running './bddcheck/check.pl -g -r 2' to determine performance score.\n"; | |||||
system("cp Zap-bits.c bits.c"); | |||||
$status = system("./bddcheck/check.pl -g -r 2 > btest-Zapped.out 2>&1"); | |||||
if ($status != 0) { | |||||
die "$0: ERROR: Zapped bdd checker failed. $diemsg\n"; | |||||
} | |||||
} | |||||
# | |||||
# Run dlc to get the operator counts on the zapped input file | |||||
# | |||||
print "\n5. Running './dlc -e' to get operator count of each function.\n"; | |||||
$status = system("./dlc -W1 -e zap-bits.c > dlc-opcount.out 2>&1"); | |||||
if ($status != 0) { | |||||
die "$0: ERROR: bits.c did not compile. $diemsg\n"; | |||||
} | |||||
################################################################# | |||||
# Collect the correctness and performance results for each puzzle | |||||
################################################################# | |||||
# | |||||
# Collect the correctness results | |||||
# | |||||
%puzzle_c_points = (); # Correctness score computed by btest | |||||
%puzzle_c_errors = (); # Correctness error discovered by btest | |||||
%puzzle_c_rating = (); # Correctness puzzle rating (max points) | |||||
$inpuzzles = 0; # Becomes true when we start reading puzzle results | |||||
$puzzlecnt = 0; # Each puzzle gets a unique number | |||||
$total_c_points = 0; | |||||
$total_c_rating = 0; | |||||
open(INFILE, "$tmpdir/btest-zapped.out") | |||||
or die "$0: ERROR: could not open input file $tmpdir/btest-zapped.out\n"; | |||||
while ($line = <INFILE>) { | |||||
chomp($line); | |||||
# Notice that we're ready to read the puzzle scores | |||||
if ($line =~ /^Score/) { | |||||
$inpuzzles = 1; | |||||
next; | |||||
} | |||||
# Notice that we're through reading the puzzle scores | |||||
if ($line =~ /^Total/) { | |||||
$inpuzzles = 0; | |||||
next; | |||||
} | |||||
# Read and record a puzzle's name and score | |||||
if ($inpuzzles) { | |||||
($blank, $c_points, $c_rating, $c_errors, $name) = split(/\s+/, $line); | |||||
$puzzle_c_points{$name} = $c_points; | |||||
$puzzle_c_errors{$name} = $c_errors; | |||||
$puzzle_c_rating{$name} = $c_rating; | |||||
$puzzle_number{$name} = $puzzlecnt++; | |||||
$total_c_points += $c_points; | |||||
$total_c_rating += $c_rating; | |||||
} | |||||
} | |||||
close(INFILE); | |||||
# | |||||
# Collect the performance results | |||||
# | |||||
%puzzle_p_points = (); # Performance points | |||||
$inpuzzles = 0; # Becomes true when we start reading puzzle results | |||||
$total_p_points = 0; | |||||
$total_p_rating = 0; | |||||
open(INFILE, "$tmpdir/btest-Zapped.out") | |||||
or die "$0: ERROR: could not open input file $tmpdir/btest-Zapped.out\n"; | |||||
while ($line = <INFILE>) { | |||||
chomp($line); | |||||
# Notice that we're ready to read the puzzle scores | |||||
if ($line =~ /^Score/) { | |||||
$inpuzzles = 1; | |||||
next; | |||||
} | |||||
# Notice that we're through reading the puzzle scores | |||||
if ($line =~ /^Total/) { | |||||
$inpuzzles = 0; | |||||
next; | |||||
} | |||||
# Read and record a puzzle's name and score | |||||
if ($inpuzzles) { | |||||
($blank, $p_points, $p_rating, $p_errors, $name) = split(/\s+/, $line); | |||||
$puzzle_p_points{$name} = $p_points; | |||||
$total_p_points += $p_points; | |||||
$total_p_rating += $p_rating; | |||||
} | |||||
} | |||||
close(INFILE); | |||||
# | |||||
# Collect the operator counts generated by dlc | |||||
# | |||||
open(INFILE, "$tmpdir/dlc-opcount.out") | |||||
or die "$0: ERROR: could not open input file $tmpdir/dlc-opcount.out\n"; | |||||
$tops = 0; | |||||
while ($line = <INFILE>) { | |||||
chomp($line); | |||||
if ($line =~ /(\d+) operators/) { | |||||
($foo, $foo, $foo, $name, $msg) = split(/:/, $line); | |||||
$puzzle_p_ops{$name} = $1; | |||||
$tops += $1; | |||||
} | |||||
} | |||||
close(INFILE); | |||||
# | |||||
# Print a table of results sorted by puzzle number | |||||
# | |||||
print "\n"; | |||||
printf("%s\t%s\n", "Correctness Results", "Perf Results"); | |||||
printf("%s\t%s\t%s\t%s\t%s\t%s\n", "Points", "Rating", "Errors", | |||||
"Points", "Ops", "Puzzle"); | |||||
foreach $name (sort {$puzzle_number{$a} <=> $puzzle_number{$b}} | |||||
keys %puzzle_number) { | |||||
printf("%d\t%d\t%d\t%d\t%d\t\%s\n", | |||||
$puzzle_c_points{$name}, | |||||
$puzzle_c_rating{$name}, | |||||
$puzzle_c_errors{$name}, | |||||
$puzzle_p_points{$name}, | |||||
$puzzle_p_ops{$name}, | |||||
$name); | |||||
} | |||||
$tpoints = $total_c_points + $total_p_points; | |||||
$trating = $total_c_rating + $total_p_rating; | |||||
print "\nScore = $tpoints/$trating [$total_c_points/$total_c_rating Corr + $total_p_points/$total_p_rating Perf] ($tops total operators)\n"; | |||||
# | |||||
# Optionally send the autoresult to the contest server if the driver | |||||
# was called with the -u command line flag. | |||||
# | |||||
if ($nickname) { | |||||
# Generate the autoresult | |||||
$autoresult = "$tpoints|$total_c_points|$total_p_points|$tops"; | |||||
foreach $name (sort {$puzzle_number{$a} <=> $puzzle_number{$b}} | |||||
keys %puzzle_number) { | |||||
$autoresult .= " |$name:$puzzle_c_points{$name}:$puzzle_c_rating{$name}:$puzzle_p_points{$name}:$puzzle_p_ops{$name}"; | |||||
} | |||||
# Post the autoresult to the server. The Linux login id is | |||||
# concatenated with the user-supplied nickname for some (very) loose | |||||
# authentication of submissions. | |||||
&Driverlib::driver_post("$login:$nickname", $autoresult, $autograded); | |||||
} | |||||
# Clean up and exit | |||||
clean ($tmpdir); | |||||
exit; | |||||
################## | |||||
# Helper functions | |||||
# | |||||
# | |||||
# check_nickname - Check a nickname for legality | |||||
# | |||||
sub check_nickname { | |||||
my $nickname = shift; | |||||
# Nicknames can't be empty | |||||
if (length($nickname) < 1) { | |||||
die "$0: Error: Empty nickname.\n"; | |||||
} | |||||
# Nicknames can't be too long | |||||
if (length($nickname) > 35) { | |||||
die "$0: Error: Nickname exceeds 35 characters.\n"; | |||||
} | |||||
# Nicknames can have restricted set of metacharacters (e.g., no # | |||||
# HTML tags) | |||||
if (!($nickname =~ /^[_-\w.,'@ ]+$/)) { | |||||
die "$0: Error: Illegal character in nickname. Only alphanumerics, apostrophes, commas, periods, dashes, underscores, and ampersands are allowed.\n"; | |||||
} | |||||
# Nicknames can't be all whitespace | |||||
if ($nickname =~ /^\s*$/) { | |||||
die "$0: Error: Nickname is all whitespace.\n"; | |||||
} | |||||
} | |||||
# | |||||
# clean - remove the scratch directory | |||||
# | |||||
sub clean { | |||||
my $tmpdir = shift; | |||||
system("rm -rf $tmpdir"); | |||||
} | |||||
@ -0,0 +1,151 @@ | |||||
/* Display structure of floating-point numbers */ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
float strtof(const char *nptr, char **endptr); | |||||
#define FLOAT_SIZE 32 | |||||
#define FRAC_SIZE 23 | |||||
#define EXP_SIZE 8 | |||||
#define BIAS ((1<<(EXP_SIZE-1))-1) | |||||
#define FRAC_MASK ((1<<FRAC_SIZE)-1) | |||||
#define EXP_MASK ((1<<EXP_SIZE)-1) | |||||
/* Floating point helpers */ | |||||
unsigned f2u(float f) | |||||
{ | |||||
union { | |||||
unsigned u; | |||||
float f; | |||||
} v; | |||||
v.u = 0; | |||||
v.f = f; | |||||
return v.u; | |||||
} | |||||
static float u2f(unsigned u) | |||||
{ | |||||
union { | |||||
unsigned u; | |||||
float f; | |||||
} v; | |||||
v.u = u; | |||||
return v.f; | |||||
} | |||||
/* Get exponent */ | |||||
unsigned get_exp(unsigned uf) | |||||
{ | |||||
return (uf>>FRAC_SIZE) & EXP_MASK; | |||||
} | |||||
/* Get fraction */ | |||||
unsigned get_frac(unsigned uf) | |||||
{ | |||||
return uf & FRAC_MASK; | |||||
} | |||||
/* Get sign */ | |||||
unsigned get_sign(unsigned uf) | |||||
{ | |||||
return (uf>>(FLOAT_SIZE-1)) & 0x1; | |||||
} | |||||
void show_float(unsigned uf) | |||||
{ | |||||
float f = u2f(uf); | |||||
unsigned exp = get_exp(uf); | |||||
unsigned frac = get_frac(uf); | |||||
unsigned sign = get_sign(uf); | |||||
printf("\nFloating point value %.10g\n", f); | |||||
printf("Bit Representation 0x%.8x, sign = %x, exponent = 0x%.2x, fraction = 0x%.6x\n", | |||||
uf, sign, exp, frac); | |||||
if (exp == EXP_MASK) { | |||||
if (frac == 0) { | |||||
printf("%cInfinity\n", sign ? '-' : '+'); | |||||
} else | |||||
printf("Not-A-Number\n"); | |||||
} else { | |||||
int denorm = (exp == 0); | |||||
int uexp = denorm ? 1-BIAS : exp - BIAS; | |||||
int mantissa = denorm ? frac : frac + (1<<FRAC_SIZE); | |||||
float fman = (float) mantissa / (float) (1<<FRAC_SIZE); | |||||
printf("%s. %c%.10f X 2^(%d)\n", | |||||
denorm ? "Denormalized" : "Normalized", | |||||
sign ? '-' : '+', | |||||
fman, uexp); | |||||
} | |||||
} | |||||
/* Extract hex/decimal/or float value from string */ | |||||
static int get_num_val(char *sval, unsigned *valp) { | |||||
char *endp; | |||||
/* See if it's an integer or floating point */ | |||||
int ishex = 0; | |||||
int isfloat = 0; | |||||
int i; | |||||
for (i = 0; sval[i]; i++) { | |||||
switch (sval[i]) { | |||||
case 'x': | |||||
case 'X': | |||||
ishex = 1; | |||||
break; | |||||
case 'e': | |||||
case 'E': | |||||
if (!ishex) | |||||
isfloat = 1; | |||||
break; | |||||
case '.': | |||||
isfloat = 1; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
if (isfloat) { | |||||
float fval = strtof(sval, &endp); | |||||
if (!*endp) { | |||||
*valp = *(unsigned *) &fval; | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} else { | |||||
long long int llval = strtoll(sval, &endp, 0); | |||||
long long int upperbits = llval >> 31; | |||||
/* will give -1 for negative, 0 or 1 for positive */ | |||||
if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) { | |||||
*valp = (unsigned) llval; | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} | |||||
} | |||||
void usage(char *fname) { | |||||
printf("Usage: %s val1 val2 ...\n", fname); | |||||
printf("Values may be given as hex patterns or as floating point numbers\n"); | |||||
exit(0); | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
int i; | |||||
unsigned uf; | |||||
if (argc < 2) | |||||
usage(argv[0]); | |||||
for (i = 1; i < argc; i++) { | |||||
char *sval = argv[i]; | |||||
if (get_num_val(sval, &uf)) { | |||||
show_float(uf); | |||||
} else { | |||||
printf("Invalid 32-bit number: '%s'\n", sval); | |||||
usage(argv[0]); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
@ -0,0 +1,75 @@ | |||||
/* Display value of fixed point numbers */ | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
/* Extract hex/decimal/or float value from string */ | |||||
static int get_num_val(char *sval, unsigned *valp) { | |||||
char *endp; | |||||
/* See if it's an integer or floating point */ | |||||
int ishex = 0; | |||||
int isfloat = 0; | |||||
int i; | |||||
for (i = 0; sval[i]; i++) { | |||||
switch (sval[i]) { | |||||
case 'x': | |||||
case 'X': | |||||
ishex = 1; | |||||
break; | |||||
case 'e': | |||||
case 'E': | |||||
if (!ishex) | |||||
isfloat = 1; | |||||
break; | |||||
case '.': | |||||
isfloat = 1; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
if (isfloat) { | |||||
return 0; /* Not supposed to have a float here */ | |||||
} else { | |||||
long long int llval = strtoll(sval, &endp, 0); | |||||
long long int upperbits = llval >> 31; | |||||
/* will give -1 for negative, 0 or 1 for positive */ | |||||
if (valp && (upperbits == 0 || upperbits == -1 || upperbits == 1)) { | |||||
*valp = (unsigned) llval; | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} | |||||
} | |||||
void show_int(unsigned uf) | |||||
{ | |||||
printf("Hex = 0x%.8x,\tSigned = %d,\tUnsigned = %u\n", | |||||
uf, (int) uf, uf); | |||||
} | |||||
void usage(char *fname) { | |||||
printf("Usage: %s val1 val2 ...\n", fname); | |||||
printf("Values may be given in hex or decimal\n"); | |||||
exit(0); | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
int i; | |||||
unsigned uf; | |||||
if (argc < 2) | |||||
usage(argv[0]); | |||||
for (i = 1; i < argc; i++) { | |||||
char *sval = argv[i]; | |||||
if (get_num_val(sval, &uf)) { | |||||
show_int(uf); | |||||
} else { | |||||
printf("Cannot convert '%s' to 32-bit number\n", sval); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
@ -0,0 +1,118 @@ | |||||
/* Testing Code */ | |||||
#include <limits.h> | |||||
#include <math.h> | |||||
/* Routines used by floation point test code */ | |||||
/* Convert from bit level representation to floating point number */ | |||||
float u2f(unsigned u) { | |||||
union { | |||||
unsigned u; | |||||
float f; | |||||
} a; | |||||
a.u = u; | |||||
return a.f; | |||||
} | |||||
/* Convert from floating point number to bit-level representation */ | |||||
unsigned f2u(float f) { | |||||
union { | |||||
unsigned u; | |||||
float f; | |||||
} a; | |||||
a.f = f; | |||||
return a.u; | |||||
} | |||||
//1 | |||||
int test_bitXor(int x, int y) | |||||
{ | |||||
return x^y; | |||||
} | |||||
int test_tmin(void) { | |||||
return 0x80000000; | |||||
} | |||||
//2 | |||||
int test_isTmax(int x) { | |||||
return x == 0x7FFFFFFF; | |||||
} | |||||
int test_allOddBits(int x) { | |||||
int i; | |||||
for (i = 1; i < 32; i+=2) | |||||
if ((x & (1<<i)) == 0) | |||||
return 0; | |||||
return 1; | |||||
} | |||||
int test_negate(int x) { | |||||
return -x; | |||||
} | |||||
//3 | |||||
int test_isAsciiDigit(int x) { | |||||
return (0x30 <= x) && (x <= 0x39); | |||||
} | |||||
int test_conditional(int x, int y, int z) | |||||
{ | |||||
return x?y:z; | |||||
} | |||||
int test_isLessOrEqual(int x, int y) | |||||
{ | |||||
return x <= y; | |||||
} | |||||
//4 | |||||
int test_logicalNeg(int x) | |||||
{ | |||||
return !x; | |||||
} | |||||
int test_howManyBits(int x) { | |||||
unsigned int a, cnt; | |||||
x = x<0 ? -x-1 : x; | |||||
a = (unsigned int)x; | |||||
for (cnt=0; a; a>>=1, cnt++) | |||||
; | |||||
return (int)(cnt + 1); | |||||
} | |||||
//float | |||||
unsigned test_floatScale2(unsigned uf) { | |||||
float f = u2f(uf); | |||||
float tf = 2*f; | |||||
if (isnan(f)) | |||||
return uf; | |||||
else | |||||
return f2u(tf); | |||||
} | |||||
int test_floatFloat2Int(unsigned uf) { | |||||
float f = u2f(uf); | |||||
int x = (int) f; | |||||
return x; | |||||
} | |||||
unsigned test_floatPower2(int x) { | |||||
float result = 1.0; | |||||
float p2 = 2.0; | |||||
int recip = (x < 0); | |||||
/* treat tmin specially */ | |||||
if ((unsigned)x == 0x80000000) { | |||||
return 0; | |||||
} | |||||
if (recip) { | |||||
x = -x; | |||||
p2 = 0.5; | |||||
} | |||||
while (x > 0) { | |||||
if (x & 0x1) | |||||
result = result * p2; | |||||
p2 = p2 * p2; | |||||
x >>= 1; | |||||
} | |||||
return f2u(result); | |||||
} |
@ -0,0 +1,30 @@ | |||||
// | |||||
// Created by GentleCold on 2022/8/17. | |||||
// | |||||
#ifndef CSAPPLEARNING_TEST_H | |||||
#define CSAPPLEARNING_TEST_H | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
int main_ret = 0; | |||||
int test_count = 0; | |||||
int test_pass = 0; | |||||
#define EXPECT_EQ_BASE(equality, expect, actual, format)\ | |||||
do {\ | |||||
test_count++;\ | |||||
if (equality) {\ | |||||
test_pass++;\ | |||||
} else {\ | |||||
fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual);\ | |||||
main_ret = 1;\ | |||||
}\ | |||||
} while(0) | |||||
#define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") | |||||
#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%lf") | |||||
#define EXPECT_EQ_TRUE(actual) EXPECT_EQ_BASE(actual, "true", "false", "%s") | |||||
#endif //CSAPPLEARNING_TEST_H |
@ -0,0 +1,15 @@ | |||||
// | |||||
// Created by GentleCold on 2022/9/7. | |||||
// | |||||
#include "test.h" | |||||
void test_all() { | |||||
} | |||||
int main() { | |||||
test_all(); | |||||
printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count); | |||||
return main_ret; | |||||
} |