diff --git a/llvm/lib/Transforms/Scaffold/GenQASM.cpp b/llvm/lib/Transforms/Scaffold/GenQASM.cpp index c7691a0bb..63577f1e8 100644 --- a/llvm/lib/Transforms/Scaffold/GenQASM.cpp +++ b/llvm/lib/Transforms/Scaffold/GenQASM.cpp @@ -933,7 +933,6 @@ void GenQASM::genQASM(Function* F) else if(fToPrint.find("Tdag") != string::npos) fToPrint = "Tdag"; else if(fToPrint.find("X.") != string::npos) fToPrint = "X"; else if(fToPrint.find("Z.") != string::npos) fToPrint = "Z"; - else if(fToPrint.find("afree") != string::npos) continue; std::replace(fToPrint.begin(), fToPrint.end(), '.', '_'); std::replace(fToPrint.begin(), fToPrint.end(), '-', '_'); diff --git a/scaffold.sh b/scaffold.sh index d5c3ac921..8a58ae8ef 100755 --- a/scaffold.sh +++ b/scaffold.sh @@ -2,31 +2,36 @@ ROOT=$(dirname $0) -# Get CTQG path -export CTQG_PATH=${ROOT}/ctqg/CTQG -if [ $(echo $PATH | grep ${CTQG_PATH} | wc -l) -eq 0 ]; then - export PATH=$PATH:$CTQG_PATH +# Get RKQC path +export RKQC_PATH=${ROOT}/rkqc +if [ $(echo $PATH | grep ${RKQC_PATH} | wc -l) -eq 0 ]; then + export PATH=$PATH:$RKQC_PATH fi function show_help { - echo "Usage: $0 [-h] [-rqfRTFcpd] [-l #] [-P #] .scaffold" + echo "Usage: $0 [-hv] [-rqfRFcpds] [-L #] .scaffold" echo " -r Generate resource estimate (default)" echo " -q Generate QASM" echo " -f Generate flattened QASM" echo " -R Disable rotation decomposition" echo " -T Disable Toffoli decomposition" - echo " -l Levels of recursion to run (default=1)" - echo " -P Set precision of rotation decomposition in decimal digits (default=10)" + echo " -l Levels of recursion to run (default=1)" echo " -F Force running all steps" echo " -c Clean all files (no other actions)" echo " -p Purge all intermediate files (preserves specified output," echo " but requires recompilation for any new output)" echo " -d Dry-run; show all commands to be run, but do not execute" + echo " -s Generate QX Simulator input file" + echo " -v Show current Scaffold version information" +} + +function show_version { + echo "Scaffold - Release 2.0 (July 10, 2016) Beta" } # Parse opts OPTIND=1 # Reset in case getopts has been used previously in the shell. -ctqg=0 +rkqc=0 clean=0 dryrun="" force=0 @@ -34,22 +39,27 @@ purge=0 res=0 rot=1 toff=1 +flat=0 +qc=0 targets="" -precision=4 -while getopts "h?cdfFpqrRT:l:P:" opt; do +while getopts "h?vcdfsFpqrRTl:" opt; do case "$opt" in h|\?) show_help exit 0 ;; + v) + show_version + exit 0 + ;; c) clean=1 ;; d) dryrun="--dry-run" - ;; + ;; F) force=1 ;; - f) targets="${targets} flat" - ;; + f) flat=1 + ;; p) purge=1 ;; q) targets="${targets} qasm" @@ -60,14 +70,23 @@ while getopts "h?cdfFpqrRT:l:P:" opt; do ;; T) toff=0 ;; + s) qc=1 + ;; l) targets="${targets} SQCT_LEVELS=${OPTARG}" ;; - P) precision=${OPTARG} esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift +if [ ${flat} -eq 1 ]; then + targets="${targets} flat" +fi + +if [ ${qc} -eq 1 ]; then + targets="${targets} qc" +fi + # Put resources at the end so it is easy to read if [ ${res} -eq 1 ]; then targets="${targets} resources" @@ -101,17 +120,15 @@ dir="$(dirname ${filename})/" file=$(basename ${filename} .scaffold) cfile="${file}.*" -if [ $(egrep '^ctqg.*{\s*' ${filename} | wc -l) -gt 0 ]; then - ctqg=1 +if [ $(egrep '^rkqc.*{\s*' ${filename} | wc -l) -gt 0 ]; then + rkqc=1 toff=1 - #dir="" fi if [ ${clean} -eq 1 ]; then make -f $ROOT/scaffold/Scaffold.makefile ${dryrun} ROOT=$ROOT DIRNAME=${dir} FILENAME=${filename} FILE=${file} CFILE=${cfile} clean exit fi -make -f $ROOT/scaffold/Scaffold.makefile ${dryrun} ROOT=$ROOT DIRNAME=${dir} FILENAME=${filename} FILE=${file} CFILE=${cfile} TOFF=${toff} CTQG=${ctqg} ROTATIONS=${rot} PRECISION=${precision} ${targets} +make -f $ROOT/scaffold/Scaffold.makefile ${dryrun} ROOT=$ROOT DIRNAME=${dir} FILENAME=${filename} FILE=${file} CFILE=${cfile} TOFF=${toff} RKQC=${rkqc} ROTATIONS=${rot} ${targets} exit 0 - diff --git a/scaffold/Scaffold.makefile b/scaffold/Scaffold.makefile index 1687aaf0b..482fd15ad 100644 --- a/scaffold/Scaffold.makefile +++ b/scaffold/Scaffold.makefile @@ -3,20 +3,17 @@ PERL=/usr/bin/perl PYTHON=/usr/bin/python ROOT=".." -DIRNAME="" FILENAME="" FILE="" CFILE="" -TOFF=0 -CTQG=0 -ROTATIONS=0 +DIRNAME="" BUILD=$(ROOT)/build/Release+Asserts SQCTPATH=$(ROOT)/Rotations/sqct/rotZ GRIDSYNTHPATH=$(ROOT)/Rotations/gridsynth/gridsynth ROTATIONPATH=$(GRIDSYNTHPATH) # select rotation decomposition tool -PRECISION="" +SCRIPTSPATH=$(ROOT)/scripts/ # select rotation decomposition tool CC=$(BUILD)/bin/clang OPT=$(BUILD)/bin/opt @@ -32,11 +29,14 @@ SCAFFOLD_LIB=$(ROOT)/build/Release+Asserts/lib/Scaffold.dylib endif +RKQC=0 +ROTATIONS=0 +TOFF=0 + ################################ # Resource Count Estimation ################################ resources: $(FILE).resources - @cat $(FILE).resources ################################ # Flat QASM generation @@ -48,30 +48,24 @@ flat: $(FILE).qasmf ################################ qasm: $(FILE).qasmh -.PHONY: res_count qasm flat +################################ +# QX Simulator generation +################################ +qc: $(FILE).qc + +.PHONY: resources qasm flat qc ################################ # Intermediate targets ################################ -# Pre-process CTQG +# Compile Scaffold to LLVM bytecode + $(FILE)_merged.scaffold: $(FILENAME) - @if [ $(CTQG) -eq 1 ]; then \ - echo "[Scaffold.makefile] Extracting CTQG from Scaffold ..."; \ - $(PERL) $(ROOT)/ctqg/trans/pre_process.pl $(FILENAME); \ - echo "[Scaffold.makefile] Compiling CTQG ..."; \ - $(ROOT)/ctqg/CTQG/ctqg $(CFILE).ctqg; \ - echo "[Scaffold.makefile] Merging CTQG output back into Scaffold ..."; \ - $(PERL) $(ROOT)/ctqg/trans/trans.pl $(CFILE).qasm > trans.qasm; \ - mv trans.qasm $(CFILE).qasm; \ - $(PERL) $(ROOT)/ctqg/trans/merge.pl $(CFILE).qasm; \ - else \ - cp $(FILENAME) $(FILE)_merged.scaffold; \ - fi + @cp $(FILENAME) $(FILE)_merged.scaffold -# Compile Scaffold to LLVM bytecode $(FILE).ll: $(FILE)_merged.scaffold - @echo "[Scaffold.makefile] Compiling $(FILE)_merged.scaffold ..." - @$(CC) $(FILE)_merged.scaffold $(CC_FLAGS) -o $(FILE).ll + @echo "[Scaffold.makefile] Compiling $(FILE).scaffold ..." + @$(CC) $(FILE)_merged.scaffold $(CC_FLAGS) -o $(FILE).ll $(FILE)1.ll: $(FILE).ll @echo "[Scaffold.makefile] Transforming cbits ..." @@ -117,40 +111,53 @@ $(FILE)7.ll: $(FILE)6.ll cp $(FILE)6.ll $(FILE)7.ll; \ elif [ $(ROTATIONS) -eq 1 ]; then \ echo "[Scaffold.makefile] Decomposing Rotations ..."; \ - if [ ! -e /tmp/epsilon-net.0.bin ]; then echo "Generating decomposition databases"; fi; \ + if [ ! -e /tmp/epsilon-net.0.bin ]; then echo "Generating decomposition databases; this may take up to an hour"; fi; \ export ROTATIONPATH=$(ROTATIONPATH); \ - export PRECISION=$(PRECISION); \ $(OPT) -S -load $(SCAFFOLD_LIB) -Rotations $(FILE)6.ll -o $(FILE)7.ll > /dev/null; \ else \ cp $(FILE)6.ll $(FILE)7.ll; \ fi # Remove any code that is useless after optimizations -$(FILE)10.ll: $(FILE)7.ll +$(FILE)8.ll: $(FILE)7.ll @echo "[Scaffold.makefile] Internalizing and Removing Unused Functions ..." - @$(OPT) -S $(FILE)7.ll -internalize -globaldce -deadargelim -o $(FILE)10.ll > /dev/null + @$(OPT) -S $(FILE)7.ll -internalize -globaldce -deadargelim -o $(FILE)8.ll > /dev/null + +# Compile RKQC +$(FILE)9.ll: $(FILE)8.ll + @if [ $(RKQC) -eq 1 ]; then \ + echo "[Scaffold.makefile] Compiling RKQC Functions ..."; \ + $(OPT) -S -load $(SCAFFOLD_LIB) -GenRKQC $(FILE)8.ll -o $(FILE)9.ll > /dev/null 2> $(FILE).errs; \ + else \ + mv $(FILE)8.ll $(FILE)9.ll; \ + fi # Perform Toffoli decomposition if TOFF is 1 -$(FILE)11.ll: $(FILE)10.ll +$(FILE)11.ll: $(FILE)9.ll @if [ $(TOFF) -eq 1 ]; then \ echo "[Scaffold.makefile] Toffoli Decomposition ..."; \ - $(OPT) -S -load $(SCAFFOLD_LIB) -ToffoliReplace $(FILE)10.ll -o $(FILE)11.ll > /dev/null; \ + $(OPT) -S -load $(SCAFFOLD_LIB) -ToffoliReplace $(FILE)9.ll -o $(FILE)11.ll > /dev/null; \ else \ - cp $(FILE)10.ll $(FILE)11.ll; \ + cp $(FILE)9.ll $(FILE)11.ll; \ fi +# Insert reverse functions if REVERSE is 1 +$(FILE)12.ll: $(FILE)11.ll + @echo "[Scaffold.makefile] Inserting Reverse Functions..." + @$(OPT) -S -load $(SCAFFOLD_LIB) -FunctionReverse $(FILE)11.ll -o $(FILE)12.ll > /dev/null + # Generate resource counts from final LLVM output -$(FILE).resources: $(FILE)11.ll +$(FILE).resources: $(FILE)12.ll @echo "[Scaffold.makefile] Generating resource count ..." - @$(OPT) -load $(SCAFFOLD_LIB) -ResourceCount $(FILE)11.ll 2> $(FILE).resources > /dev/null + @$(OPT) -load $(SCAFFOLD_LIB) -ResourceCount $(FILE)12.ll 2> $(FILE).resources > /dev/null @echo "[Scaffold.makefile] Resources written to $(FILE).resources ..." -# Generate hierarchical QASM -$(FILE).qasmh: $(FILE)11.ll +$(FILE).qasmh: $(FILE)12.ll @echo "[Scaffold.makefile] Generating hierarchical QASM ..." - @$(OPT) -load $(SCAFFOLD_LIB) -gen-qasm $(FILE)11.ll 2> $(FILE).qasmh > /dev/null + @$(OPT) -load $(SCAFFOLD_LIB) -gen-qasm $(FILE)12.ll 2> $(FILE).qasmh > /dev/null @echo "[Scaffold.makefile] Hierarchical QASM written to $(FILE).qasmh ..." + # Translate hierarchical QASM back to C++ for flattening $(FILE)_qasm.scaffold: $(FILE).qasmh @echo "[Scaffold.makefile] Generating flattened QASM ..." @@ -164,15 +171,19 @@ $(FILE)_qasm: $(FILE)_qasm.scaffold $(FILE).qasmf: $(FILE)_qasm @./$(FILE)_qasm > $(FILE).tmp @cat fdecl.out $(FILE).tmp > $(FILE).qasmf - @echo "[Scaffold.makefile] Flat QASM written to $(FILE).qasmf ..." + @echo "[Scaffold.makefile] Flat QASM written to $(FILE).qasmf ..." + +$(FILE).qc: $(FILE).qasmf + @echo "[Scaffold.makefile] Transforming flat QASM to QX Simulator input ..." + @$(SHELL) $(ROOT)/scripts/qasmf2qc.sh $(FILE).qasmf + @echo "[Scaffold.makefile] QX Simulator input written to $(FILE).qc ..." # purge cleans temp files purge: - @rm -f $(FILE)_merged.scaffold $(FILE)_noctqg.scaffold $(FILE).ll $(FILE)1.ll $(FILE)1a.ll $(FILE)1b.ll $(FILE)2.ll $(FILE)3.ll $(FILE)4.ll $(FILE)5.ll $(FILE)5a.ll $(FILE)6.ll $(FILE)6tmp.ll $(FILE)7.ll $(FILE)8.ll $(FILE)9.ll $(FILE)10.ll $(FILE)11.ll $(FILE)tmp.ll $(FILE)_qasm $(FILE)_qasm.scaffold fdecl.out $(CFILE).ctqg $(CFILE).c $(CFILE).signals $(FILE).tmp sim_$(CFILE) $(FILE).*.qasm + @rm -f $(FILE)_merged.scaffold $(FILE)_no.scaffold $(FILE).ll $(FILE)1.ll $(FILE)1a.ll $(FILE)1b.ll $(FILE)2.ll $(FILE)3.ll $(FILE)4.ll $(FILE)5.ll $(FILE)5a.ll $(FILE)6.ll $(FILE)6tmp.ll $(FILE)7.ll $(FILE)8.ll $(FILE)9.ll $(FILE)10.ll $(FILE)11.ll $(FILE)12.ll $(FILE)tmp.ll $(FILE)_qasm $(FILE)_qasm.scaffold fdecl.out $(CFILE).ctqg $(CFILE).c $(CFILE).signals $(FILE).tmp sim_$(CFILE) $(FILE).*.qasm # clean removes all completed files clean: purge - @rm -f $(FILE).resources $(FILE).qasmh $(FILE).qasmf + @rm -f $(FILE).resources $(FILE).qasmh $(FILE).qasmf $(FILE).qc .PHONY: clean purge - diff --git a/scaffold/flatten-qasm.py b/scaffold/flatten-qasm.py index 9d4485a91..cf52c37c6 100644 --- a/scaffold/flatten-qasm.py +++ b/scaffold/flatten-qasm.py @@ -12,6 +12,7 @@ def process_qasm(fname): qgates_4 = ['PrepX','PrepZ'] qgates_5 = ['MeasX','MeasZ'] qgates_6 = ['Rz'] + qgates_7 = ['afree'] gateNames = { @@ -30,7 +31,8 @@ def process_qasm(fname): 'Rz':'Rz', 'CNOT':'CNOT', #'CX', 'Toffoli':'Tof', - 'Fredkin':'Fredkin' + 'Fredkin':'Fredkin', + 'afree':'afree' } pattern_qbit_decl = re.compile(r"\s*\bqbit\b\s+(?P\w+)\s*\[\s*(?P\d+)\s*\]\s*;") @@ -97,6 +99,13 @@ def process_qasm(fname): instFnName = 'qg_'+q fstr = 'void '+instFnName+'(char* a, double b){ printf("' +gateNames[q] +' %s,%f\\n",a,b); }\n' fout.write(fstr) + + for q in qgates_7: + instFnName = q + fstr = 'void '+instFnName+'(char** a, int b ){ for(int i = 0; i < b; i++){ printf("' +gateNames[q] +' %s\\n",(*a)); a++; }}\n' + + fout.write(fstr) + fout.write('\n')