Ziria Wireless Programming for Hardware Dummies Boidar Radunovi
Ziria: Wireless Programming for Hardware Dummies Božidar Radunović, Dimitrios Vytiniotis joint work with Gordon Stewart, Mahanth Gowda, Geoff Mainland http: //research. microsoft. com/en-us/projects/ziria/
Layout Introduction Wi. Fi in Ziria Compiling and Optimizing Ziria Hands-on Conclusions 2
Prelude: Software Defined Radios FPGA: Programmable digital electronics Traditionally used for prototyping and development in wireless industry Examples: WARP (all on FPGA), Zyng (So. C: Arm + FPGA) DSP: One or more VLIW cores optimized for signal processing Prototyping, but also commercially (many small cells on DSP) Examples: TI, Freescale CPUs: Digital interface between a radio and a CPU Prototyping and some deployments ($2 k GSM base-station) Examples: USRP (easy to program but slow), SORA (fast, μs latency), blade. RF (cheap and portable) 3
Why do we care about wireless research? Lots of innovation in PHY/MAC design New protocols/standards: 5 G, Io. T New PHY features: localization Fast, cheap and flexible deployments: (GSM, small cells) Security/hacking Popular experimental platform: GNURadio Relatively easy to program but slow, no real network deployment Modern wireless PHYs require high-rate DSP Real-time platforms [SORA, WARP, …] Achieve protocol processing requirements, difficult to program, no code portability, lots of low -level hand-tuning 4
Issues for wireless researchers CPU platforms (e. g. SORA) Manual vectorization, CPU placement Cache / data sizing optimizations FPGA platforms (e. g. WARP) Difficulty in writing and reusing code hampers innovation Latency-sensitive design, difficult for new students/researchers to break into Multi-core DSP (e. g. Freescale, TI) Heterogeneous architecture, implying data coherency and sync. problems Portability/readability Manually highly optimized code is difficult to read and maintain Also: practically impossible to target another platform 5
What is wrong with current tools? 6
Current SDR Software Tools Portable (FPGA/CPU), graphical interface: Simulink, Lab. View CPU-based: C/C++/Python Gnu. Radio, SORA Control and data separation Codi. Phy [U. of Colorado], Open. Radio [Stanford]: Specialized languages (DSL): Stream processing languages: Stream. It [MIT] DSLs for DSP/arrays, Feldspar [Chalmers]: we put more emphasis on control Spiral 7
Issues Programming abstraction is tied to execution model Programmer has to reason about how the program will be executed/optimized while writing the code Verbose programming Shared state Low-level optimization We next illustrate on Sora code examples (other platforms are have similar problems) 8
Running example: Wi. Fi receiver remove. DC Detect Carrier Packet start Channel Estimation Channel info Invert Channel Decode Header Invert Channel Packet info Decode Packet 9
How do we execute this on CPU? remove. DC Detect Carrier Packet start Channel Estimation Channel info Invert Channel Decode Header Invert Channel Packet info Decode Packet 10
Shared state CREATE_BRICK_SINK CREATE_BRICK_FILTER CREATE_BRICK_FILTER CREATE_BRICK_SINK CREATE_BRICK_FILTER CREATE_BRICK_DEMUX 5 CREATE_BRICK_FILTER CREATE_BRICK_FILTER Shared state CREATE_BRICK_FILTER 11
Separation of control and data Resetting whoever* is downstream *we don’t know who that is when we write this component 12
Verbosity - Declarations are written in host language - Language is not specialized, so often verbose - Hinders fast prototyping 13
Manual optimizations SORA_EXTERN_C SELECTANY extern const unsigned long gc_XXXLUT[256] = { 0 x 0000, 0 x 77073096, 0 x. EE 0 E 612 C, 0 x 990951 BA, 0 x 076 DC 419, 0 x 706 AF 48 F, 0 x. E 963 A 535, 0 x 9 E 6495 A 3, 0 x 0 EDB 8832, 0 x 79 DCB 8 A 4, 0 x. E 0 D 5 E 91 E, 0 x 97 D 2 D 988, 0 x 09 B 64 C 2 B, 0 x 7 EB 17 CBD, 0 x. E 7 B 82 D 07, 0 x 90 BF 1 D 91, 0 x 1 DB 71064, 0 x 6 AB 020 F 2, 0 x. F 3 B 97148, 0 x 84 BE 41 DE, . . . 0 x. BAD 03605, 0 x. CDD 70693, 0 x 54 DE 5729, 0 x 23 D 967 BF, 0 x. B 3667 A 2 E, 0 x. C 4614 AB 8, 0 x 5 D 681 B 02, 0 x 2 A 6 F 2 B 94, 0 x. B 40 BBE 37, 0 x. C 30 C 8 EA 1, 0 x 5 A 05 DF 1 B, 0 x 2 D 02 EF 8 D } FINL void Calc. XXXIncremental(IN UCHAR input, IN OUT PULONG p. XXX) { *p. XXX = (*p. XXX >> 8) ^ gc_XXXLUT[input ^ ((*p. XXX) & 0 x. FF)]; } FINL ULONG Calc. XXX(PUCHAR p. Byte, ULONG Length) { ULONG XXX = 0 x. FFFF; ULONG Index = 0; for (Index = 0; Index < Length; Index++) { XXX = ((XXX ) >> 8 ) ^ gc_XXXLUT[( p. Byte[Index] ) ^ (( XXX ) & 0 x 000000 FF )]; } return ~XXX; } What is this code doing? 14
Vectorization remove. DC Detect Carrier Packet start Channel Estimation - Beneficial to process items in chunks - But how large can chunks be? Channel info Invert Channel Decode Header Invert Channel Packet info Decode Packet 15
My Own Frustrations Implemented several PHY algorithms in FPGA Never been able to reuse them: Complexity of interfacing (timing and precision) was higher than rewriting! Implemented several PHY algorithms in Sora Better reuse but still difficult Spent 2 h figuring out which internal state variable I haven’t initialized when borrowed a piece of code from other project. I want tools to allow me to write reusable code and incrementally build ever more complex systems! 16
Improving this situation New wireless programming platform 1. 2. 3. Code written in a high-level language: reusable and easy to understand Compiler deals with low-level code optimization Same code compiles on different platforms (not there just yet!) Challenges 1. 2. Design PL abstractions that are intuitive and expressive Design efficient compilation schemes (to multiple platforms) What is special about wireless 1. 2. … that affects abstractions: large degree of separation b/w data and control … that affects compilation: need high-throughput stream processing 17
Our Choice: Domain Specific Language What are domain-specific languages? Examples: Make SQL Benefits: Language design captures specifics of the task This enables compiler to optimize better 18
Why is wireless code special? Wireless = lots of signal processing Control vs data flow separation Data processing elements: FFT/IFFT, Coding/Decoding, Scrambling/Descrambling Predictable execution and performance, independent of data Control flow elements: Header processing, rate adaptation 19
Programming model remove. DC Detect Carrier Packet start Channel Estimation Channel info Invert Channel Decode Header Invert Channel Packet info Decode Packet 20
How do we want code to look like? SORA_EXTERN_C SELECTANY extern FINL void Calc. XXXIncremental(IN UCHAR input, IN OUT PULONG p. XXX) const unsigned long gc_XXXLUT[256] = { for i in [0, CRC_X_WIDTH] { { *p. XXX = (*p. XXX >> 8) ^ if (start_state[i] == '1) then { 0 x 0000, 0 x 77073096, 0 x. EE 0 E 612 C, 0 x 990951 BA, gc_XXXLUT[input ^ ((*p. XXX) & 0 x. FF)]; for j in [0, CRC_S_WIDTH - 1] { 0 x 076 DC 419, 0 x 706 AF 48 F, 0 x. E 963 A 535, 0 x 9 E 6495 A 3, } out[i+1+j] : = out[i+1+j] ^ base[1+j]; 0 x 0 EDB 8832, 0 x 79 DCB 8 A 4, 0 x. E 0 D 5 E 91 E, 0 x 97 D 2 D 988, 0 x 09 B 64 C 2 B, 0 x 7 EB 17 CBD, 0 x. E 7 B 82 D 07, 0 x 90 BF 1 D 91, } FINL ULONG 0 x 1 DB 71064, 0 x 6 AB 020 F 2, 0 x. F 3 B 97148, 0 x 84 BE 41 DE, Calc. XXX(PUCHAR p. Byte, ULONG Length) for j in [0, CRC_X_WIDTH-i-1] { . . . { start_state[i+1+j] : = start_state[i+1+j] ^ base[1+j]; 0 x. BAD 03605, 0 x. CDD 70693, 0 x 54 DE 5729, 0 x 23 D 967 BF, ULONG XXX = 0 x. FFFF; } 0 x. B 3667 A 2 E, 0 x. C 4614 AB 8, 0 x 5 D 681 B 02, 0 x 2 A 6 F 2 B 94, ULONG Index = 0; } 0 x. B 40 BBE 37, 0 x. C 30 C 8 EA 1, 0 x 5 A 05 DF 1 B, 0 x 2 D 02 EF 8 D } } for (Index = 0; Index < Length; Index++) { XXX = ((XXX ) >> 8 ) ^ gc_XXXLUT[( p. Byte[Index] ) ^ (( XXX ) & 0 x 000000 FF )]; } return ~XXX; } 21
What do we not want to optimize? We assume efficient DSP libraries: FFT Viterbi/Turbo decoding Same are used in many standards: Wi. Fi, Wi. Max, LTE This is readily available: FPGA (Xilinx, Altera) DSP (coprocessors) CPUs (Volk, Sora libraries, Spiral) Most of PHY design is in connecting these blocks 22
Layout Introduction Wi. Fi in Ziria Compiling and Optimizing Ziria Hands-on Conclusions 23
Ziria and OFDM network basics Orthogonal Frequency Division Multiplexing The basis of industrial successful communication standards 802. 11 a, Wi. MAX, 4 G LTE, … Advantages: good use of spectrum with easy channel inversion Will show you next some basics of OFDM networks using Wi. Fi as a case study, along with corresponding code fragments in Ziria …
Complex data and signals Q (I, Q) φ I Represents signal φ t
Superimposing signals for transmission Note we used different frequencies 26
Transmitting OFDM symbols Consider N input complex samples … … … Inverse FFT … … …
Receiving OFDM symbols Due to orthogonality, FFT can recover the original vector … … … … FFT … … …
Why IFFT/FFT? We could after all directly send the data. . . … … … Answer: IFFT/FFT gives easy way to estimate and correct channel effects IFFT Channel
OFDM and channel estimation IFFT Multipath FFT So Simple!!
Actual Wi. Fi 802. 11 a OFDM transmission Data Pilots: used to estimate channel changes from one symbol transmission to the next IFFT Prefix affected from delayed version of previous signal Solution: “cyclic prefix” replicate prefix of signal in the end Guard bands: unused slots to better control interference
Modulation and demodulation Modulator 00 01 11 10 IFFT De-Modulator Channel 00 01 11 10 01 11 00 10 Example is QPSK, but other schemes used as well: BPSK, QAM 16, QAM 64, etc.
QPSK modulation in Ziria fun comp modulate_qpsk () { A new stream “computation” Take 2 bits from input into array of size 2 … repeat [8, 4] { (x : arr[2] bit) <- takes 2; emit ( if (x[0] == bit(0) && x[1] == bit(1)) then complex 16{re=-qpsk_mod_11 a; im= qpsk_mod_11 a } else if (x[0] == bit(0) && x[1] == bit(0)) then complex 16{re=-qpsk_mod_11 a; im=-qpsk_mod_11 a} else if (x[0] == bit(1) && x[1] == bit(1)) then complex 16{re=qpsk_mod_11 a; im=qpsk_mod_11 a} else Repeatedly … complex 16{re=qpsk_mod_11 a; im=-qpsk_mod_11 a} ) } } Emit … Github link here … this complex 16 value 00 01 11 10 Modulator 01 IFFT 11 qpsk_mod_11 a 00 10
Rest of TX pipeline Connect blocks like a pipe (“on the data path”) Github link here scrambler(default_scrmbl_st) >>> encode 12() >>> interleaver_qpsk() >>> modulate_qpsk()) . . 011010 Scrambler: spread input sequence to avoid peaks Encoder Interleaver Encoder: encodes input adding redundancy for automatic error correction, e. g. 1 -2 encoding, 2 -3 encoding, 3 -4 encoding Modulator IFFT Interleaver: calculates a (fixed) permutation of the input. To avoid bursty errors
Details of transmitting OFDM symbols in Ziria fun comp ifft() { var symbol: arr[FFT_SIZE] complex 16; var fftdata: arr[FFT_SIZE+CP_SIZE] complex 16; do { zero_complex 16(symbol); } repeat { (s: arr[64] complex 16) <- takes 64; do { symbol[FFT_SIZE-32, 32] : = s[0, 32]; symbol[0, 32] : = s[32, 32]; fftdata[CP_SIZE, FFT_SIZE] : = sora_ifft(symbol); -- Add CP fftdata[0, CP_SIZE] : = fftdata[FFT_SIZE, CP_SIZE]; } map_ofdm() ifft() Local mutable variables do { … } : execute nonstreaming statements emits fftdata; } } Array slices Call to C function (here SORA FFT) through “external function interface” Emit array
4 G LTE is based on similar blocks LTE uses similar design principles as Wi. Fi But much more complex (100 s of pages of specs) MAC and PHY are much more intertwined Any MAC modification likely implies PHY changes Figures from 3 GPP 36. 211, 36. 212
Blocks that maintain internal state: scrambler(default_scrmbl_st) >>>. . . 011010 Scrambler Encoder Initialize state Spread input sequence to avoid peaks State persists through all repetitions Update state Interleaver Modulator … fun comp scrambler(init_scrmbl_st: arr[7] bit) { var scrmbl_st: arr[7] bit : = init_scrmbl_st; repeat [8, 8] { x <- take; var tmp : bit; do { tmp : = (scrmbl_st[3] ^ scrmbl_st[0]); scrmbl_st[0: 5] : = scrmbl_st[1: 6]; scrmbl_st[6] : = tmp; }; emit (x^tmp) } } Raises the question: When is the state of a block initialized? Answer: when block becomes active in a processing path Next: activation of processing paths through the example of Wi. Fi receiver pipeline. . .
Wi. Fi receiver Ziria key aspect Detect transmission Active path remove. DC() cca() LTS(…) params Estimate channel Fixup cyclic prefix Data. Symbol() parse. Header() Decode • Explicit handover of control and passing of control parameters • Handover of control introduces and initializes new pipeline path Channel. Equalization(params) FFT() Deinterleave Invert effects of channel Demod. BPSK() Get. Data() Pilot. Track() h: Header. Info descramble() Decode(h) Deinterleave Demod(h) Remove guard band elements Remove pilots 011010 … to MAC layer
Wi. Fi receiver in Ziria code fun comp detect. STS() { remove. DC() >>> cca() } Ziria control handover : seq { x <- some-block ; next-block } Detect. STS() remove. DC() cca() det LTS(det) params Data. Symbol(det) FFT() Channel. Equalization(params) Decode. PLCP() parse. Header() Decode(h) Decode Deinterleave Demod. BPSK() Get. Data() Decode(h) Deinterleave Demod(h) fun comp receiver() { seq { det <- detect. STS() ; params <- LTS(det) ; Data. Symbol(det) >>> FFT() >>> Channel. Equalization(params) >>> Pilot. Track() >>> Get. Data() >>> receive. Bits() } } Pilot. Track() h: Header. Info descramble() fun comp receive. Bits() { seq { (h : Header. Info) <- Decode. PLCP() ; Decode(h) } } “in sequence” Keep running some -block until it returns x 011010 … to MAC layer Transfer control to new block. Control parameter x scopes over next -block
Ziria computers versus transformers Ziria type system ensures that the first block in seq is a computer (eventually returns) Ziria control handover : seq { x <- some-block ; next-block } A transformer block (like the scrambler) A computer block: eventually returns control repeat { x <- takes 64 ; . . . do stuff. . . ; emit e } seq { x <- takes 64; ; do more stuff ; return e } Keep running some -block until it returns x Transfer control to new block. Control parameter x scopes over next -block
A typical computer block: transmission detection Detect. STS() remove. DC() cca() Detect high correlation with known sequence => someone is transmitting seq { … do stuff … ; until (detected == true) { x <- takes 4; … do stuff … … try to detect … } ; … do stuff … ; return ret; } Let us examine the code on Github
Layout Introduction Wi. Fi in Ziria Compiling and Optimizing Ziria Hands-on Conclusions 42
Interfacing with other layers RF interface – synchronous 16 -bit complex input Radio: Sora, Blade. RF File: test samples, radio captures MAC interface IP, memory buffer (interfacing with MAC) External C libraries Vector library (v_add, v_sub, v_mul, v_correlate, etc) Communication library (fft, Viterbi decoder) Simple calling convention to add more functions
CPU execution model Actions: tick() B 1 Return values: YIELD (data_val) YIELD process(x) SKIP process(x) tick() B 2 DONE (control_val) Q: Why do we need ticks? A: Example: emit 1; emit 2; emit 3 1. B 2. tick() while it YIELDs or is DONE 2. When B 2 SKIPs go upstream A. B 1. tick() while it SKIPs or is DONE B. When YIELD(x) call B 2. process(x); goto 1
AST transformations to eliminate overheads fun comp test 1() = repeat { (x: int) <- take; emit x + 1; } in read[int] >>> test 1() >>> write[int] read >>> (let auto_map_6(x: int 32) = x + 1 in map auto_map_6) >>> (let auto_map_7(x: int 32) = x + 1 in map auto_map_7) >>> write buf_getint 32(pbuf_ctx, &__yv_tmp_ln 10_7_buf); __yv_tmp_ln 11_5_buf = auto_map_6_ln 2_9(__yv_tmp_ln 10_7_buf); __yv_tmp_ln 12_3_buf = auto_map_7_ln 2_10(__yv_tmp_ln 11_5_buf); buf_putint 32(pbuf_ctx, __yv_tmp_ln 12_3_buf); 45
Converting pipeline loops to tight innode loops let block_VECTORIZED (u: unit) = var y: int; repeat let vect_up_wrap_46 () = var vect_ya_48: arr[4] int; (vect_xa_47 : arr[4] int) <- take 1; __unused_174 <- times 4 (vect_j_50. (x : int) <- return vect_xa_47[0*4+vect_j_50*1+0]; __unused_1 <- return y : = x+1; return vect_ya_48[vect_j_50*1+0] : = y); emit vect_ya_48 in vect_up_wrap_46 (tt) let block_VECTORIZED (u: unit) = var y: int; repeat let vect_up_wrap_46 () = var vect_ya_48: arr[4] int; (vect_xa_47 : arr[4] int) <- take 1; emit let __unused_174 = for vect_j_50 in 0, 4 { let x = vect_xa_47[0*4+vect_j_50*1+0] in let __unused_1 = y : = x+1 in vect_ya_48[vect_j_50*1+0] : = y } in vect_ya_48 in vect_up_wrap_46 (tt) 46
Further optimizations 1. 2. 3. 4. 5. Responsible for most performance benefits Static partial evaluation, aggressive inlining Reuse memory, avoid redundant mem-copying Compile expressions to lookup tables (LUTs) Pipeline vectorization transformation Programmer guided top-level pipeline parallelization 47
Pipeline vectorization Problem statement: increase the width of pipelines (input and output size of each block) Benefits of vectorization Fatter pipelines => lower dataflow graph interpretive overhead Array inputs vs individual elements => more data locality Especially for bit-arrays, enhances effects of LUTs NB: A manual optimization in SDR platforms, makes code incompatible with and non-reusable in different pipelines 48
Vectorization challenges How to find the correct and optimal widths: key novelty M: special “mitigator” blocks that convert widths Detect. STS() remove. DC() 4 4 M 16 16 M M 80 cca() of Ziria Static analysis of input and outputs of every block Search of “uniform fat pipelines” solution Difficulty: must not take more elements nor emit fewer elements when control flow switches Interested in details? Please read ASPLOS’ 15 paper det LTS(det) 144 params Data. Symbol(det) 64 FFT() 64 Channel. Equalization(params) 64 Decode. PLCP() parse. Header() Decode(h) 8 24 Decode h: Header. Info descramble() 8 48 Decode(h) Deinterleave 96 48 Deinterleave Demod. BPSK() 96 48 Get. Data() 64 Pilot. Track() Demod(h) 011010 … to MAC layer Actual vector sizes computed automatically on Wi. Fi receiver
Vectorization and LUT synergy let comp scrambler() = var scrmbl_st: arr[7] bit : = {'1, '1, '1, '1}; var tmp, y: bit; repeat { (x: bit) <- take; do { tmp : = (scrmbl_st[3] ^ scrmbl_st[0]); scrmbl_st[0: 5] : = scrmbl_st[1: 6]; scrmbl_st[6] : = tmp; y : = x ^ tmp }; emit (y) } let comp v_scrambler () = var scrmbl_st: arr[7] bit : = {'1, '1, '1, '1}; var tmp, y: bit; var vect_ya_26: arr[8] bit; let auto_map_71(vect_xa_25: arr[8] bit) = LUT for vect_j_28 in 0, 8 { vect_ya_26[vect_j_28] : = tmp : = scrmbl_st[3]^scrmbl_st[0]; scrmbl_st[0: +6] : = scrmbl_st[1: +6]; scrmbl_st[6] : = tmp; y : = vect_xa_25[0*8+vect_j_28]^tmp; return y }; return vect_ya_26 in map auto_map_71 50
Highlights of performance evaluation (experiments on i 7 )
Throughput (Wi. Fi RX) 52
Throughput (Wi. Fi TX) 53
Effects of optimizations (Wi. Fi RX) 54
Effects of optimizations (Wi. Fi TX) Vectorization alone not great (reason: bit array addressing) but enables LUTs! 55
Latency & real-world performance Throughput only gives average latency We also evaluate tail latency: see ASPLOS paper for details • Real-world experiments on SORA hardware 98% packet success rate • • 56
Layout Introduction Wi. Fi in Ziria Compiling and Optimizing Ziria Hands-on Conclusions 57
Ziria Toolchain
Interfacing with other layers RF interface – synchronous 16 -bit complex input Radio: Sora, Blade. RF File: test samples, radio captures MAC interface IP, memory buffer (interfacing with MAC) External C libraries Vector library (v_add, v_sub, v_mul, v_correlate, etc) Communication library (fft, Viterbi decoder) Simple calling convention to add more functions
Flexibility of the toolchain TEST PERFORMANCE Easy to create unit tests Easy to profile fun comp transmitter() { seq{ emits create. STSin. Time() ; emits create. LTSin. Time() ; (transform_w_header() >>> map_ofdm() >>> ifft()) } } fun comp receiver() { fun comp encdec_atten(c: int 16) { seq{ det<-detect. Preamble(1000) let comp main = read[bit] repeat >>> scrambler() >>> write[bit]; { ; params <- (LTS(det. shift, det. max. Corr)) (x: complex 16) <-take; ; Data. Symbol(det. shift) emit --input-file-name=test_scramble. infile complex 16{re=x. re/c; im=x. im/c}. /test_scramble. out --input-file-mode=dbg . /test_scrambler. out--input=file --input=dummy --dummy-samples=100000 --output=dummy >>> FFT() } --output=file --output-file-name=test_scramble. outfile --output-file-mode=dbg >>> Channel. Equalization(params) } >>> Pilot. Track() Total input items (including EOF): 100008 (100008 items: 100000 (100000 B) 25 (25 B), output items: 24 B), (24 output B) >>> Get. Data() Time Elapsed: 1514276 201396 ususlet comp main = read >>> receive. Bits() >>> transform_w_header() Bytes copied: 0 } >>> encdec_atten(16*5). . /tools/Blink. Diff -f test_scramble. outfile -g test_scramble. outfile. ground -d -v -n 0. 9 } >>> receive. Bits() Matching! (EOF) (Accuracy 100. 0%) >>> write
Debugging Ziria compiler guarantees same execution of optimized and un-optimized code Debugging in C easy if (i. Energy_ln 124_187 > 1000 L && no. Inc_ln 118_183 > 4 L && (old. Corr_ln 115_180 > max. Corr_ln 109_174 || old. Ind_ln 116_181 != bounds_check(7, 3 + 0, ". . /scramble. blk: 38: 25 -26"); max. Ind_ln 110_175) && norm. Max. Corrln 223_319 > 96 L) { bit. Read(scrmbl_st, 3, &bitres 11); detected_ln 119_184 = 1 U; } bounds_check(7, 0 + 0, ". . /scramble. blk: 38: 40 -41"); bit. Read(scrmbl_st, 0, &bitres 12); if (old. Old. Corr_ln 114_179 < old. Corr_ln 115_180 && old. Corr_ln 115_180 < tmp_blk_r 17 = bitres 11 ^ bitres 12; max. Corr_ln 109_174 && old. Old. Ind_ln 117_182 == old. Ind_ln 116_181 && UNIT; old. Ind_ln 116_181 == max. Ind_ln 110_175) { bounds_check(7, 0 + 5, ". . /scramble. blk: 39: 7 -39"); no. Inc_ln 118_183 = no. Inc_ln 118_183 + 1 L; bounds_check(7, 1 + 5, ". . /scramble. blk: 39: 34 -39"); } else { bit. Arr. Read(scrmbl_st, 1, 6, bitarrres 13); no. Inc_ln 118_183 = 0 L; } bit. Arr. Write(bitarrres 13, 0, 6, scrmbl_st); UNIT; old. Old. Corr_ln 114_179 = old. Corr_ln 115_180; bounds_check(7, 6 + 0, ". . /scramble. blk: 40: 7 -26"); old. Corr_ln 115_180 = max. Corr_ln 109_174; bit. Write(scrmbl_st, 6, tmp_blk_r 17); old. Old. Ind_ln 117_182 = old. Ind_ln 116_181; UNIT; old. Ind_ln 116_181 = max. Ind_ln 110_175; return x_blk_r 15 ^ tmp_blk_r 17; iterind_ln 120_185 = iterind_ln 120_185 + 1 L; 61
Hands-on experience
Before We Start: Useful Locations Github repository: https: //github. com/dimitriv/Ziria User guide: <github>/blob/master/doc/User. Guide/language. md Grammar: <github>/blob/master/doc/User. Guide/grammar. md Windows path: C: UsersDemoZiriacompilercode Cygwin path: /cygdrive/c/Users/Demo/Ziria/compiler/code/ 63
Before We Start: Refresh Ziria distro Start Cygwin Go to: cd /cygdrive/c/Users/Demo/Ziria/compiler Pull latest release from Git. Hub git pull Copy latest binaries: cp binaries/wplc-win 64 -110515. exe wplc. exe cp binaries/Blink. Diff-win 64 -110515. exe tools/Blink. Diff. exe 64
Let’s test Scrambler Go to: <Ziria-path>/Wi. Fi/transmitter/tests Edit test_scramble. blk Type: make –B test_scramble. test 65
How about performance? Go to: <Ziria-path>/Wi. Fi/transmitter/perf Edit test_scramble_perf. blk Type: make –B test_scramble_perf 66
Hello World Go to: /cygdrive/c/Users/Demo/Ziria/compiler/code/examples First Ziria program – flip bits in input stream – test. blk: fun comp flip() { repeat { x <- take; emit (x ^ ‘ 1); } } let comp main = read >>> flip() >>> write Input file (test. infile): 0, 1, 1, 1, 0, 1 Run: make –B test. outfile && cat test. outfile
Performance Run: make –B test. out Profile with: . /test. out --input=dummy --dummy-samples=10000 --output=dummy Run: EXTRAOPTS=‘—vectorize’ make –B test. perf Run: EXTRAOPTS=‘—vectorize —autolut’ make –B test. perf 68
Why Auto. LUT didn’t work Vectorizer is too aggressive! (use —ddump-fold) We can use annotations Run: make –B test. perf fun comp flip() { make –B test. perf Run: EXTRAOPTS=‘—vectorize’ repeat [8, 8] { Run: EXTRAOPTS=‘—vectorize —autolut’ make –B test. perf x <- take; emit (x ^ ‘ 1); } } let comp main = read >>> flip() >>> write 69
More serious example We want to double the size of LTS preamble in Wi. Fi to improve estimation Modify Wi. Fi transmitter (transmitter. blk) to send two LTS preambles Modify Wi. Fi receiver (receiver. blk) to still receive packets (for simplicity we ignore the second preamble, taking 2 x 80 samples) Transmitter: <Ziria-path>/Wi. Fi/transmitter. blk Receiver: <Ziria-path>/Wi. Fi/receiver. blk Test: make -B test_tx. outfile cp test_tx. outfile test_rx. infile make -B test_rx. test 70
Solution fun comp transmitter() { fun comp receiver() { seq{ emits create. STSin. Time() seq{ det<-detect. Preamble(1000) ; emits create. LTSin. Time() ; params<-(LTS(det. shift, det…)) ; emits create. LTSin. Time() ; x <- takes 160 ; (transform_w_header() >>> map_ofdm() >>> ifft()) ; Data. Symbol(det. shift) } } >>> FFT() >>> Channel. Equalization(params) >>> Pilot. Track() >>> Get. Data() >>> receive. Bits() }} 71
Wi. Fi Sniffer Demo 72
Layout Introduction Wi. Fi in Ziria Compiling and Optimizing Ziria Hands-on Conclusions 73
Status Released to Git. Hub under Apache 2. 0 https: //github. com/dimitriv/Ziria Wi. Fi implementation included in release Currently: RF: SORA, Blade. RF Architectures: CPU/SIMD Looking into porting to other CPU-based SDRs 74
Conclusions More wireless innovations will happen at intersections of PHY and MAC levels We need prototypes and test-beds to evaluate ideas PHY programming in its infancy Difficult, limited portability and scalability Steep learning curve, difficult to compare and extend previous works Wireless programming is easy and fun – go for it! http: //research. microsoft. com/en-us/projects/ziria/ 75
Thank you! http: //research. microsoft. com/en-us/projects/ziria/ https: //github. com/dimitriv/Ziria 76
- Slides: 76