├── floem ├── path.py ├── programs │ ├── hello.h │ ├── hello.c │ ├── simple_math_ext.c │ ├── hello.py │ ├── func_increment1.py │ ├── hello_depend.py │ ├── memory_region.py │ ├── func_increment2.py │ ├── join_inject2.py │ ├── inc2_function.py │ ├── inc2_function_ext.py │ ├── join_inject.py │ ├── pipeline_state_empty_port1.py │ ├── func_insert_start_element.py │ ├── spec_impl.py │ ├── nested_compo_in_impl.py │ ├── nested_spec_impl_in_compo.py │ ├── spec_impl_at.py │ ├── socket_recv_real.py │ ├── pipeline_state_simple.py │ ├── state_shared.py │ ├── probe_spec_impl.py │ ├── pipeline_state_empty_port3.py │ ├── pipeline_state_empty_port2.py │ ├── probe_multi.py │ ├── queue_custom.py │ ├── pipeline_state_nonempty.py │ ├── smart_queue_entry_simpler.py │ ├── hton1.py │ ├── smart_queue_entry.py │ └── queue_default.py ├── __init__.py ├── programs_perpacket_state │ ├── cavium_varsize_enq_test.c │ ├── queue_shared_p2_main.c │ ├── queue_shared_data1_main.c │ ├── cavium_varsize_deq_test.c │ ├── queue_shared_data2_main.c │ ├── queue_shared_p1_main.c │ ├── auto_inserted_queue.py │ ├── free_alternate.py │ ├── multiple_buffers_pipeline.py │ ├── free_zero_or_one.py │ ├── queue_shared_p2.h │ ├── queue_shared_p1.h │ ├── queue_shared_data2.h │ ├── smart_queue_multi_funcs.py │ ├── queue_shared_pointer.py │ ├── queue_shared_data1.h │ ├── queue_shared_data.py │ ├── smart_queue_entry.py │ ├── smart_queue_many2one.py │ ├── cavium_varsize_deq.py │ └── cavium_varsize_enq.py ├── programs_cavium │ ├── hello.py │ ├── shared_state.py │ ├── outqueue.py │ ├── packet_read.py │ └── packet_build.h ├── include │ ├── util.h │ ├── socket.h │ ├── linux_hugepage.h │ └── shm.h ├── include_cavium │ ├── floem-dma.h │ ├── floem-queue.h │ ├── floem-cache.h │ ├── floem-queue-manage.h │ └── floem-util.h ├── collection.py ├── empty_port.py ├── cparser.py ├── target.py ├── standard_elements.py ├── hton.py ├── cache_tests │ ├── one_in_one_out.py │ └── one_in_one_out_state.py ├── library.py ├── queue_smart.py ├── process_handling.py └── workspace.py ├── .gitignore ├── apps ├── memcached_cpu_only │ ├── test_cache │ ├── test_no_steer │ ├── test_nic.c │ ├── test_no_steer.c │ ├── test_cache.c │ ├── settings.c │ ├── test_app.c │ ├── nicif.h │ └── loc │ │ └── cloc_nic_offload.py ├── benchmarks_simple │ ├── test_queue.c │ ├── reply.py │ ├── inqueue2.py │ ├── inout.py │ ├── inqueue1core.py │ ├── request.py │ └── inqueue.py ├── benchmarks_param_update │ ├── test_queue_nic.c │ ├── test_queue.c │ ├── param_update.c │ ├── main.py │ └── request.py ├── benchmarks_network_func │ ├── aes_ni.h │ ├── count-min-sketch.h │ ├── pkt-utils.h │ ├── nic-compute.h │ ├── aes.h │ ├── cluster-setup.h │ └── count-min-sketch.c ├── storm │ ├── hash.h │ ├── test_storm_nic.c │ ├── dummy.c │ ├── collections │ │ ├── stack.h │ │ ├── flipbuffer.h │ │ └── hash_table.h │ ├── worker.h │ ├── rank.c │ ├── storm.h │ └── dccp.h ├── memcached_nic_only │ └── settings.c ├── parameter_server │ └── message.py ├── memcached_cached │ ├── settings.c │ └── test_app.c └── memcached_split │ ├── test_app.c │ ├── nicif.h │ └── settings.c ├── configure.py ├── setup.py ├── mockup ├── memcached │ ├── comm.h │ └── memcached.c └── TCP │ ├── tcp_minimal_pulling.c │ ├── tcp.c │ └── tcp_component.c ├── doc ├── runtime.md └── library-of-c-functions.md └── LICENSE /floem/path.py: -------------------------------------------------------------------------------- 1 | srcpath = "" 2 | -------------------------------------------------------------------------------- /floem/programs/hello.h: -------------------------------------------------------------------------------- 1 | void print_hello(); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.DS_Store 3 | *.pyc 4 | *.o 5 | tmp.c 6 | tmp 7 | CAVIUM.* 8 | app.* 9 | dpdk.* 10 | -------------------------------------------------------------------------------- /apps/memcached_cpu_only/test_cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mangpo/floem/HEAD/apps/memcached_cpu_only/test_cache -------------------------------------------------------------------------------- /apps/memcached_cpu_only/test_no_steer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mangpo/floem/HEAD/apps/memcached_cpu_only/test_no_steer -------------------------------------------------------------------------------- /floem/programs/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void print_hello() { 5 | printf("hello world!\n"); 6 | } -------------------------------------------------------------------------------- /floem/__init__.py: -------------------------------------------------------------------------------- 1 | from dsl import * 2 | from library import * 3 | from net import * 4 | from graph import Cache 5 | from compiler import Compiler 6 | import queue_smart, cache_smart 7 | 8 | -------------------------------------------------------------------------------- /apps/benchmarks_simple/test_queue.c: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | init(argv); 5 | 6 | run_threads(); 7 | while(1) pause(); 8 | kill_threads(); 9 | } 10 | -------------------------------------------------------------------------------- /configure.py: -------------------------------------------------------------------------------- 1 | import commands 2 | 3 | # Create path.rtk 4 | status, abs_path = commands.getstatusoutput("pwd") 5 | f = open("floem/path.py", "w") 6 | f.write("srcpath = \"" + abs_path + "/floem\"\n") 7 | print "path.py is created." 8 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/cavium_varsize_enq_test.c: -------------------------------------------------------------------------------- 1 | #include "varsize_enq.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | init(argv); 5 | run_threads(); 6 | while(1) pause(); 7 | kill_threads(); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /apps/benchmarks_param_update/test_queue_nic.c: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | #include "protocol_binary.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | init(argv); 6 | init_params(); 7 | 8 | run_threads(); 9 | while(1) pause(); 10 | kill_threads(); 11 | } -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_p2_main.c: -------------------------------------------------------------------------------- 1 | #include "queue_shared_p2.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | init(argv); 6 | usleep(1000); 7 | for(int i=0; i<10; i++) 8 | pop(0); 9 | 10 | finalize_and_check(); 11 | } -------------------------------------------------------------------------------- /apps/memcached_cpu_only/test_nic.c: -------------------------------------------------------------------------------- 1 | #include "dpdk.h" 2 | #include "iokvs.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | settings_init(argc, argv); 6 | init(argv); 7 | ialloc_init(data_region); 8 | run_threads(); 9 | while(1) pause(); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /apps/benchmarks_network_func/aes_ni.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_NI_H_ 2 | #define _AES_NI_H_ 3 | 4 | #include "aes_ni.h" 5 | 6 | void aes128_load_key(int8_t *enc_key); 7 | void aes128_enc(int8_t *plainText,int8_t *cipherText); 8 | void aes128_dec(int8_t *cipherText,int8_t *plainText); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_data1_main.c: -------------------------------------------------------------------------------- 1 | #include "queue_shared_data1.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | init(argv); 6 | for(int i=1; i<10; i++) 7 | push(i, i); 8 | 9 | //usleep(10000); 10 | while(1); 11 | finalize_and_check(); 12 | } -------------------------------------------------------------------------------- /floem/programs_perpacket_state/cavium_varsize_deq_test.c: -------------------------------------------------------------------------------- 1 | #include "varsize_deq.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | init(argv); 5 | run_threads(); 6 | int i; 7 | for(i=0; i<64; i++) { 8 | push((i%4)+1,i); 9 | } 10 | kill_threads(); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /floem/programs/simple_math_ext.c: -------------------------------------------------------------------------------- 1 | #include "simple_math.h" 2 | 3 | int main(int argc, char *argv[]) { 4 | init(argv); // does nothing in this program 5 | // extra init between here 6 | run_threads(); // does nothing in this program 7 | int x = inc2(42); 8 | printf("%d\n", x); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_data2_main.c: -------------------------------------------------------------------------------- 1 | #include "queue_shared_data2.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | init(argv); 6 | usleep(1000); 7 | // for(int i=0; i<10; i++) 8 | // pop(0); 9 | run_threads(); 10 | while(1); 11 | 12 | finalize_and_check(); 13 | } -------------------------------------------------------------------------------- /apps/benchmarks_param_update/test_queue.c: -------------------------------------------------------------------------------- 1 | #include "dpdk.h" 2 | #include "protocol_binary.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | printf("sizeof(param_message) = %d\n", sizeof(param_message)); 6 | init(argv); 7 | init_params(); 8 | 9 | run_threads(); 10 | while(1) pause(); 11 | kill_threads(); 12 | } 13 | -------------------------------------------------------------------------------- /floem/programs/hello.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Hello(Element): 4 | def impl(self): 5 | self.run_c(r'''printf("hello world\n");''') 6 | 7 | 8 | class P(Segment): 9 | def impl(self): 10 | Hello() 11 | 12 | P('p') 13 | 14 | c = Compiler() 15 | c.testing = "while(1) pause();" 16 | c.generate_code_and_run() -------------------------------------------------------------------------------- /apps/storm/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef HASH_H 2 | #define HASH_H 3 | 4 | #include "stdint.h" 5 | #include "stdlib.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | uint32_t hash(const void *key, size_t length, const uint32_t initval); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* HASH_H */ 18 | 19 | -------------------------------------------------------------------------------- /apps/storm/test_storm_nic.c: -------------------------------------------------------------------------------- 1 | #include "storm.h" 2 | #include "worker.h" 3 | #include "dpdk.h" 4 | 5 | struct executor *executor; 6 | 7 | int main(int argc, char *argv[]) { 8 | assert(argc > 1); 9 | 10 | init(argv); 11 | run_threads(); 12 | while(1) dccp_print_stat(); 13 | kill_threads(); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /floem/programs/func_increment1.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | inc1 = Inc('inc1', configure=[Int]) 4 | inc2 = Inc('inc2', configure=[Int]) 5 | inc1 >> inc2 6 | 7 | t = APIThread('add2', ["int"], "int") 8 | t.run(inc1, inc2) 9 | 10 | c = Compiler() 11 | c.testing = "out(add2(11)); out(add2(0));" 12 | c.generate_code_and_run([13,2]) 13 | 14 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_p1_main.c: -------------------------------------------------------------------------------- 1 | #include "queue_shared_p1.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | init(argv); 6 | int* p = data_region; 7 | for(int i=0; i<10; i++) 8 | p[i] = i; 9 | 10 | for(int i=0; i<10; i++) 11 | push(i); 12 | 13 | usleep(10000); 14 | finalize_and_check(); 15 | } -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='floem', 4 | version='0.1', 5 | description='DSL for NIC-accelerated network applications', 6 | url='http://github.com/mangpo/floem', 7 | author='Phitchaya Mangpo Phothilimthana', 8 | author_email='mangpo@eecs.berkeley.edu', 9 | license='BSD', 10 | packages=['floem'], 11 | zip_safe=False) 12 | -------------------------------------------------------------------------------- /floem/programs/hello_depend.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Hello(Element): 4 | def impl(self): 5 | self.run_c(r'''print_hello();''') 6 | 7 | 8 | class P(Segment): 9 | def impl(self): 10 | Hello() 11 | 12 | P('p') 13 | 14 | c = Compiler() 15 | c.include = r''' 16 | #include "hello.h" 17 | ''' 18 | c.testing = "while(1) pause();" 19 | c.depend = ['hello'] 20 | c.generate_code_and_run() -------------------------------------------------------------------------------- /apps/storm/dummy.c: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | 3 | void print_execute(const struct tuple *t, struct executor *self){} 4 | void rank_execute(const struct tuple *t, struct executor *self){} 5 | void count_execute(const struct tuple *t, struct executor *self){} 6 | void spout_execute(const struct tuple *t, struct executor *self){} 7 | 8 | void spout_init(struct executor *self){} 9 | void count_init(struct executor *self){} 10 | -------------------------------------------------------------------------------- /floem/programs/memory_region.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | MemoryRegion("region", 10) 4 | 5 | class Test(Element): 6 | def impl(self): 7 | self.run_c(r''' 8 | int* p = (int*) region; 9 | *p = 99; 10 | printf("%d\n", *p); 11 | ''') 12 | 13 | Test('test') 14 | 15 | c = Compiler() 16 | c.resource = False 17 | c.remove_unused = False 18 | c.testing = r''' 19 | test(); 20 | ''' 21 | c.generate_code_and_run([99]) -------------------------------------------------------------------------------- /apps/benchmarks_network_func/count-min-sketch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Count-min Sketch header 3 | */ 4 | #ifndef _COUNT_MIN_SKETCH 5 | #define _COUNT_MIN_SKETCH 6 | #include 7 | 8 | #define CM_ROW_NUM 4 9 | #define CM_COL_NUM 64 * 1024 10 | 11 | void cm_sketch_init(); 12 | uint64_t cm_sketch_read(int row, uint32_t flow_id); 13 | void cm_sketch_update(int row, uint32_t flow_id, uint64_t new_val); 14 | 15 | #endif /* _COUNT_MIN_SKETCH */ 16 | -------------------------------------------------------------------------------- /floem/programs/func_increment2.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class add2(CallableSegment): 4 | def configure(self): 5 | self.inp = Input(Int) 6 | self.out = Output(Int) 7 | 8 | def impl(self): 9 | inc1 = Inc('inc1', configure=[Int]) 10 | inc2 = Inc('inc2', configure=[Int]) 11 | self.inp >> inc1 >> inc2 >> self.out 12 | 13 | add2('add2') 14 | 15 | c = Compiler() 16 | c.testing = "out(add2(11)); out(add2(0));" 17 | c.generate_code_and_run([13,2]) 18 | 19 | -------------------------------------------------------------------------------- /apps/benchmarks_network_func/pkt-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Packet utilities header 3 | */ 4 | #ifndef _PKT_UTILS_H 5 | #define _PKT_UTILS_H 6 | #include 7 | #include 8 | 9 | //#define CAVIUM 10 | #define UDP_PAYLOAD 42 11 | 12 | uint32_t get_flow_id(uint8_t *pkt_ptr); 13 | void print_pkt(uint8_t *pkt_ptr, int len); 14 | bool pkt_filter(uint8_t *pkt_ptr); 15 | void header_swap(uint8_t *pkt_ptr); 16 | void recapsulate_pkt(uint8_t *pkt_ptr, int pkt_len); 17 | 18 | 19 | #endif /* _PKT_UTILS_H */ 20 | -------------------------------------------------------------------------------- /apps/memcached_nic_only/settings.c: -------------------------------------------------------------------------------- 1 | #include "cvmx.h" 2 | #include "cvmx-atomic.h" 3 | #include "shared-mm.h" 4 | #include "util.h" 5 | #include "iokvs.h" 6 | 7 | struct settings settings; 8 | 9 | void settings_init() 10 | { 11 | settings.udpport = 11211; 12 | settings.verbose = 1; 13 | settings.segsize = 2 * 1024 * 1024; // debug: 2048, real: 2MB 14 | settings.segmaxnum = 128; 15 | settings.segcqsize = 8 * 1024; 16 | struct ip_addr ip = { .addr = {0x0a, 0x03, 0x00, 0x23} }; 17 | settings.localip = ip; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /floem/programs/join_inject2.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | Inject = create_inject("inject", "int", 40, "gen_func") 4 | 5 | add = Add(configure=[Int]) 6 | inject1 = Inject() 7 | inject2 = Inject() 8 | 9 | inject1 >> add.inp1 10 | inject2 >> add.inp2 11 | 12 | t = APIThread("run", [], "int") 13 | t.run(add) 14 | 15 | t1 = InternalThread("t1") 16 | t1.run(inject1) 17 | 18 | t2 = InternalThread("t2") 19 | t2.run(inject2) 20 | 21 | c = Compiler() 22 | c.include = r'''int gen_func(int i) { return i; }''' 23 | c.testing = r''' 24 | for(int i=0;i<10;i++) 25 | out(run()); 26 | ''' 27 | c.generate_code_and_run() -------------------------------------------------------------------------------- /apps/memcached_cpu_only/test_no_steer.c: -------------------------------------------------------------------------------- 1 | #include "iokvs.h" 2 | #include 3 | 4 | void maintenance(struct item_allocator *iallocs) 5 | { 6 | int i; 7 | usleep(100000); 8 | while (1) { 9 | for (i = 0; i < NUM_THREADS; i++) { 10 | ialloc_maintenance(&iallocs[i]); 11 | } 12 | usleep(10); 13 | } 14 | } 15 | 16 | int main(int argc, char *argv[]) { 17 | settings_init(argc, argv); 18 | init(argv); 19 | hasht_init(); 20 | struct item_allocator *iallocs = get_item_allocators(); 21 | 22 | run_threads(); 23 | maintenance(iallocs); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /floem/programs_cavium/hello.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Hello(Element): 4 | def impl(self): 5 | self.run_c(''' 6 | printf("hello world\\n"); 7 | sleep(3); 8 | ''') 9 | 10 | 11 | class run(Segment): 12 | def impl(self): 13 | Hello() 14 | 15 | def cavium(): 16 | run('run', device=target.CAVIUM, cores=[0]) 17 | c = Compiler() 18 | c.testing = "sleep(10);" 19 | c.generate_code_as_header() 20 | 21 | def cpu(): 22 | run('run') 23 | c = Compiler() 24 | c.testing = "sleep(10);" 25 | c.generate_code_and_run() 26 | 27 | cavium() 28 | 29 | -------------------------------------------------------------------------------- /apps/memcached_cpu_only/test_cache.c: -------------------------------------------------------------------------------- 1 | #include "iokvs.h" 2 | #include 3 | 4 | void maintenance(struct item_allocator *iallocs) 5 | { 6 | int i; 7 | usleep(100000); 8 | while (1) { 9 | for (i = 0; i < NUM_THREADS; i++) { 10 | ialloc_maintenance(&iallocs[i]); 11 | } 12 | usleep(10); 13 | } 14 | } 15 | 16 | int main(int argc, char *argv[]) { 17 | settings_init(argc, argv); 18 | ialloc_init(NULL); 19 | init(argv); 20 | hasht_init(); 21 | struct item_allocator *iallocs = get_item_allocators(); 22 | 23 | run_threads(); 24 | maintenance(iallocs); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /apps/parameter_server/message.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class param_message(State): 4 | group_id = Field(Int) 5 | member_id = Field(Int) # worker 6 | start_id = Field(Uint(64)) 7 | starttime = Field('struct timeval') # 16 bytes 8 | n = Field(Int) 9 | parameters = Field(Array(Int)) 10 | layout = [group_id, member_id, start_id, starttime, n, parameters] 11 | 12 | n_params = 3500000 13 | n_groups = 128 14 | n_workers = 8 15 | buffer_size = 350 16 | 17 | define = r''' 18 | #define N_PARAMS %d 19 | #define N_GROUPS %d 20 | #define BUFFER_SIZE %d 21 | #define BITMAP_FULL 0xff 22 | ''' % (n_params, n_groups, buffer_size) 23 | -------------------------------------------------------------------------------- /floem/programs/inc2_function.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class Inc(Element): 5 | def configure(self): 6 | self.inp = Input(Int) 7 | self.out = Output(Int) 8 | 9 | def impl(self): 10 | self.run_c("int x = inp() + 1; output { out(x); }") 11 | 12 | 13 | class inc2(CallableSegment): 14 | def configure(self): 15 | self.inp = Input(Int) 16 | self.out = Output(Int) 17 | 18 | def impl(self): 19 | self.inp >> Inc() >> Inc() >> self.out 20 | 21 | 22 | inc2('inc2', process='simple_math') 23 | 24 | c = Compiler() 25 | c.testing = "out(inc2(11)); out(inc2(0));" 26 | c.generate_code_and_run([13,2]) 27 | 28 | -------------------------------------------------------------------------------- /floem/programs/inc2_function_ext.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class Inc(Element): 5 | def configure(self): 6 | self.inp = Input(Int) 7 | self.out = Output(Int) 8 | 9 | def impl(self): 10 | self.run_c("int x = inp() + 1; output { out(x); }") 11 | 12 | 13 | class inc2(CallableSegment): 14 | def configure(self): 15 | self.inp = Input(Int) 16 | self.out = Output(Int) 17 | 18 | def impl(self): 19 | self.inp >> Inc() >> Inc() >> self.out 20 | 21 | 22 | inc2('inc2', process='simple_math') 23 | 24 | c = Compiler() 25 | c.generate_code_as_header('simple_math') 26 | c.depend = ['simple_math'] 27 | c.compile_and_run('simple_math_ext') -------------------------------------------------------------------------------- /floem/programs/join_inject.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | Inject1 = create_inject("inject1", "int", 10, "gen_func") 4 | Inject2 = create_inject("inject2", "int", 10, "gen_func") 5 | 6 | add = Add(configure=[Int]) 7 | inject1 = Inject1() 8 | inject2 = Inject2() 9 | 10 | inject1 >> add.inp1 11 | inject2 >> add.inp2 12 | 13 | t = APIThread("run", [], "int") 14 | t.run(add) 15 | 16 | t1 = InternalThread("t1") 17 | t1.run(inject1) 18 | 19 | t2 = InternalThread("t2") 20 | t2.run(inject2) 21 | 22 | c = Compiler() 23 | c.include = r'''int gen_func(int i) { return i; }''' 24 | c.testing = r''' 25 | for(int i=0;i<10;i++) 26 | out(run()); 27 | ''' 28 | c.generate_code_and_run([2*i for i in range(10)]) -------------------------------------------------------------------------------- /mockup/memcached/comm.h: -------------------------------------------------------------------------------- 1 | /* App doorbell */ 2 | struct flextcp_pl_adb { 3 | union { 4 | struct { 5 | uint32_t rx_tail; 6 | uint32_t tx_tail; 7 | } bumpqueue; 8 | uint8_t raw[62]; 9 | } __attribute__((packed)) msg; 10 | uint8_t type; 11 | volatile uint8_t nic_own; 12 | } __attribute__((packed)); 13 | 14 | /** Kernel doorbell format */ 15 | struct flextcp_pl_kdb { 16 | union { 17 | struct { 18 | uint64_t rx_base; 19 | uint64_t tx_base; 20 | uint32_t rx_len; 21 | uint32_t tx_len; 22 | } setqueue; 23 | struct { 24 | uint32_t rx_tail; 25 | uint32_t tx_tail; 26 | } bumpqueue; 27 | } msg; 28 | uint8_t _pad[36]; 29 | uint16_t flags; 30 | uint8_t _pad1; 31 | volatile uint8_t nic_own; 32 | } __attribute__((packed)); 33 | -------------------------------------------------------------------------------- /floem/programs/pipeline_state_empty_port1.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class Gen(Element): 5 | def configure(self): 6 | self.out = Output(Int, Int) 7 | 8 | def impl(self): 9 | self.run_c(r''' 10 | for(int i=0; i<10; i++) { 11 | out(i, 2*i); 12 | } 13 | output multiple; 14 | ''') 15 | 16 | 17 | class Display(Element): 18 | def configure(self): 19 | self.inp = Input() 20 | 21 | def impl(self): 22 | self.run_c(r''' 23 | printf("1\n"); 24 | ''') 25 | 26 | class run(CallableSegment): 27 | def impl(self): 28 | Gen() >> Display() 29 | 30 | run('run') 31 | 32 | c = Compiler() 33 | c.testing = r''' 34 | run(); 35 | ''' 36 | c.generate_code_and_run([1 for x in range(10)]) -------------------------------------------------------------------------------- /apps/memcached_cpu_only/settings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "iokvs.h" 7 | 8 | struct settings settings; 9 | 10 | void settings_init(int argc, char *argv[]) 11 | { 12 | settings.udpport = 11211; 13 | settings.verbose = 1; 14 | settings.segsize = 2 * 1024 * 1024; // debug: 2048, real: 2MB 15 | settings.segmaxnum = 512; 16 | settings.segcqsize = 8 * 1024; 17 | 18 | if (argc != 2) { 19 | fprintf(stderr, "Usage: flexkvs LOCAL-IP LOCAL-MAC\n"); 20 | exit(1); 21 | } 22 | 23 | #ifdef RTE 24 | if (inet_pton(AF_INET, argv[1], &settings.localip) != 1) { 25 | fprintf(stderr, "Parsing ip failed\n"); 26 | exit(1); 27 | } 28 | #else 29 | struct ip_addr ip = { .addr = {0x0, 0x0, 0x0, 0x0} }; 30 | settings.localip = ip; 31 | #endif 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /floem/programs/func_insert_start_element.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class func(CallableSegment): 4 | def configure(self): 5 | self.inp = Input(Int) 6 | self.offset = Input(Int) 7 | self.out = Output(Int) 8 | 9 | def args_order(self): 10 | return [self.inp, self.offset] 11 | 12 | def impl(self): 13 | inc1 = Inc(name='inc1', configure=[Int]) 14 | inc2 = Inc(name='inc2', configure=[Int]) 15 | add1 = Add(name='add1', configure=[Int]) 16 | add2 = Add(name='add2', configure=[Int]) 17 | 18 | self.inp >> inc1 >> add1.inp1 19 | self.inp >> inc2 >> add1.inp2 20 | add1 >> add2.inp1 21 | self.offset >> add2.inp2 22 | add2 >> self.out 23 | 24 | func('func') 25 | 26 | c = Compiler() 27 | c.testing = "out(func(1, 0)); out(func(2, 100));" 28 | c.generate_code_and_run([4, 106]) -------------------------------------------------------------------------------- /apps/benchmarks_network_func/nic-compute.h: -------------------------------------------------------------------------------- 1 | /* 2 | * In-NIC compute header 3 | */ 4 | #ifndef _NIC_COMPUTE_H 5 | #define _NIC_COMPUTE_H 6 | #include 7 | #include "pkt-utils.h" 8 | 9 | #ifdef CAVIUM 10 | #include "util.h" 11 | #else 12 | #include 13 | #endif 14 | 15 | typedef enum _TYPE { 16 | ECHO, /* echo */ 17 | HASH, /* hash computing */ 18 | FLOW, /* flow classification */ 19 | SEQU, /* sequencer */ 20 | } PKT_TYPE; 21 | 22 | void lock_group_init(spinlock_t*, int); 23 | PKT_TYPE pkt_parser(uint8_t *pkt_ptr); 24 | void crypto_3des_initialize(const uint64_t *key); 25 | void crypto_3des_encrypt(uint64_t *data, int data_len); 26 | void compute_3des(uint8_t *pkt_ptr, int pkt_len); 27 | void compute_aes(uint8_t *pkt_ptr, int pkt_len); 28 | 29 | #define MIN(a,b) (((a)>(b))?(b):(a)) 30 | #define MAX(a,b) (((a)>(b))?(a):(b)) 31 | 32 | #endif /* _NIC_COMPUTE_H */ 33 | -------------------------------------------------------------------------------- /floem/programs/spec_impl.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | f = Identity(configure=[Int]) 4 | g = Identity(configure=[Int]) 5 | 6 | f >> g 7 | 8 | class test(Composite): 9 | def spec(self): 10 | t1 = APIThread("all", ["int"], "int") 11 | t1.run(f, g) 12 | 13 | def impl(self): 14 | t1 = APIThread("put", ["int"], None) 15 | t1.run(f) 16 | t2 = APIThread("get", [], "int") 17 | t2.run(g) 18 | 19 | test() 20 | 21 | def run_spec(): 22 | c = Compiler() 23 | c.desugar_mode = "spec" 24 | c.testing = "out(all(42)); out(all(123)); out(all(999));" 25 | c.generate_code_and_run([42,123,999]) 26 | 27 | def run_impl(): 28 | c = Compiler() 29 | c.desugar_mode = "impl" 30 | c.testing = "put(42); out(get()); put(123); out(get()); put(999); out(get());" 31 | c.generate_code_and_run([42,123,999]) 32 | 33 | run_spec() 34 | #run_impl() -------------------------------------------------------------------------------- /doc/runtime.md: -------------------------------------------------------------------------------- 1 | # Queue Synchronization Layer 2 | 3 | If you are interested in using our queue synchronization layer with your own queue implementation. 4 | First read Section 3.6 of my [thesis](http://www2.eecs.berkeley.edu/Pubs/TechRpts/2018/EECS-2018-134.html). 5 | 6 | The queue synchronization layer is in `floem/include_cavium/floem-queue-manage`. 7 | The functions `smart_dma_read` and `smart_dma_write` in `floem-queue-manage.c` is equivalent to the functions `access_entry` and `access_done`, explained in the document, respectively. 8 | 9 | Our NIC queue implementation is in `floem/include_cavium/floem-queue`. 10 | The functions `enqueue_ready_var` and `dequeue_ready_var` are the function `nic_own` for enqueue and dequeue processes, respectively, 11 | while `enqueue_done_var` and `dequeue_done_var` are `cpu_own` for enqueue and dequeue processes, respectively. 12 | 13 | Our CPU queue implementation is in `floem/include/queue.h`. -------------------------------------------------------------------------------- /floem/include/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | #define nic_htons(x) x 5 | #define nic_ntohs(x) x 6 | #define nic_htonl(x) x 7 | #define nic_ntohl(x) x 8 | #define nic_htonp(x) x 9 | #define nic_ntohp(x) x 10 | 11 | static inline uint64_t htonp(uint64_t x) 12 | { 13 | uint8_t *s = (uint8_t *)&x; 14 | uint64_t ret = (uint64_t)((uint64_t) s[0] << 56 | (uint64_t) s[1] << 48 | 15 | (uint64_t) s[2] << 40 | (uint64_t) s[3] << 32 | 16 | (uint64_t) s[4] << 24 | (uint64_t) s[5] << 16 | 17 | (uint64_t) s[6] << 8 | s[7]); 18 | //printf("htonp: %p -> %p\n", (void*) x, (void*) ret); 19 | return ret; 20 | } 21 | 22 | static inline uint64_t ntohp(uint64_t x) { 23 | return htonp(x); 24 | } 25 | 26 | 27 | // Ignore CAVIUM DEFINE 28 | #define CVMX_CACHE_LINE_ALIGNED 29 | #define CVMX_SHARED 30 | 31 | 32 | #define shared_mm_malloc(x) malloc(x) 33 | #define shared_mm_free(x) free(x) 34 | 35 | 36 | #endif -------------------------------------------------------------------------------- /apps/memcached_cached/settings.c: -------------------------------------------------------------------------------- 1 | #include "iokvs.h" 2 | 3 | #ifdef CAVIUM 4 | #include "cvmx.h" 5 | #include "cvmx-atomic.h" 6 | #include "shared-mm.h" 7 | #include "util.h" 8 | #else 9 | #include 10 | #include 11 | #endif 12 | 13 | struct settings settings; 14 | 15 | void settings_init() 16 | { 17 | settings.udpport = 11211; 18 | settings.verbose = 1; 19 | settings.segsize = 2 * 1024 * 1024; // debug: 2048, real: 2MB 20 | settings.segmaxnum = 128; 21 | settings.segcqsize = 8 * 1024; 22 | struct ip_addr ip = { .addr = {0x0a, 0x03, 0x00, 0x23} }; 23 | settings.localip = ip; 24 | } 25 | 26 | iokvs_message template = { 27 | .ipv4 = { ._v_hl = 0x45, ._ttl = 0x40, ._proto = 0x11}, 28 | #ifndef CAVIUM 29 | .ether = { .type = 0x0008 }, 30 | .mcudp = { .n_data = 0x0100 } 31 | #else 32 | .ether = { .type = 0x0800 }, 33 | .mcudp = { .n_data = 1 } 34 | #endif 35 | }; // CAVIUM 36 | 37 | iokvs_message* iokvs_template() { 38 | return &template; 39 | } -------------------------------------------------------------------------------- /floem/programs_perpacket_state/auto_inserted_queue.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | a = Field(Int) 5 | 6 | class Gen(Element): 7 | def configure(self): 8 | self.inp = Input(Int) 9 | self.out = Output() 10 | 11 | def impl(self): 12 | self.run_c("state.a = inp(); output { out(); }") 13 | 14 | 15 | class Display(Element): 16 | def configure(self): 17 | self.inp = Input() 18 | 19 | def impl(self): 20 | self.run_c(r'''printf("%d\n", state.a);''') 21 | 22 | class main(Flow): 23 | state = PerPacket(MyState) 24 | 25 | def impl(self): 26 | gen = Gen() 27 | display = Display() 28 | 29 | gen >> display 30 | 31 | put = APIThread('put', ["int"], None) 32 | put.run(gen) 33 | 34 | get = APIThread('get', [], None) 35 | get.run(display) 36 | 37 | c = Compiler(main) 38 | c.testing = "put(42); get(); put(123); get();" 39 | c.generate_code_and_run([42,123]) -------------------------------------------------------------------------------- /floem/include_cavium/floem-dma.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOEM_DMA_H 2 | #define FLOEM_DMA_H 3 | #include "cvmcs-nic.h" 4 | #include "floem-util.h" 5 | 6 | int dma_free(void *buf); 7 | int dma_buf_alloc(void **buf); 8 | int dma_read(uintptr_t addr, size_t len, void **buf); 9 | #ifdef RUNTIME 10 | int dma_comp_reset(); 11 | int dma_read_with_buf(uintptr_t addr, size_t len, void *buf, bool block); 12 | int dma_write(uint64_t remote_addr, uint64_t size, void *local_buf, bool block); 13 | int dma_comp_reset(); 14 | void dma_release_comp(int); 15 | bool dma_complete(int); 16 | #else 17 | cvm_dma_comp_ptr_t *dma_comp_reset(); 18 | cvm_dma_comp_ptr_t *dma_read_with_buf(uintptr_t addr, size_t len, void *buf, bool block); 19 | cvm_dma_comp_ptr_t *dma_write(uint64_t remote_addr, uint64_t size, void *local_buf, bool block); 20 | cvm_dma_comp_ptr_t *dma_comp_reset(); 21 | void dma_release_comp(cvm_dma_comp_ptr_t *); 22 | bool dma_complete(cvm_dma_comp_ptr_t *); 23 | #endif 24 | 25 | void dma_read_flush(); 26 | void dma_write_flush(); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /floem/collection.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | 4 | class InstancesCollection: 5 | def __init__(self): 6 | self.spec = set() 7 | self.impl = None 8 | 9 | def add(self, x): 10 | self.spec.add(x) 11 | if self.impl: 12 | self.impl.add(x) 13 | 14 | def union(self, other): 15 | self.spec = self.spec.union(other.spec) 16 | if self.impl and other.impl: 17 | self.impl = self.impl.union(other.impl) 18 | elif self.impl: 19 | self.impl = self.impl.union(other.spec) 20 | elif other.impl: 21 | self.impl = copy.copy(other.impl) 22 | 23 | 24 | def union_spec(self, other): 25 | self.spec = self.spec.union(other.spec) 26 | 27 | def union_impl(self, other): 28 | if self.impl: 29 | self.impl = self.impl.union(other.spec) 30 | else: 31 | self.impl = copy.copy(other.spec) 32 | 33 | def get_spec(self): 34 | return self.spec 35 | 36 | def get_impl(self): 37 | return self.impl -------------------------------------------------------------------------------- /floem/programs/nested_compo_in_impl.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class Test(Composite): 5 | def configure(self): 6 | self.inp = Input(Int) 7 | self.out = Output(Int) 8 | 9 | def spec(self): 10 | self.inp >> Inc(configure=[Int]) >> self.out 11 | 12 | def impl(self): 13 | class compo(Composite): 14 | def configure(self): 15 | self.inp = Input(Int) 16 | self.out = Output(Int) 17 | 18 | def impl(self): 19 | self.inp >> Inc(configure=[Int]) >> Inc(configure=[Int]) >> self.out 20 | 21 | self.inp >> compo() >> self.out 22 | 23 | test = Test() 24 | f = Inc(configure=[Int]) 25 | f >> test 26 | 27 | t = APIThread("run", ["int"], "int") 28 | t.run(f, test) 29 | 30 | assert len(test.collection.spec) == 1 31 | assert len(test.collection.impl) == 2 32 | 33 | c = Compiler() 34 | c.testing = "out(run(0));" 35 | 36 | c.desugar_mode = "spec" 37 | c.generate_code_and_run([2]) 38 | 39 | c.desugar_mode = "impl" 40 | c.generate_code_and_run([3]) 41 | -------------------------------------------------------------------------------- /apps/benchmarks_param_update/param_update.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define N_PARAMS 512 7 | #define N_POOLS 100000 8 | 9 | typedef struct { 10 | double ws[N_PARAMS]; 11 | double accums[N_PARAMS]; 12 | rte_spinlock_t lock; 13 | } param_pool; 14 | 15 | param_pool params[100000]; 16 | 17 | double r2() 18 | { 19 | return (double)rand() / (double)RAND_MAX ; 20 | } 21 | 22 | void init_params() { 23 | int i, j; 24 | for(i=0; i> Inc(configure=[Int]) >> Inc(configure=[Int]) >> self.out 17 | 18 | def spec(self): 19 | self.inp >> Inc(configure=[Int]) >> self.out 20 | 21 | inner = Inner() 22 | self.inp >> inner >> self.out 23 | 24 | 25 | test = Compo() 26 | f = Inc(configure=[Int]) 27 | f >> test 28 | 29 | t = APIThread("run", ["int"], "int") 30 | t.run(f, test) 31 | 32 | assert len(test.collection.spec) == 1 33 | assert len(test.collection.impl) == 2 34 | 35 | c = Compiler() 36 | c.testing = "out(run(0));" 37 | 38 | c.desugar_mode = "spec" 39 | c.generate_code_and_run([2]) 40 | 41 | #c.desugar_mode = "impl" 42 | #c.generate_code_and_run([3]) 43 | 44 | # TODO: still buggy -------------------------------------------------------------------------------- /floem/programs/spec_impl_at.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Compo(Composite): 4 | def configure(self): 5 | self.inp = Input(Int) 6 | self.out = [Output(Int), Output(Int)] 7 | 8 | def spec(self): 9 | for i in range(2): 10 | self.inp >> Inc(configure=[Int]) >> self.out[i] 11 | 12 | def impl(self): 13 | self.inp >> Inc(configure=[Int]) >> self.out[0] 14 | self.inp >> Inc(configure=[Int]) >> Inc(configure=[Int]) >> self.out[1] 15 | 16 | class Display(Element): 17 | def configure(self): 18 | self.inp = Input(Int) 19 | 20 | def impl(self): 21 | self.run_c(r'''printf("%d\n", inp());''') 22 | 23 | inc = Inc(configure=[Int]) 24 | compo = Compo() 25 | display = Display() 26 | 27 | inc >> compo 28 | compo.out[0] >> display 29 | compo.out[1] >> display 30 | 31 | t = APIThread("run", [Int], None) 32 | t.run(inc, compo, display) 33 | 34 | def run_spec(): 35 | c = Compiler() 36 | c.desugar_mode = "spec" 37 | c.testing = "run(0);" 38 | c.generate_code_and_run([2,2]) 39 | 40 | def run_impl(): 41 | c = Compiler() 42 | c.desugar_mode = "impl" 43 | c.testing = "run(0);" 44 | c.generate_code_and_run([2,3]) 45 | 46 | run_spec() 47 | #run_impl() -------------------------------------------------------------------------------- /floem/programs/socket_recv_real.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class DisplayPacket(Element): 4 | def configure(self): 5 | self.inp = Input(SizeT, "void *", "void *") 6 | self.out = Output("void *", "void *") 7 | 8 | def impl(self): 9 | self.run_c(r''' 10 | (size_t len, void *pkt, void *buf) = inp(); 11 | if (pkt != NULL) { 12 | printf("Got packet\n"); 13 | uint8_t* x = (uint8_t*) pkt; 14 | for(int i=0; i> DisplayPacket('print_packet') >> \ 34 | net.FromNetFree('from_net_free') 35 | from_net.nothing >> Drop('drop') 36 | 37 | test('test', process='dpdk', cores=range(4)) 38 | 39 | c = Compiler() 40 | c.testing = 'while (1) pause();' 41 | c.generate_code_and_compile() 42 | -------------------------------------------------------------------------------- /apps/benchmarks_network_func/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_H_ 2 | #define _AES_H_ 3 | 4 | #include 5 | 6 | 7 | // #define the macros below to 1/0 to enable/disable the mode of operation. 8 | // 9 | // CBC enables AES encryption in CBC-mode of operation. 10 | // ECB enables the basic ECB 16-byte block algorithm. Both can be enabled simultaneously. 11 | 12 | // The #ifndef-guard allows it to be configured before #include'ing or at compile time. 13 | #ifndef CBC 14 | #define CBC 1 15 | #endif 16 | 17 | #ifndef ECB 18 | #define ECB 1 19 | #endif 20 | 21 | #define AES128 1 22 | //#define AES192 1 23 | //#define AES256 1 24 | 25 | #if defined(ECB) && (ECB == 1) 26 | 27 | void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length); 28 | void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length); 29 | 30 | #endif // #if defined(ECB) && (ECB == !) 31 | 32 | 33 | #if defined(CBC) && (CBC == 1) 34 | 35 | void AES_CBC_encrypt_buffer(uint8_t* output, uint32_t length, const uint8_t* key, const uint8_t* iv); 36 | void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); 37 | 38 | #endif // #if defined(CBC) && (CBC == 1) 39 | 40 | 41 | #endif //_AES_H_ 42 | -------------------------------------------------------------------------------- /floem/empty_port.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | def nonempty_to_empty_port_pass(g): 5 | vis = set() 6 | for instance in g.instances.values(): 7 | for port in instance.element.inports: 8 | if len(port.argtypes) == 0 and port.name in instance.input2ele: 9 | for prev_name, prev_portname in instance.input2ele[port.name]: 10 | prev_inst = g.instances[prev_name] 11 | prev_port = [port for port in prev_inst.element.outports if port.name == prev_portname][0] 12 | if len(prev_port.argtypes) > 0: 13 | element = prev_inst.element 14 | 15 | if prev_name + "_empty" in vis: 16 | new_element = element 17 | else: 18 | new_element = element.clone(prev_name + "_empty") 19 | vis.add(prev_name + "_empty") 20 | prev_inst.element = new_element 21 | g.addElement(new_element) 22 | 23 | prev_port = [port for port in new_element.outports if port.name == prev_portname][0] 24 | prev_port.argtypes = [] 25 | new_element.reassign_output_values(prev_portname, '') -------------------------------------------------------------------------------- /apps/storm/collections/stack.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * \brief Barrelfish collections library stack 4 | */ 5 | 6 | /* 7 | * Copyright (c) 2012, ETH Zurich. 8 | * All rights reserved. 9 | * 10 | * This file is distributed under the terms in the attached LICENSE file. 11 | * If you do not find this file, copies can be found by writing to: 12 | * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 | */ 14 | 15 | #ifndef _COLLECTIONS_STACK_H_ 16 | #define _COLLECTIONS_STACK_H_ 17 | 18 | #include 19 | 20 | #include 21 | 22 | __BEGIN_DECLS 23 | 24 | struct collections_stack { 25 | /** 26 | * total number of elements 27 | */ 28 | uint32_t num_elements; 29 | 30 | /** 31 | * elements of the stack kept in a linked list 32 | */ 33 | collections_listnode *elements; 34 | }; 35 | 36 | void collections_stack_create(struct collections_stack **stack); 37 | 38 | void *collections_stack_pop(struct collections_stack *stack); 39 | 40 | void collections_stack_push(struct collections_stack *stack, void *element); 41 | 42 | void *collections_stack_top(struct collections_stack *stack); 43 | 44 | void collections_stack_release(struct collections_stack *stack); 45 | 46 | __END_DECLS 47 | 48 | #endif // _COLLECTIONS_STACK_H_ 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, University of California, Berkeley. 2 | 3 | Authored by Phitchaya Mangpo Phothilimthana. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /floem/programs/pipeline_state_simple.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class MyState(State): 5 | val = Field(Int) 6 | 7 | 8 | class MyFlow(Flow): 9 | state = PerPacket(MyState) 10 | 11 | class Save(Element): 12 | 13 | def configure(self): 14 | self.inp = Input(Int) 15 | self.out = Output() 16 | 17 | def impl(self): 18 | state = MyFlow.state 19 | self.run_c(r'''state.val = inp(); output { out(); }''') 20 | self.defs(state.val) # TODO: use this info instead of analyze C 21 | 22 | class Display(Element): 23 | def configure(self): 24 | self.inp = Input() 25 | 26 | def impl(self): 27 | state = MyFlow.state 28 | self.run_c(r'''printf("%d\n", state.val);''') 29 | self.uses(state.val) 30 | 31 | class Run(CallableSegment): 32 | def configure(self): 33 | self.inp = Input(Int) 34 | 35 | def impl(self): 36 | display = MyFlow.Display() 37 | save = MyFlow.Save() 38 | 39 | self.inp >> save >> display 40 | 41 | def impl(self): 42 | MyFlow.Run('run') 43 | 44 | c = Compiler(MyFlow) 45 | c.testing = r''' 46 | run(1); 47 | run(2); 48 | run(3); 49 | ''' 50 | c.generate_code_and_run([1,2,3]) 51 | 52 | 53 | # TODO: pass per-packet state as parameter -------------------------------------------------------------------------------- /floem/include_cavium/floem-queue.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOEM_QUEUE_H 2 | #define FLOEM_QUEUE_H 3 | 4 | #include 5 | #include "cvmcs-nic.h" 6 | #include "floem-util.h" 7 | 8 | #define FLAG_INUSE 4 9 | #define FLAG_CLEAN 2 10 | #define FLAG_OWN 1 11 | 12 | typedef struct { 13 | size_t len; 14 | size_t offset; 15 | void* queue; 16 | size_t clean; 17 | int id; 18 | uint32_t entry_size; 19 | } circular_queue; 20 | 21 | typedef struct { 22 | size_t len; 23 | size_t offset; 24 | void* queue; 25 | size_t clean; 26 | int id; 27 | uint32_t entry_size; 28 | lock_t lock; 29 | } circular_queue_lock; 30 | 31 | typedef struct { 32 | uint8_t flag; 33 | uint8_t task; 34 | uint16_t len; 35 | uint8_t checksum; 36 | uint8_t pad; 37 | } __attribute__((packed)) q_entry; 38 | 39 | typedef struct { 40 | q_entry* entry; 41 | uintptr_t addr; 42 | int qid; 43 | } q_buffer; 44 | 45 | q_buffer enqueue_alloc(circular_queue* q, size_t len, int gap, void(*clean)(q_buffer)); 46 | void enqueue_submit(q_buffer buf, bool check); 47 | q_buffer dequeue_get(circular_queue* q); 48 | void dequeue_release(q_buffer buf, uint8_t flag_clean); 49 | void no_clean(q_buffer buff); 50 | int dequeue_ready_var(void*); 51 | int dequeue_ready_var_checksum(void*); 52 | int dequeue_done_var(void*); 53 | int enqueue_ready_var(void*); 54 | int enqueue_done_var(void*); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/multiple_buffers_pipeline.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | fork = create_element_instance("myfork", [Port("in", ["int"])], [Port("out0", []), Port("out1", [])], 4 | r''' 5 | int x = in(); 6 | state.a = x; 7 | state.b = x; 8 | output { out0(); out1(); } 9 | ''') 10 | 11 | inc = create_element_instance("inc", [Port("in", [])], [Port("out", [])], 12 | r''' 13 | state.a++; 14 | output { out(); } 15 | ''') # TODO: def & use 16 | 17 | add = create_element_instance("add", [Port("in0", []), Port("in1", [])], [Port("out", [])], 18 | r''' 19 | state.sum = state.a + state.b; 20 | output { out(); } 21 | ''') 22 | 23 | display = create_element_instance("display", [Port("in", [])], [], r'''printf("%d\n", state.sum);''') 24 | 25 | state = create_state("mystate", "int a; int b; int sum;") 26 | pipeline_state(fork, "mystate") 27 | 28 | x1, x2 = fork(None) 29 | y1 = inc(x1) 30 | z = add(y1, x2) 31 | display(z) 32 | 33 | prod = API_thread("run", ["int"], None) 34 | t = internal_thread("t") 35 | 36 | prod.run(fork) 37 | t.run(inc, add, display) 38 | 39 | c = Compiler() 40 | c.testing = r''' 41 | run(1); 42 | ''' 43 | c.generate_code_and_run([3, 'free!']) -------------------------------------------------------------------------------- /floem/programs/state_shared.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class A(State): 4 | count = Field(Int) 5 | 6 | def init(self, count=0): 7 | self.count = count 8 | 9 | 10 | class Counter(Element): 11 | a = Persistent(A) # TODO: Persistent 12 | 13 | def configure(self): 14 | self.inp = Input(Int) 15 | self.out = Output(Int) 16 | 17 | def states(self, a): 18 | self.a = a 19 | 20 | def impl(self): 21 | self.run_c(r''' 22 | int x = inp(); 23 | a->count += x; 24 | output { out(a->count); } 25 | ''') 26 | 27 | a = A(init=[0]) 28 | 29 | 30 | class Shared(CallableSegment): 31 | def configure(self): 32 | self.inp = Input(Int) 33 | self.out = Output(Int) 34 | 35 | def impl(self): 36 | counter = Counter(states=[a]) 37 | self.inp >> counter >> self.out 38 | 39 | 40 | run1 = Shared('run1') 41 | run2 = Shared('run2') 42 | 43 | 44 | class Local(CallableSegment): 45 | def configure(self): 46 | self.inp = Input(Int) 47 | self.out = Output(Int) 48 | 49 | def impl(self): 50 | a = A(init=[0]) 51 | counter = Counter(states=[a]) 52 | self.inp >> counter >> self.out 53 | 54 | run1 = Local('run3') 55 | run2 = Local('run4') 56 | 57 | c = Compiler() 58 | c.testing = r''' 59 | out(run1(2)); 60 | out(run2(2)); 61 | out(run3(1)); 62 | out(run4(1)); 63 | ''' 64 | c.generate_code_and_run([2,4,1,1]) -------------------------------------------------------------------------------- /floem/programs_perpacket_state/free_zero_or_one.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | choose = create_element_instance("choose", [Port("in", ["int"])], [Port("out0", []), Port("out1", [])], 4 | r''' 5 | (int x) = in(); 6 | state.a = x; 7 | output switch { 8 | case (x % 3 == 0): out0(); 9 | case (x % 3 == 1): out1(); 10 | } 11 | ''') 12 | 13 | Display = create_element("display", [Port("in", [])], [], 14 | r''' 15 | printf("%d\n", state.a); 16 | ''') 17 | display1 = Display() 18 | display2 = Display() 19 | display3 = Display() 20 | 21 | fork = create_element_instance("myfork", [Port("in", [])], [Port("out0", []), Port("out1", [])], 22 | r''' 23 | output { out0(); out1(); } 24 | ''') 25 | 26 | state = create_state("mystate", "int a;") 27 | pipeline_state(choose, "mystate") 28 | 29 | x1, x2 = choose(None) 30 | display1(x1) 31 | x2, x3 = fork(x2) 32 | display2(x2) 33 | display3(x3) 34 | 35 | f = API_thread("run", ["int"], None) 36 | f.run(choose, display1) 37 | 38 | t2 = internal_thread("t2") 39 | t2.run(fork, display2) 40 | 41 | t3 = internal_thread("t3") 42 | t3.run(display3) 43 | 44 | c = Compiler() 45 | c.testing = r''' 46 | run(0); run(1); 47 | usleep(1000); 48 | run(2); 49 | ''' 50 | c.generate_code_and_run([0,'free!', 1, 1, 'free!', 'free!']) -------------------------------------------------------------------------------- /floem/programs/probe_spec_impl.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | Inject = create_inject("inject", "int", 10, "gen_func") 4 | Probe = create_probe("probe", "int", 10, "cmp_func") 5 | 6 | inject = Inject() 7 | probe = Probe() 8 | f = Identity(configure=[Int]) 9 | g = Identity(configure=[Int]) 10 | drop = Drop() 11 | 12 | inject >> f >> g >> probe >> drop 13 | 14 | class test(Composite): 15 | def spec(self): 16 | t1 = InternalThread("t1") 17 | t1.run(inject, f, g, probe, drop) 18 | 19 | def impl(self): 20 | t1 = InternalThread("t1") 21 | t2 = InternalThread("t2") 22 | t1.run(inject, f) 23 | t2.run(g, probe, drop) 24 | 25 | test() 26 | 27 | c = Compiler() 28 | c.include = r''' 29 | int gen_func(int i) { return i; } 30 | void cmp_func(int spec_n, int *spec_data, int impl_n, int *impl_data) { 31 | if(!(spec_n == impl_n)) { 32 | printf("Spec records %d entries, but Impl records %d entries.\n", spec_n, impl_n); 33 | exit(-1); 34 | } 35 | for(int i=0; i 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | static int create_server_socket(uint16_t port) { 11 | int listener = 0; 12 | struct sockaddr_in serv_addr; 13 | 14 | printf("create socket\n"); 15 | listener = socket(AF_INET, SOCK_STREAM, 0); 16 | assert(listener != -1); 17 | 18 | int optval = 1; 19 | int r = setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)); 20 | assert(r == 0); 21 | 22 | struct sockaddr_in saddr = { 23 | .sin_family = AF_INET, 24 | .sin_port = htons(port), 25 | .sin_addr = { INADDR_ANY }, 26 | }; 27 | 28 | r = bind(listener, (void *)&saddr, sizeof(saddr)); 29 | if(r != 0) 30 | printf("bind failed with status %d.\n", r); 31 | assert(r == 0); 32 | 33 | r = listen(listener, 4); // backlog 34 | printf("socket listen\n"); 35 | 36 | return listener; 37 | } 38 | 39 | static int create_client_socket() { 40 | printf("client starts...\n"); 41 | int sock = socket(AF_INET, SOCK_STREAM, 0); 42 | assert(sock != -1); 43 | 44 | return sock; 45 | } 46 | 47 | static struct sockaddr_in create_sockaddr(const char* hostname, uint16_t port) { 48 | struct sockaddr_in saddr = { 49 | .sin_family = AF_INET, 50 | .sin_port = htons(port), 51 | }; 52 | 53 | if(hostname != NULL) { 54 | int r = inet_pton(AF_INET, hostname, &saddr.sin_addr); 55 | assert(r == 1); 56 | } 57 | 58 | return saddr; 59 | } 60 | 61 | #endif -------------------------------------------------------------------------------- /floem/programs/pipeline_state_empty_port3.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | b = Field(Int) 5 | 6 | 7 | class main(Flow): 8 | state = PerPacket(MyState) 9 | 10 | class Gen(Element): 11 | def configure(self): 12 | self.out = Output(Int, Int) 13 | 14 | def impl(self): 15 | self.run_c(r''' 16 | for(int i=0; i<10; i++) { 17 | out(i, 2*i); 18 | } 19 | output multiple; 20 | ''') 21 | 22 | class Save(Element): 23 | def configure(self): 24 | self.inp = Input(Int, Int) 25 | self.out0 = Output(Int) 26 | self.out1 = Output(Int) 27 | 28 | def impl(self): 29 | self.run_c(r''' 30 | (int a, int b) = inp(); 31 | state.b = b; 32 | output switch { case (a%2==0): out0(a); else: out1(a); } 33 | ''') 34 | 35 | class Display(Element): 36 | def configure(self): 37 | self.inp = Input() 38 | 39 | def impl(self): 40 | self.run_c(r''' 41 | printf("%d\n", state.b); 42 | ''') 43 | 44 | class run(CallableSegment): 45 | def impl(self): 46 | save = main.Save() 47 | display = main.Display() 48 | main.Gen() >> save 49 | save.out0 >> display 50 | save.out1 >> display 51 | 52 | def impl(self): 53 | main.run('run') 54 | 55 | c = Compiler(main) 56 | c.testing = r''' 57 | run(); 58 | ''' 59 | c.generate_code_and_run([2*x for x in range(10)]) -------------------------------------------------------------------------------- /apps/memcached_cpu_only/test_app.c: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | #include "iokvs.h" 3 | #include 4 | 5 | static struct item_allocator **iallocs; 6 | 7 | void run_app(void *threadid) { 8 | long tid = (long)threadid; 9 | printf("Worker %ld: segmaxnum = %d\n", tid, settings.segmaxnum); 10 | struct item_allocator ia; 11 | ialloc_init_allocator(&ia, tid); 12 | iallocs[tid] = &ia; 13 | init_segment(tid, &ia); 14 | 15 | printf("Worker %ld starting\n", tid); 16 | 17 | while(true) { 18 | process_eq(tid); 19 | clean_log(&ia, true); // TODO: always true 20 | } 21 | } 22 | 23 | void maintenance() 24 | { 25 | size_t i; 26 | usleep(100000); 27 | while (1) { 28 | create_segment(); 29 | for (i = 0; i < NUM_THREADS; i++) { 30 | ialloc_maintenance(iallocs[i]); 31 | } 32 | //usleep(10); 33 | } 34 | } 35 | 36 | int main(int argc, char *argv[]) { 37 | settings_init(argc, argv); 38 | init(argv); 39 | ialloc_init(data_region); 40 | hasht_init(); 41 | iallocs = calloc(NUM_THREADS, sizeof(*iallocs)); 42 | printf("main: segmaxnum = %d\n", settings.segmaxnum); 43 | 44 | pthread_t threads[NUM_THREADS]; 45 | for(int t=0;t 4 | 5 | static struct item_allocator *iallocs; 6 | 7 | void run_app(void *threadid) { 8 | long tid = (long)threadid; 9 | struct item_allocator* ia = &iallocs[tid]; 10 | printf("Worker %ld: segmaxnum = %ld, ia = %p\n", tid, settings.segmaxnum, ia); 11 | //ialloc_init_allocator(&ia, tid); 12 | //iallocs[tid] = &ia; 13 | 14 | printf("Worker %ld starting\n", tid); 15 | 16 | while(true) { 17 | int i; 18 | for(i=0; i 5 | #include "cvmcs-nic.h" 6 | #include "floem-util.h" 7 | 8 | //#define DEBUG 9 | #define HIT_RATE 10 | #define BUCKET_NITEMS 5 11 | 12 | typedef struct _cache_bucket cache_bucket; 13 | 14 | typedef struct _citem { 15 | struct _citem* next; 16 | cache_bucket* bucket; 17 | uint32_t hv; 18 | uint16_t keylen, last_vallen; 19 | uint8_t evicted; 20 | uint8_t content[]; 21 | } citem; 22 | 23 | typedef struct _cache_bucket { 24 | lock_t lock; 25 | int replace; 26 | citem *items[BUCKET_NITEMS]; 27 | uint32_t hashes[BUCKET_NITEMS]; 28 | } CVMX_CACHE_LINE_ALIGNED cache_bucket; 29 | 30 | inline bool citem_key_matches(citem *it, const void *key, int klen); 31 | inline bool citem_hkey_matches(citem *it, const void *key, int klen, uint32_t hv); 32 | inline void *citem_key(citem *it); 33 | inline void *citem_value(citem *it); 34 | void cache_init(cache_bucket *buckets, int n); 35 | citem *cache_get(cache_bucket *buckets, int nbuckets, const void *key, int klen, uint32_t hv, bool* success); 36 | citem *cache_put(cache_bucket *buckets, int nbuckets, citem *nit, bool replace, bool* success); 37 | citem *cache_put_or_get(cache_bucket *buckets, int nbuckets, citem *nit, bool replace, bool* success); 38 | void cache_delete(cache_bucket *buckets, int nbuckets, void* key, int klen, uint32_t hv, bool* success); 39 | inline void cache_release(citem *it); 40 | uint32_t jenkins_hash(const void *key, size_t length); 41 | 42 | 43 | void cache_info(cache_bucket *buckets, int nbuckets, uint32_t hv, const char*); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /floem/target.py: -------------------------------------------------------------------------------- 1 | # device = CPU 2 | HOST = 'CPU' 3 | CPU = 'CPU' 4 | cpu_include_h = ["", "", "", "", '', '', ''] 5 | cpu_include_c = cpu_include_h + \ 6 | ["", "", "", "", '', '', ''] 7 | 8 | # device = CAVIUM, process = CAVIUM 9 | CAVIUM = 'CAVIUM' 10 | cavium_include_h = ['"cvmcs-nic.h"', '"floem-queue.h"', '"floem-cache.h"'] 11 | cavium_include_c = cavium_include_h +\ 12 | ['', '"floem-util.h"', '"floem-dma.h"', '"floem-queue-manage.h"'] 13 | 14 | 15 | # device = CPU, process = DPDK 16 | def is_dpdk_proc(process): 17 | return process == 'dpdk' 18 | 19 | dpdk = "dpdk" 20 | dpdk_dir = "/homes/sys/mangpo/dpdk" #"/opt/dpdk" 21 | dpdk_include = dpdk_dir + "/include/dpdk" 22 | dpdk_lib = dpdk_dir + "/lib/" 23 | dpdk_pmds = "-lrte_pmd_ixgbe -lrte_pmd_i40e" 24 | dpdk_libs = "-Wl,--whole-archive " + dpdk_pmds + " -lrte_eal" + \ 25 | " -lrte_mempool -lrte_mempool_ring -lrte_hash -lrte_ring -lrte_kvargs" + \ 26 | " -lrte_ethdev -lrte_mbuf -lrte_pmd_ring -lrte_pci -lrte_bus_pci -lrte_bus_vdev" + \ 27 | " -lnuma -Wl,--no-whole-archive -lm -lpthread -ldl" 28 | dpdk_driver_header = [''] 29 | 30 | 31 | def runtime_hook(graph, process): 32 | src = "" 33 | if process == CAVIUM and graph.shared_states: 34 | src = r''' 35 | #ifdef RUNTIME 36 | { 37 | int corenum = cvmx_get_core_num(); 38 | if(corenum >= RUNTIME_START_CORE) smart_dma_manage(corenum - RUNTIME_START_CORE); 39 | } 40 | #endif 41 | ''' 42 | return src 43 | -------------------------------------------------------------------------------- /floem/include_cavium/floem-queue-manage.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOEM_QUEUE_MANAGE_H 2 | #define FLOEM_QUEUE_MANAGE_H 3 | #include "cvmcs-nic.h" 4 | #include "floem-util.h" 5 | 6 | #define CAVIUM 7 | #define BUFF_SIZE 2 * 1024 8 | 9 | void init_dma_circular_queue(); 10 | int create_dma_circular_queue(uint64_t addr, int size, int overlap, 11 | int (*ready_scan)(void*), int (*done_scan)(void*)); 12 | void* smart_dma_read_local(int qid, size_t addr); 13 | void* smart_dma_read(int qid, size_t addr, int size); 14 | int smart_dma_write(int qid, size_t addr, int size, void* p); 15 | 16 | void smart_info(int qid, size_t addr, int size); 17 | void smart_dma_manage(int); 18 | 19 | typedef struct _dma_segment { 20 | int id; 21 | uint32_t status, size; 22 | int count; 23 | uint64_t min, max, addr, addr_max, offset; 24 | uint64_t commit_max; 25 | uint8_t *buf; 26 | #ifdef RUNTIME 27 | int comp; 28 | #else 29 | cvm_dma_comp_ptr_t *comp; 30 | #endif 31 | uint64_t starttime; 32 | } CVMX_CACHE_LINE_ALIGNED dma_segment; 33 | 34 | typedef struct _dma_circular_queue { 35 | int size, overlap, block_size, n, id; 36 | size_t addr, read_ready, write_ready; 37 | int read_ready_seg, write_ready_seg, write_start_seg, write_finish_seg; 38 | dma_segment *segments; 39 | int (*ready_scan)(void*); 40 | int (*done_scan)(void*); 41 | uint64_t last_read, last_write, write_gap; 42 | spinlock_t rlock, wlock; 43 | } CVMX_CACHE_LINE_ALIGNED dma_circular_queue; 44 | 45 | #define VALID 0 46 | #define WRITING 1 47 | #define INVALID 2 48 | #define READING 3 49 | #define RELEASE 4 50 | 51 | #define DMA_WAIT 100000 // 83 us (0.5 us) 52 | #define WRITE_WAIT 1000000 // 833 us 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /floem/programs/pipeline_state_empty_port2.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | b = Field(Int) 5 | 6 | 7 | class main(Flow): 8 | state = PerPacket(MyState) 9 | 10 | class Gen(Element): 11 | def configure(self): 12 | self.out = Output(Int, Int) 13 | 14 | def impl(self): 15 | self.run_c(r''' 16 | for(int i=0; i<10; i++) { 17 | out(i, 2*i); 18 | } 19 | output multiple; 20 | ''') 21 | 22 | class Save(Element): 23 | def configure(self): 24 | self.inp = Input(Int, Int) 25 | self.out = Output(Int) 26 | 27 | def impl(self): 28 | self.run_c(r''' 29 | (int a, int b) = inp(); 30 | state.b = b; 31 | output { out(a); } 32 | ''') 33 | 34 | class Get(Element): 35 | def configure(self): 36 | self.inp = Input() 37 | self.out = Output(Int) 38 | 39 | def impl(self): 40 | self.run_c(r''' 41 | int b = state.b; 42 | output { out(b); } 43 | ''') 44 | 45 | class Display(Element): 46 | def configure(self): 47 | self.inp = Input() 48 | 49 | def impl(self): 50 | self.run_c(r''' 51 | printf("%d\n", state.b); 52 | ''') 53 | 54 | class run(CallableSegment): 55 | def impl(self): 56 | main.Gen() >> main.Save() >> main.Get() >> main.Display() 57 | 58 | def impl(self): 59 | main.run('run') 60 | 61 | c = Compiler(main) 62 | c.testing = r''' 63 | run(); 64 | ''' 65 | c.generate_code_and_run([2*x for x in range(10)]) -------------------------------------------------------------------------------- /floem/standard_elements.py: -------------------------------------------------------------------------------- 1 | from graph import * 2 | from program import * 3 | 4 | 5 | def Fork(name, n, type): 6 | outports = [Port("out%d" % (i+1), [type]) for i in range(n)] 7 | calls = ["out%d(x);" % (i+1) for i in range(n)] 8 | src = "(%s x) = in(); output { %s }" % (type, " ".join(calls)) 9 | return Element(name, [Port("in", [type])], outports, src) 10 | 11 | 12 | def Fork_multi_values(name, n, types): 13 | args = [] 14 | types_args = [] 15 | for i in range(len(types)): 16 | arg = "_arg%d" % i 17 | args.append(arg) 18 | types_args.append("%s %s" % (types[i], arg)) 19 | 20 | args_str = ",".join(args) 21 | outports = [Port("out%d" % (i + 1), types) for i in range(n)] 22 | calls = ["out%d(%s);" % ((i + 1), args_str) for i in range(n)] 23 | if len(types) == 0: 24 | src = "output { %s }" % (" ".join(calls)) 25 | else: 26 | src = "(%s) = in(); output { %s }" % (",".join(types_args), " ".join(calls)) 27 | return Element(name, [Port("in", types)], outports, src) 28 | 29 | 30 | def IdentityElement(name, type): 31 | src = "(%s x) = in(); output { out(x); }" % type 32 | return Element(name, [Port("in", [type])], [Port("out", [type])], src) 33 | 34 | Fork2 = Fork("Fork2", 2, "int") 35 | Fork3 = Fork("Fork3", 3, "int") 36 | Forward = IdentityElement("Forward", "int") 37 | Add = Element("Add", [Port("in1", ["int"]), Port("in2", ["int"])], [Port("out", ["int"])], 38 | r'''int x = in1() + in2(); output { out(x); }''') 39 | 40 | Inc = Element("Inc", [Port("in", ["int"])], [Port("out", ["int"])], r'''int x = in() + 1; output { out(x); }''') 41 | 42 | Drop = Element("Drop", [Port("in", ["int"])], [], r'''in();''') 43 | 44 | -------------------------------------------------------------------------------- /floem/hton.py: -------------------------------------------------------------------------------- 1 | import target, common 2 | 3 | 4 | def get_all_types_fields(g, state_name, prefix): 5 | if state_name in g.states: 6 | state = g.states[state_name] 7 | ret = [] 8 | for field in state.fields: 9 | if field in state.mapping: 10 | t = state.mapping[field][0] 11 | ret += get_all_types_fields(g, t, prefix + field + '.') 12 | return ret 13 | else: 14 | return [(state_name, prefix[:-1])] 15 | 16 | htons = "htons" 17 | htonl = "htonl" 18 | htonp = "htonp" 19 | size2convert = {1: "", 2: htons, 4: htonl, 8: htonp} 20 | def hton_instance(g, instance, state_name): 21 | src = " (size_t size, void* pkt, void* buf) = inp();\n" 22 | src += " {0}* p = ({0}*) pkt;\n".format(state_name) 23 | types_fields = get_all_types_fields(g, state_name, 'p->') 24 | for type, field in types_fields: 25 | try: 26 | size = common.sizeof(type) 27 | if size == 2 or size == 4 or size == 8: 28 | src += " {0} = {1}({0});\n".format(field, size2convert[size]) 29 | except: 30 | pass 31 | element = instance.element 32 | new_element = element.clone(element.name + "_" + state_name) 33 | new_element.code = src 34 | instance.element = new_element 35 | 36 | 37 | def is_on_CPU(g, instance): 38 | t = instance.thread 39 | d = g.get_device_from_thread(t) 40 | return d == target.CPU 41 | 42 | 43 | def hton_pass(g): 44 | for inst in g.instances.values(): 45 | special = inst.element.special 46 | if isinstance(special, tuple) and special[0] == 'hton': 47 | if is_on_CPU(g, inst): 48 | hton_instance(g, inst, special[1]) 49 | -------------------------------------------------------------------------------- /floem/programs_cavium/shared_state.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Count(State): 4 | count = Field(Int) 5 | 6 | def init(self): 7 | self.count = 100 8 | 9 | count = Count() 10 | 11 | class Counter(Element): 12 | this = Persistent(Count) 13 | 14 | def states(self): 15 | self.this = count 16 | 17 | def configure(self): 18 | self.inp = Input('void*', 'void*') 19 | self.out = Output('void*', 'void*') 20 | 21 | def impl(self): 22 | self.run_c(r''' 23 | (void* p, void* buf) = inp(); 24 | this->count++; 25 | output { out(p, buf); } 26 | ''') 27 | 28 | def impl_cavium(self): 29 | self.run_c(r''' 30 | (void* p, void* buf) = inp(); 31 | 32 | int *count; 33 | dma_read(this, sizeof(int), (void **) &count); 34 | 35 | int local = nic_htonl(*count); 36 | local++; 37 | *count = nic_ntohl(local); 38 | 39 | dma_write(this, sizeof(int), count); 40 | 41 | // Free the block 42 | dma_free(count); 43 | output { out(p, buf); } 44 | ''') 45 | 46 | class ReadCounter(Element): 47 | this = Persistent(Count) 48 | 49 | def states(self): 50 | self.this = count 51 | 52 | def impl(self): 53 | self.run_c(r''' 54 | printf("count = %d\n", this->count); 55 | ''') 56 | 57 | 58 | class NICRx(Segment): 59 | def impl(self): 60 | net.FromNet() >> Counter() >> net.FromNetFree() 61 | 62 | 63 | class GetCount(CallableSegment): 64 | def impl(self): 65 | ReadCounter() 66 | 67 | 68 | NICRx('nic_rx', device=target.CAVIUM, cores=[0,1,2,3]) 69 | GetCount('get_count', process='tmp') 70 | 71 | master_process('tmp') 72 | 73 | c = Compiler() 74 | c.generate_code_as_header() -------------------------------------------------------------------------------- /apps/memcached_split/test_app.c: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | #include "iokvs.h" 3 | #include 4 | 5 | static struct item_allocator **iallocs; 6 | 7 | void run_app(void *threadid) { 8 | long tid = (long)threadid; 9 | printf("Worker %ld: segmaxnum = %ld\n", tid, settings.segmaxnum); 10 | struct item_allocator ia; 11 | ialloc_init_allocator(&ia, tid); 12 | iallocs[tid] = &ia; 13 | init_segment(tid, &ia); 14 | init_segment(tid, &ia); 15 | init_segment(tid, &ia); 16 | init_segment(tid, &ia); 17 | 18 | printf("Worker %ld starting\n", tid); 19 | 20 | int round = 0; 21 | int qid = 0; 22 | while(true) { 23 | process_eq(qid); 24 | clean_log(&ia, true); // TODO: is this frequent enough? 25 | qid = (qid + 1) % 3; 26 | } 27 | } 28 | 29 | void maintenance() 30 | { 31 | size_t i; 32 | usleep(100000); 33 | while (1) { 34 | create_segment(); 35 | for (i = 0; i < NUM_THREADS; i++) { 36 | ialloc_maintenance(iallocs[i]); 37 | } 38 | //usleep(10); 39 | } 40 | } 41 | 42 | int main(int argc, char *argv[]) { 43 | //settings_init(argv); 44 | init(argv); 45 | ialloc_init(); 46 | hasht_init(); 47 | iallocs = calloc(NUM_THREADS, sizeof(*iallocs)); 48 | printf("main: segmaxnum = %ld\n", settings.segmaxnum); 49 | 50 | pthread_t threads[NUM_THREADS]; 51 | for(int t=0;t 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | typedef struct _MyState { 13 | int index; 14 | int qid; 15 | int* p; 16 | 17 | } __attribute__ ((packed)) MyState; 18 | 19 | 20 | typedef struct _queue_Storage { 21 | uint8_t data[4096]; 22 | 23 | } __attribute__ ((packed)) queue_Storage; 24 | 25 | 26 | typedef struct _queue_EnqueueCollection { 27 | circular_queue* insts[2]; 28 | 29 | } __attribute__ ((packed)) queue_EnqueueCollection; 30 | 31 | 32 | typedef struct _queue_DequeueCollection { 33 | circular_queue* insts[2]; 34 | 35 | } __attribute__ ((packed)) queue_DequeueCollection; 36 | 37 | 38 | typedef struct _entry_queue0 { 39 | uint8_t flag; uint8_t task; uint16_t len; uint8_t checksum; uint8_t pad; uint64_t p; int index; 40 | } __attribute__ ((packed)) entry_queue0; 41 | 42 | 43 | typedef struct _pipeline_queue0 { 44 | int refcount; q_buffer buffer; entry_queue0* entry; int* p; 45 | } __attribute__ ((packed)) pipeline_queue0; 46 | 47 | 48 | typedef struct _MyState_compressed0 { 49 | int refcount; int index; 50 | int qid; 51 | int* p; 52 | 53 | } __attribute__ ((packed)) MyState_compressed0; 54 | 55 | 56 | typedef struct __queue_fill0_from_main_push_Save0_join_buffer { 57 | q_buffer in_entry_arg0; MyState_compressed0* in_pkt_arg0; 58 | } __attribute__ ((packed)) _queue_fill0_from_main_push_Save0_join_buffer; 59 | 60 | void *data_region; 61 | 62 | void pop(int arg0); 63 | 64 | void init(char *argv[]); 65 | void finalize_and_check(); 66 | void run_threads(); 67 | void kill_threads(); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_p1.h: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_SHARED_P1_H 2 | #define QUEUE_SHARED_P1_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | typedef struct _MyState { 13 | int index; 14 | int qid; 15 | int* p; 16 | 17 | } __attribute__ ((packed)) MyState; 18 | 19 | 20 | typedef struct _queue_Storage { 21 | uint8_t data[4096]; 22 | 23 | } __attribute__ ((packed)) queue_Storage; 24 | 25 | 26 | typedef struct _queue_EnqueueCollection { 27 | circular_queue* insts[2]; 28 | 29 | } __attribute__ ((packed)) queue_EnqueueCollection; 30 | 31 | 32 | typedef struct _queue_DequeueCollection { 33 | circular_queue* insts[2]; 34 | 35 | } __attribute__ ((packed)) queue_DequeueCollection; 36 | 37 | 38 | typedef struct _entry_queue0 { 39 | uint8_t flag; uint8_t task; uint16_t len; uint8_t checksum; uint8_t pad; uint64_t p; int index; 40 | } __attribute__ ((packed)) entry_queue0; 41 | 42 | 43 | typedef struct _pipeline_queue0 { 44 | int refcount; q_buffer buffer; entry_queue0* entry; int* p; 45 | } __attribute__ ((packed)) pipeline_queue0; 46 | 47 | 48 | typedef struct _MyState_compressed0 { 49 | int refcount; int index; 50 | int qid; 51 | int* p; 52 | 53 | } __attribute__ ((packed)) MyState_compressed0; 54 | 55 | 56 | typedef struct __queue_fill0_from_main_push_Save0_join_buffer { 57 | q_buffer in_entry_arg0; MyState_compressed0* in_pkt_arg0; 58 | } __attribute__ ((packed)) _queue_fill0_from_main_push_Save0_join_buffer; 59 | 60 | void *data_region; 61 | 62 | void push(int arg0); 63 | 64 | void init(char *argv[]); 65 | void finalize_and_check(); 66 | void run_threads(); 67 | void kill_threads(); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /floem/programs_cavium/outqueue.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | MAX_ELEMS = 10 4 | n_cores = 4 5 | 6 | class Tuple(State): 7 | task = Field(Uint(8)) 8 | id = Field(Int) 9 | 10 | def init(self): 11 | self.declare = False 12 | 13 | Inject = create_inject("inject", Pointer(Tuple), 100, "random_count", 100000) 14 | 15 | Enq, Deq, DeqRelease = queue.queue_custom("tx_queue", Tuple, MAX_ELEMS, n_cores, "task") 16 | 17 | class GetCore(Element): 18 | def configure(self): 19 | self.inp = Input(Pointer(Tuple)) 20 | self.out = Output(Pointer(Tuple), SizeT) 21 | 22 | def impl(self): 23 | self.run_c(r''' 24 | (Tuple* t) = inp(); 25 | output { out(t, t->id %s %s); } 26 | ''' % ('%', n_cores)) 27 | 28 | class Display(Element): 29 | def configure(self): 30 | self.inp = Input('q_buffer') 31 | self.out = Output('q_buffer') 32 | 33 | def impl(self): 34 | self.run_c(r''' 35 | (q_buffer buff) = inp(); 36 | Tuple* t = buff.entry; 37 | if(t) printf("t: id = %d\n", t->id); 38 | output switch { case t: out(buff); } 39 | ''') 40 | 41 | class app(Segment): 42 | def impl(self): 43 | Inject() >> GetCore() >> Enq() 44 | 45 | class nic(Segment): 46 | def impl(self): 47 | self.core_id >> Deq() >> Display() >> DeqRelease() 48 | 49 | app('app') 50 | nic('nic', cores=[0,1,2,3]) 51 | 52 | c = Compiler() 53 | c.include = r''' 54 | #include 55 | 56 | typedef struct _Tuple { 57 | int id; 58 | uint8_t task; 59 | } Tuple; 60 | 61 | Tuple* random_count(size_t i) { 62 | Tuple* t = (Tuple*) malloc(sizeof(Tuple)); 63 | t->task = 10; 64 | t->id = i; 65 | return t; 66 | } 67 | ''' 68 | c.testing = r''' 69 | while(1); 70 | ''' 71 | c.generate_code_and_run() -------------------------------------------------------------------------------- /apps/storm/collections/flipbuffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * \brief Barrelfish collections library - flip buffer 4 | */ 5 | 6 | /* 7 | * Copyright (c) 2012, ETH Zurich. 8 | * All rights reserved. 9 | * 10 | * This file is distributed under the terms in the attached LICENSE file. 11 | * If you do not find this file, copies can be found by writing to: 12 | * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 | */ 14 | 15 | #ifndef _COLLECTIONS_FLIPBUFFER_H_ 16 | #define _COLLECTIONS_FLIPBUFFER_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | __BEGIN_DECLS 23 | 24 | struct collections_fbuf { 25 | void *front; /// < front buffer (currently active buffer) 26 | size_t frontlen; /// < length (in bytes) of front buffer 27 | void *back; /// < back buffer 28 | size_t backlen; /// < length (in bytes) of back buffer 29 | }; 30 | 31 | void collections_fbuf_append(struct collections_fbuf *fbuf, const void *data, 32 | size_t length); 33 | 34 | void collections_fbuf_create(struct collections_fbuf **fbuf); 35 | 36 | void collections_fbuf_flip(struct collections_fbuf *fbuf); 37 | 38 | void collections_fbuf_free(struct collections_fbuf *fbuf); 39 | 40 | void *collections_fbuf_get_data(struct collections_fbuf *fbuf); 41 | 42 | size_t collections_fbuf_get_length(struct collections_fbuf *fbuf); 43 | 44 | bool collections_fbuf_is_empty(struct collections_fbuf *fbuf); 45 | 46 | void collections_fbuf_other_free(struct collections_fbuf *fbuf); 47 | 48 | bool collections_fbuf_other_is_empty(struct collections_fbuf *fbuf); 49 | 50 | void collections_fbuf_release(struct collections_fbuf *fbuf); 51 | 52 | __END_DECLS 53 | 54 | #endif // _COLLECTIONS_FLIPBUFFER_H_ 55 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_data2.h: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_SHARED_DATA2_H 2 | #define QUEUE_SHARED_DATA2_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | typedef struct _MyState { 13 | int qid; 14 | int* p; 15 | uint8_t* key; 16 | int keylen; 17 | 18 | } __attribute__ ((packed)) MyState; 19 | 20 | 21 | typedef struct _queue_Storage { 22 | uint8_t data[4096]; 23 | 24 | } __attribute__ ((packed)) queue_Storage; 25 | 26 | 27 | typedef struct _queue_EnqueueCollection { 28 | circular_queue* insts[2]; 29 | 30 | } __attribute__ ((packed)) queue_EnqueueCollection; 31 | 32 | 33 | typedef struct _queue_DequeueCollection { 34 | circular_queue* insts[2]; 35 | 36 | } __attribute__ ((packed)) queue_DequeueCollection; 37 | 38 | 39 | typedef struct _entry_queue0 { 40 | uint8_t flag; uint8_t task; uint16_t len; uint8_t checksum; uint8_t pad; uint64_t p; int keylen; uint8_t _content[]; 41 | } __attribute__ ((packed)) entry_queue0; 42 | 43 | 44 | typedef struct _pipeline_queue0 { 45 | int refcount; q_buffer buffer; entry_queue0* entry; int* p; uint8_t* key; 46 | } __attribute__ ((packed)) pipeline_queue0; 47 | 48 | 49 | typedef struct _MyState_compressed0 { 50 | int refcount; int qid; 51 | int* p; 52 | uint8_t* key; 53 | int keylen; 54 | 55 | } __attribute__ ((packed)) MyState_compressed0; 56 | 57 | 58 | typedef struct __queue_fill0_from_main_push_Save0_join_buffer { 59 | q_buffer in_entry_arg0; MyState_compressed0* in_pkt_arg0; 60 | } __attribute__ ((packed)) _queue_fill0_from_main_push_Save0_join_buffer; 61 | 62 | void *data_region; 63 | 64 | void init(char *argv[]); 65 | void finalize_and_check(); 66 | void run_threads(); 67 | void kill_threads(); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/smart_queue_multi_funcs.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | x = Field(Int) 5 | qid = Field(Int) 6 | 7 | 8 | class save(Element): 9 | def configure(self): 10 | self.inp = Input(Int) 11 | self.out = Output() 12 | 13 | def impl(self): 14 | self.run_c(r''' 15 | (int x) = inp(); 16 | state.x = x; 17 | state.qid = 0; 18 | output { out(); } 19 | ''') 20 | 21 | class Display(Element): 22 | def configure(self): 23 | self.inp = Input() 24 | 25 | def impl(self): 26 | self.run_c(r''' 27 | printf("%d\n", state.x); 28 | ''') 29 | 30 | class main(Flow): 31 | state = PerPacket(MyState) 32 | 33 | def impl(self): 34 | Enq, Deq, Clean = queue_smart.smart_queue("queue", 32, 16, 1, 1) 35 | 36 | class func1(CallableSegment): 37 | def configure(self): 38 | self.inp = Input() 39 | 40 | def impl(self): 41 | enq = Enq() 42 | self.inp >> save() >> enq.inp[0] 43 | 44 | class func2(CallableSegment): 45 | def configure(self): 46 | self.inp = Input() 47 | 48 | def impl(self): 49 | enq = Enq() 50 | self.inp >> save() >> enq.inp[0] 51 | 52 | class dequeue(CallableSegment): 53 | def configure(self): 54 | self.inp = Input() 55 | 56 | def impl(self): 57 | deq = Deq() 58 | self.inp >> deq >> Display() 59 | 60 | func1('func1') 61 | func2('func2') 62 | dequeue('deq') 63 | 64 | c = Compiler(main) 65 | c.testing = "func1(1); func2(2); func2(3); func1(4); deq(0); deq(0); deq(0); deq(0);" 66 | c.generate_code_and_run([1,2,3,4]) -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_pointer.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | qid = Field(Int) 5 | index = Field(Int) 6 | p = Field(Pointer(Int), shared='data_region') # TODO 7 | 8 | class main(Flow): 9 | state = PerPacket(MyState) 10 | 11 | class Save(Element): 12 | def configure(self): 13 | self.inp = Input(Int) 14 | self.out = Output() 15 | 16 | def impl(self): 17 | self.run_c(r''' 18 | state.index = inp(); state.p = data_region; state.qid = 0; output { out(); } 19 | ''') 20 | 21 | class Display(Element): 22 | def configure(self): 23 | self.inp = Input() 24 | 25 | def impl(self): 26 | self.run_c(r''' 27 | printf("%d\n", state.p[state.index]); fflush(stdout); 28 | ''') 29 | 30 | Enq, Deq, Scan = queue_smart.smart_queue("queue", 32, 128, 2, 1) 31 | 32 | 33 | class push(CallableSegment): 34 | def configure(self): 35 | self.inp = Input(Int) 36 | 37 | def impl(self): 38 | self.inp >> main.Save() >> main.Enq() 39 | 40 | class pop(CallableSegment): 41 | def configure(self): 42 | self.inp = Input(Int) 43 | 44 | def impl(self): 45 | self.inp >> main.Deq() >> main.Display() 46 | 47 | def impl(self): 48 | MemoryRegion("data_region", 4 * 100) 49 | main.push('push', process="queue_shared_p1") 50 | main.pop('pop', process="queue_shared_p2") 51 | master_process("queue_shared_p1") 52 | 53 | 54 | c = Compiler(main) 55 | c.generate_code_as_header() 56 | c.depend = {"queue_shared_p1_main": ['queue_shared_p1'], 57 | "queue_shared_p2_main": ['queue_shared_p2']} 58 | c.compile_and_run(["queue_shared_p1_main", "queue_shared_p2_main"]) -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_data1.h: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_SHARED_DATA1_H 2 | #define QUEUE_SHARED_DATA1_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | typedef struct _MyState { 13 | int qid; 14 | int* p; 15 | uint8_t* key; 16 | int keylen; 17 | 18 | } __attribute__ ((packed)) MyState; 19 | 20 | 21 | typedef struct _queue_Storage { 22 | uint8_t data[4096]; 23 | 24 | } __attribute__ ((packed)) queue_Storage; 25 | 26 | 27 | typedef struct _queue_EnqueueCollection { 28 | circular_queue* insts[2]; 29 | 30 | } __attribute__ ((packed)) queue_EnqueueCollection; 31 | 32 | 33 | typedef struct _queue_DequeueCollection { 34 | circular_queue* insts[2]; 35 | 36 | } __attribute__ ((packed)) queue_DequeueCollection; 37 | 38 | 39 | typedef struct _entry_queue0 { 40 | uint8_t flag; uint8_t task; uint16_t len; uint8_t checksum; uint8_t pad; uint64_t p; int keylen; uint8_t _content[]; 41 | } __attribute__ ((packed)) entry_queue0; 42 | 43 | 44 | typedef struct _pipeline_queue0 { 45 | int refcount; q_buffer buffer; entry_queue0* entry; int* p; uint8_t* key; 46 | } __attribute__ ((packed)) pipeline_queue0; 47 | 48 | 49 | typedef struct _MyState_compressed0 { 50 | int refcount; int qid; 51 | int* p; 52 | uint8_t* key; 53 | int keylen; 54 | 55 | } __attribute__ ((packed)) MyState_compressed0; 56 | 57 | 58 | typedef struct __queue_fill0_from_main_push_Save0_join_buffer { 59 | q_buffer in_entry_arg0; MyState_compressed0* in_pkt_arg0; 60 | } __attribute__ ((packed)) _queue_fill0_from_main_push_Save0_join_buffer; 61 | 62 | void *data_region; 63 | 64 | void push(int arg0, uint8_t arg1); 65 | 66 | void init(char *argv[]); 67 | void finalize_and_check(); 68 | void run_threads(); 69 | void kill_threads(); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /apps/storm/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKER_H 2 | #define WORKER_H 3 | 4 | #include 5 | #include 6 | #include "hash.h" 7 | #include "storm.h" 8 | 9 | #define ETHARP_HWADDR_LEN 6 10 | 11 | struct eth_addr { 12 | uint8_t addr[ETHARP_HWADDR_LEN]; 13 | } __attribute__ ((packed)); 14 | 15 | struct ip_addr { 16 | uint8_t addr[4]; 17 | } __attribute__ ((packed)); 18 | 19 | struct worker { 20 | const char *hostname; 21 | struct eth_addr mac; 22 | struct ip_addr ip; 23 | uint32_t seq; 24 | uint16_t port; 25 | int sock; 26 | struct executor executors[MAX_EXECUTORS]; 27 | }; 28 | 29 | // All bolts 30 | void print_execute(const struct tuple *t, struct executor *self); 31 | void rank_execute(const struct tuple *t, struct executor *self); 32 | void count_execute(const struct tuple *t, struct executor *self); 33 | void spout_execute(const struct tuple *t, struct executor *self); 34 | 35 | void spout_init(struct executor *self); 36 | void count_init(struct executor *self); 37 | 38 | struct worker* get_workers(); 39 | int fields_grouping(const struct tuple *t, struct executor *self); 40 | int global_grouping(const struct tuple *t, struct executor *self); 41 | 42 | void init_task2executor(struct executor *executor); 43 | int *get_task2executorid(); 44 | int *get_task2worker(); 45 | struct executor *get_executors(); 46 | struct tuple* random_spout(size_t i); 47 | struct tuple* random_count(size_t i); 48 | struct tuple* random_rank(size_t i); 49 | 50 | #if defined(BIGFISH) || defined(BIGFISH_FLEXNIC) 51 | # define PROC_FREQ 1600000.0 // bigfish (Khz) 52 | #else 53 | # define PROC_FREQ 2200000.0 // swingout (Khz) 54 | #endif 55 | 56 | #define PROC_FREQ_MHZ (uint64_t)(PROC_FREQ / 1000) 57 | 58 | #define BATCH_SIZE 64 // in tuples 59 | #define BATCH_DELAY 2000 // in us = (2000 * PROC_FREQ_MHZ) in cycles 60 | #define LINK_RTT (130) // in us 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /floem/cache_tests/one_in_one_out.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class Mult2(Element): 5 | def configure(self, *params): 6 | self.inp = Input(Int) 7 | self.out = Output(Int, Int) 8 | 9 | def impl(self): 10 | self.run_c(r''' 11 | (int x) = inp(); 12 | output { out(x, 2*x); } 13 | ''') 14 | 15 | class OnlyVal(Element): 16 | def configure(self): 17 | self.inp = Input(Int, Int) 18 | self.out = Output(Int) 19 | 20 | def impl(self): 21 | self.run_c(r''' 22 | (int key, int val) = inp(); 23 | output { out(val); } 24 | ''') 25 | 26 | CacheGetStart, CacheGetEnd, CacheSetStart, CacheSetEnd, \ 27 | CacheState, Key2State, KV2State, State2Key, State2KV = \ 28 | cache_smart.smart_cache('MyCache', Int, [Int], write_policy=Cache.write_back, write_miss=Cache.write_alloc) 29 | 30 | 31 | class MyState(CacheState): 32 | pass 33 | 34 | 35 | class main(Flow): 36 | state = PerPacket(MyState) 37 | 38 | def impl(self): 39 | class compute(CallableSegment): 40 | def configure(self): 41 | self.inp = Input(Int) 42 | self.out = Output(Int) 43 | 44 | def impl(self): 45 | self.inp >> CacheGetStart() >> Mult2() >> CacheGetEnd() >> OnlyVal() >> self.out 46 | 47 | class set(CallableSegment): 48 | def configure(self): 49 | self.inp = Input(Int, Int) 50 | 51 | def impl(self): 52 | self.inp >> CacheSetStart() >> CacheSetEnd() >> library.Drop() 53 | 54 | compute('compute') 55 | set('set') 56 | 57 | 58 | c = Compiler(main) 59 | c.testing = r''' 60 | set(1, 100); 61 | out(compute(11)); out(compute(1)); out(compute(11)); out(compute(1)); 62 | set(11, 222); out(compute(11)); out(compute(1)); 63 | ''' 64 | c.generate_code_and_run([22,100,22,100, 222, 100]) -------------------------------------------------------------------------------- /floem/programs/probe_multi.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | Inject = create_inject("inject", "int", 10, "gen_func") 4 | Probe = create_probe("probe", "int", 10, "cmp_func") 5 | 6 | class Choice(Element): 7 | def configure(self): 8 | self.inp = Input(Int) 9 | self.out1 = Output(Int) 10 | self.out2 = Output(Int) 11 | 12 | def impl(self): 13 | self.run_c(r''' 14 | (int x) = inp(); output switch { case (x % 2 == 0): out1(x); else: out2(x); } 15 | ''') 16 | 17 | inject = Inject() 18 | f1 = Identity(configure=[Int]) 19 | f2 = Identity(configure=[Int]) 20 | drop = Drop() 21 | 22 | class test(Composite): 23 | def spec(self): 24 | probe = Probe() 25 | inject >> f1 >> f2 >> probe >> drop 26 | 27 | def impl(self): 28 | probe1 = Probe() 29 | probe2 = Probe() 30 | choice = Choice() 31 | inject >> choice 32 | choice.out1 >> f1 >> probe1 >> drop 33 | choice.out2 >> f2 >> probe2 >> drop 34 | 35 | compo = test() 36 | t = InternalThread("t") 37 | t.run(compo) 38 | 39 | 40 | c = Compiler() 41 | c.include = r''' 42 | int gen_func(int i) { return i; } 43 | void cmp_func(int spec_n, int *spec_data, int impl_n, int *impl_data) { 44 | if(!(spec_n == impl_n)) { 45 | printf("Spec records %d entries, but Impl records %d entries.\n", spec_n, impl_n); 46 | exit(-1); 47 | } 48 | for(int i=0; iether.src; 18 | struct eth_addr dest = m->ether.dest; 19 | m->ether.src = dest; 20 | m->ether.dest = src; 21 | 22 | struct ip_addr src_ip = m->ipv4.src; 23 | struct ip_addr dest_ip = m->ipv4.dest; 24 | m->ipv4.src = dest_ip; 25 | m->ipv4.dest = src_ip; 26 | 27 | uint16_t src_port = m->udp.src_port; 28 | uint16_t dest_port = m->udp.dest_port; 29 | m->udp.dest_port = src_port; 30 | m->udp.src_port = dest_port; 31 | 32 | m->mcr.request.magic = PROTOCOL_BINARY_RES; 33 | m->mcr.request.opcode = PROTOCOL_BINARY_CMD_GET; 34 | m->mcr.request.datatype = PROTOCOL_BINARY_RAW_BYTES; 35 | m->mcr.request.status = htons(PROTOCOL_BINARY_RESPONSE_KEY_ENOENT); 36 | /* 37 | uint8_t* p = pkt; 38 | int i; 39 | for(i=0; i<64; i++) { 40 | printf("%x ",p[i]); 41 | } 42 | printf("\n"); 43 | */ 44 | 45 | output { out(size, pkt, buff); } 46 | ''') 47 | 48 | class nic_rx(Segment): 49 | def impl(self): 50 | from_net = net.FromNet() 51 | to_net = net.ToNet() 52 | 53 | from_net.nothing >> library.Drop() 54 | 55 | from_net >> Reply() >> to_net 56 | 57 | 58 | nic_rx('nic_rx', process='dpdk', cores=range(2)) 59 | #nic_rx('nic_rx', device=target.CAVIUM, cores=range(1)) 60 | c = Compiler() 61 | c.include = r''' 62 | #include "protocol_binary.h" 63 | ''' 64 | c.testing = 'while (1) pause();' 65 | #c.generate_code_as_header() 66 | c.generate_code_and_compile() 67 | -------------------------------------------------------------------------------- /floem/programs/queue_custom.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_cores = 2 4 | 5 | 6 | class Tuple(State): 7 | val = Field(Int) 8 | task = Field(Uint(8)) 9 | layout = [val, task] 10 | 11 | class Display(Element): 12 | def configure(self): 13 | self.inp = Input(queue.q_buffer) 14 | self.out = Output(queue.q_buffer) 15 | 16 | def impl(self): 17 | self.run_c(r''' 18 | q_buffer buff = inp(); 19 | Tuple* t = (Tuple*) buff.entry; 20 | if(t) printf("%d\n", t->val); 21 | output switch { case t: out(buff); } 22 | ''') 23 | 24 | class EnqConfirm(Element): 25 | def configure(self): 26 | self.inp = Input(Pointer(Tuple)) 27 | 28 | def impl(self): 29 | self.run_c(r''' 30 | Tuple* t = inp(); 31 | printf("%d\n", -t->val); 32 | ''') 33 | 34 | Enq, Deq, Release = queue.queue_custom('queue', Tuple, 4, n_cores, Tuple.task, enq_output=True) 35 | 36 | class RxWrite(CallableSegment): 37 | def configure(self): 38 | self.inp = Input(Pointer(Tuple), Int) 39 | 40 | def impl(self): 41 | enq = Enq() 42 | self.inp >> enq >> EnqConfirm() 43 | 44 | 45 | class RxPrint(CallableSegment): 46 | def configure(self): 47 | self.inp = Input(Int) 48 | 49 | def impl(self): 50 | deq = Deq() 51 | release = Release() 52 | display = Display() 53 | self.inp >> deq >> display >> release 54 | 55 | RxWrite('mysend') 56 | RxPrint('process') 57 | 58 | c = Compiler() 59 | c.testing = r''' 60 | Tuple tuples[5]; 61 | for(int i=0; i<5;i++) { 62 | tuples[i].task = 10; 63 | tuples[i].val = i; 64 | } 65 | 66 | for(int i=0; i<5;i++) { 67 | mysend(&tuples[i], 0); 68 | process(0); 69 | } 70 | 71 | for(int i=0; i<5;i++) { 72 | tuples[i].val = 100 + i; 73 | mysend(&tuples[i], 1); 74 | tuples[i].task = 0; 75 | } 76 | 77 | for(int i=0; i<5;i++) { 78 | process(1); 79 | } 80 | ''' 81 | c.generate_code_and_run([0,0,-1,1,-2,2,-3,3,-4,4,-100,-101,-102,-103,-104,100,101,102,103]) -------------------------------------------------------------------------------- /floem/programs/pipeline_state_nonempty.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | b = Field(Int) 5 | 6 | class main(Flow): 7 | state = PerPacket(MyState) 8 | 9 | class Gen(Element): 10 | def configure(self): 11 | self.out = Output(Int, Int) 12 | 13 | def impl(self): 14 | self.run_c(r''' 15 | for(int i=0; i<10; i++) { 16 | out(i, 2*i); 17 | } 18 | output multiple; 19 | ''') 20 | 21 | class Save(Element): 22 | def configure(self): 23 | self.inp = Input(Int, Int) 24 | self.out = Output(Int) 25 | 26 | def impl(self): 27 | self.run_c(r''' 28 | (int a, int b) = inp(); 29 | state.b = b; 30 | output { out(a); } 31 | ''') 32 | 33 | class Get(Element): 34 | def configure(self): 35 | self.inp = Input(Int) 36 | self.out = Output(Int, Int) 37 | 38 | def impl(self): 39 | self.run_c(r''' 40 | int a = inp(); 41 | int b = state.b; 42 | output { out(a, b); } 43 | ''') 44 | 45 | class Get2(Element): 46 | def configure(self): 47 | self.inp = Input(Int, Int) 48 | self.out = Output(Int) 49 | 50 | def impl(self): 51 | self.run_c(r''' 52 | inp(); 53 | int b = state.b; 54 | output { out(b); } 55 | ''') 56 | 57 | class Display(Element): 58 | def configure(self): 59 | self.inp = Input(Int) 60 | 61 | def impl(self): 62 | self.run_c(r''' 63 | printf("%d\n", inp()); 64 | ''') 65 | 66 | class run(CallableSegment): 67 | def impl(self): 68 | main.Gen() >> main.Save() >> main.Get() >> main.Get2() >> main.Display() 69 | 70 | def impl(self): 71 | main.run('run') 72 | 73 | c = Compiler(main) 74 | c.testing = r''' 75 | run(); 76 | ''' 77 | c.generate_code_and_run([2*x for x in range(10)]) -------------------------------------------------------------------------------- /apps/benchmarks_param_update/main.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_cores = 1 4 | 5 | class MyState(State): 6 | core = Field(SizeT) 7 | payload = Field(Pointer(Uint(8)), size='sizeof(param_entry)') 8 | 9 | 10 | class Reply(Element): 11 | def configure(self): 12 | self.inp = Input(SizeT, "void*", "void*") 13 | self.out = Output(SizeT, "void*", "void*") 14 | 15 | def impl(self): 16 | self.run_c(r''' 17 | (size_t size, void* pkt, void* buff) = inp(); 18 | param_message* m = (param_message*) pkt; 19 | 20 | struct eth_addr src = m->ether.src; 21 | struct eth_addr dest = m->ether.dest; 22 | m->ether.src = dest; 23 | m->ether.dest = src; 24 | 25 | struct ip_addr src_ip = m->ipv4.src; 26 | struct ip_addr dest_ip = m->ipv4.dest; 27 | m->ipv4.src = dest_ip; 28 | m->ipv4.dest = src_ip; 29 | 30 | uint16_t src_port = m->udp.src_port; 31 | uint16_t dest_port = m->udp.dest_port; 32 | m->udp.dest_port = src_port; 33 | m->udp.src_port = dest_port; 34 | 35 | m->status = 1; 36 | 37 | /* 38 | uint8_t* p = pkt; 39 | int i; 40 | for(i=0; i<64; i++) { 41 | printf("%x ",p[i]); 42 | } 43 | printf("\n"); 44 | */ 45 | 46 | output { out(size, pkt, buff); } 47 | ''') 48 | 49 | 50 | class Update(Element): 51 | def configure(self): 52 | self.inp = Input(SizeT, "void *", "void *") 53 | 54 | def impl(self): 55 | self.run_c(r''' 56 | (size_t size, void* pkt, void* buff) = inp(); 57 | param_message* m = (param_message*) pkt; 58 | //printf("udpate: pool = %d, param = %lf\n", m->pool, m->param); 59 | update_param(m->pool, m->param); 60 | ''') 61 | 62 | 63 | class run(Segment): 64 | def impl(self): 65 | from_net = net.FromNet() 66 | to_net = net.ToNet() 67 | 68 | from_net.nothing >> library.Drop() 69 | 70 | from_net >> Update() 71 | from_net >> Reply() >> to_net 72 | 73 | 74 | run('run', process='dpdk', cores=range(n_cores)) 75 | 76 | c = Compiler() 77 | c.include = r''' 78 | #include "protocol_binary.h" 79 | ''' 80 | c.generate_code_as_header() 81 | c.depend = ['dpdk', 'param_update'] 82 | c.compile_and_run("test_queue") 83 | -------------------------------------------------------------------------------- /apps/storm/rank.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "storm.h" 10 | 11 | #define DEFAULT_EMIT_FREQUENCY_IN_SECONDS 1 12 | #define TOP_N 5 13 | 14 | static int rank(const void *a, const void *b) 15 | { 16 | const struct tuple *t1 = a, *t2 = b; 17 | return t2->v[0].integer - t1->v[0].integer; 18 | } 19 | 20 | void rank_execute(const struct tuple *t, struct executor *self) 21 | { 22 | static __thread time_t lasttime = 0; 23 | static __thread struct tuple rankings[TOP_N + 1]; 24 | 25 | if(t->task == 30) 26 | printf("Ranker %d got '%s', %d.\n", t->task & 0xff, t->v[0].str, t->v[0].integer); 27 | 28 | for(int j = 0; j < MAX_VECTOR; j++) { 29 | if(t->v[j].integer == 0) { 30 | break; 31 | } 32 | 33 | // Update if already in ranking 34 | bool found = false; 35 | for(int i = 0; i <= TOP_N; i++) { 36 | if(!strcmp(rankings[i].v[0].str, t->v[j].str)) { 37 | rankings[i].v[0].integer = t->v[j].integer; 38 | found = true; 39 | break; 40 | } 41 | } 42 | 43 | // Append to end if not in ranking 44 | if(!found) { 45 | strcpy(rankings[TOP_N].v[0].str, t->v[j].str); 46 | rankings[TOP_N].v[0].integer = t->v[j].integer; 47 | } 48 | 49 | // Re-sort ranking 50 | qsort(rankings, TOP_N + 1, sizeof(struct tuple), rank); 51 | } 52 | 53 | struct timeval tv; 54 | int r = gettimeofday(&tv, NULL); 55 | assert(r == 0); 56 | 57 | //printf("time: %ld > = %ld\n", tv.tv_sec, lasttime + DEFAULT_EMIT_FREQUENCY_IN_SECONDS); 58 | if(tv.tv_sec >= lasttime + DEFAULT_EMIT_FREQUENCY_IN_SECONDS) { 59 | lasttime = tv.tv_sec; 60 | 61 | // Emit rankings 62 | struct tuple out; 63 | for(int i = 0; i < TOP_N; i++) { 64 | strcpy(out.v[i].str, rankings[i].v[0].str); 65 | out.v[i].integer = rankings[i].v[0].integer; 66 | printf("Rank %d, '%s', count %d\n", i, rankings[i].v[0].str, 67 | rankings[i].v[0].integer); 68 | } 69 | 70 | tuple_send(&out, self); 71 | } 72 | //sleep(1); 73 | } 74 | -------------------------------------------------------------------------------- /floem/library.py: -------------------------------------------------------------------------------- 1 | from dsl import * 2 | 3 | 4 | class Identity(Element): 5 | 6 | def configure(self, data_type): 7 | self.data_type = data_type 8 | self.inp = Input(self.data_type) 9 | self.out = Output(self.data_type) 10 | 11 | def impl(self): 12 | self.run_c(r''' 13 | %s x = inp(); 14 | output { out(x); } 15 | ''' % self.data_type) 16 | 17 | 18 | class Inc(Element): 19 | def configure(self, data_type): 20 | self.data_type = data_type 21 | self.inp = Input(data_type) 22 | self.out = Output(data_type) 23 | 24 | def impl(self): 25 | self.run_c(r''' 26 | %s x = inp(); 27 | output { out(x + 1); } 28 | ''' % self.data_type) 29 | 30 | 31 | class Add(Element): 32 | def configure(self, data_type): 33 | self.data_type = data_type 34 | self.inp1 = Input(self.data_type) 35 | self.inp2 = Input(self.data_type) 36 | self.out = Output(self.data_type) 37 | 38 | def impl(self): 39 | self.run_c(r''' 40 | %s x1 = inp1(); 41 | %s x2 = inp2(); 42 | output { out(x1 + x2); } 43 | ''' % (self.data_type, self.data_type)) 44 | 45 | 46 | class Drop(Element): 47 | def configure(self): 48 | self.inp = Input() 49 | 50 | def impl(self): 51 | self.run_c("") 52 | 53 | 54 | class Constant(Element): 55 | def configure(self, t, c): 56 | self.out = Output(t) 57 | self.c = c 58 | 59 | def impl(self): 60 | self.run_c(r''' 61 | output { out(%s); } 62 | ''' % self.c) 63 | 64 | 65 | class PrintNum(Element): 66 | def configure(self, data_type=Int): 67 | self.data_type = data_type 68 | self.inp = Input(data_type) 69 | 70 | def impl(self): 71 | if self.data_type in [SizeT, Uintptr]: 72 | format = "%ld" 73 | elif self.data_type == Float: 74 | format = "%f" 75 | elif self.data_type == Double: 76 | format = "%lf" 77 | else: 78 | format = "%d" 79 | 80 | self.run_c(r''' 81 | %s x = inp(); 82 | printf("%s\n", x); 83 | ''' % (self.data_type, format)) 84 | -------------------------------------------------------------------------------- /mockup/TCP/tcp_minimal_pulling.c: -------------------------------------------------------------------------------- 1 | app_new_flow >>re syscall1 >>re new_flow_client@KERNEL >>2 doorbell3 >> send_handshake_syn@NIC >> TO_NET; 2 | 3 | // client->server 4 | app_new_flow_init >> context_enqueue@APP_CORE | kernel_context@KERNEL (API) >> context_dequeue@KERNEL >> classify@KERNEL >> new_flow_client@KERNEL >> doorbell3 >> send_handshake_syn@NIC >> TO_NET; 5 | 6 | 7 | [exception >> exception_enqueue@NIC >> DMA_write >>pull kernel_entry >>] recv_handshake_syn_ack@KERNEL >> new_flow_confirm@KERNEL >> doorbell4 >> nic_new_flow@NIC >> send_handshake_ack@NIC >> TO_NET; 8 | new_flow_confirm@KERNEL >> enqueue_ker2app@KERNEL | dequeue_ker2app@APP_CORE >>pull app_new_flow_ready; 9 | 10 | 11 | AppNewFlow app_new_flow; 12 | API AppNewFlow@APP_CORE { 13 | 14 | .return { 15 | port in(queue*); // in_return 16 | port out(queue*); 17 | 18 | .run() { out(in()); } 19 | } 20 | } 21 | 22 | Element NewFlowClient@KERNEL { 23 | port in(2tuple_opaque); 24 | port in_return(queue*,seq,ack); 25 | port out(uint32_t,2tuple_opaque); 26 | 27 | .run() { 28 | queue *q = allocate queue 29 | x = combine in(2tuple) and in(opaque) 30 | out(addr,x); 31 | in_return(q); 32 | } 33 | 34 | } 35 | 36 | // Flow: app_new_flow >> syscall >> new_flow_client >> doorbell >> new_flow_client >> syscall >> app_new_flow 37 | // Go until doorbell because the first half of doorbell is still on the same thread. 38 | // Essentially there is this implicit reverse flow within each hardware device. 39 | // This is not true for @NIC??? 40 | 41 | 42 | 43 | exception >> exception_queue@NIC >> DMA_write >>pull kernel_entry 44 | kernel_entry >> recv_handshake_syn_ack@KERNEL // case: new flow(client) 45 | kernel_entry >> recv_handshake_syn@KERNEL // case: new flow (server) 46 | kernel_entry >> recv_handshake_ack@KERNEL // case: new flow (server) 47 | 48 | Element KernelEntry { 49 | port in_pull(uint32_t); 50 | port in(queue_entry); 51 | port out(…); 52 | } 53 | 54 | // Pulling elements 55 | // @NIC: none 56 | // @APP_CORE/APP: API nodes 57 | // @KERNEL: need scheduling 58 | // @APP_CORE/APP non-API node: need scheduling 59 | 60 | // Consider having API for kernel 61 | // external part may have interrupt, use external libraries 62 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/queue_shared_data.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | qid = Field(Int) 5 | keylen = Field(Int) 6 | key = Field(Pointer(Uint(8)), size='state->keylen') 7 | p = Field(Pointer(Int), shared='data_region') 8 | 9 | 10 | class main(Flow): 11 | state = PerPacket(MyState) 12 | 13 | class Save(Element): 14 | def configure(self): 15 | self.inp = Input(Int, Uint(8)) 16 | self.out = Output() 17 | 18 | def impl(self): 19 | self.run_c(r''' 20 | (int len, uint8_t data) = inp(); 21 | state->qid = 0; 22 | state->key = (uint8_t *) malloc(len); 23 | state->keylen = len; 24 | for(int i=0; ip = &p[data]; 29 | output { out(); } 30 | ''') 31 | 32 | class Display(Element): 33 | def configure(self): 34 | self.inp = Input() 35 | 36 | def impl(self): 37 | self.run_c(r''' 38 | printf("%d %d %d %d\n", state->keylen, state->key[0], state->key[state.keylen-1], *state->p); 39 | fflush(stdout); 40 | ''') 41 | 42 | Enq, Deq, Scan = queue_smart.smart_queue("queue", 32, 128, 2, 1) 43 | 44 | class push(CallableSegment): 45 | def configure(self): 46 | self.inp = Input(Int, Uint(8)) 47 | 48 | def impl(self): 49 | self.inp >> main.Save() >> main.Enq() 50 | 51 | class pop(Segment): 52 | # def configure(self): 53 | # self.inp = Input(Size) 54 | 55 | def impl(self): 56 | self.core_id >> main.Deq() >> main.Display() 57 | 58 | def impl(self): 59 | MemoryRegion("data_region", 4 * 100) 60 | main.push('push', process="queue_shared_data1") 61 | main.pop('pop', process="queue_shared_data2") 62 | 63 | master_process("queue_shared_data1") 64 | 65 | c = Compiler(main) 66 | c.generate_code_as_header() 67 | c.depend = {"queue_shared_data1_main": ['queue_shared_data1'], 68 | "queue_shared_data2_main": ['queue_shared_data2']} 69 | c.compile_and_run(["queue_shared_data1_main", "queue_shared_data2_main"]) -------------------------------------------------------------------------------- /floem/include_cavium/floem-util.h: -------------------------------------------------------------------------------- 1 | #ifndef FLOEM_UTIL_H 2 | #define FLOEM_UTIL_H 3 | 4 | #include "cvmcs-nic.h" 5 | #include 6 | 7 | #define DMA_CACHE 8 | #define RUNTIME 9 | #define RUNTIME_CORES 4 10 | #define RUNTIME_START_CORE (12-RUNTIME_CORES) 11 | 12 | typedef cvmx_spinlock_t lock_t; 13 | #define qlock_init(x) cvmx_spinlock_init(x) 14 | #define qlock_lock(x) cvmx_spinlock_lock(x) 15 | #define qlock_unlock(x) cvmx_spinlock_unlock(x) 16 | 17 | #define lock_init(x) cvmx_spinlock_init(x) 18 | #define lock_lock(x) cvmx_spinlock_lock(x) 19 | #define lock_unlock(x) cvmx_spinlock_unlock(x) 20 | 21 | typedef cvmx_spinlock_t spinlock_t; 22 | #define spinlock_init(x) cvmx_spinlock_init(x) 23 | #define spinlock_lock(x) cvmx_spinlock_lock(x) 24 | #define spinlock_trylock(x) cvmx_spinlock_trylock(x) 25 | #define spinlock_unlock(x) cvmx_spinlock_unlock(x) 26 | #define spinlock_locked(x) cvmx_spinlock_locked(x) 27 | 28 | #define __sync_fetch_and_add32(ptr, inc) cvmx_atomic_fetch_and_add32(ptr, inc) 29 | #define __sync_fetch_and_add64(ptr, inc) cvmx_atomic_fetch_and_add64(ptr, inc) 30 | #define __sync_fetch_and_sub32(ptr, inc) cvmx_atomic_fetch_and_add32(ptr, -(inc)) 31 | #define __sync_fetch_and_sub64(ptr, inc) cvmx_atomic_fetch_and_add64(ptr, -(inc)) 32 | #define __sync_bool_compare_and_swap32(ptr, old, new) cvmx_atomic_compare_and_store32(ptr, old, new) 33 | #define __sync_bool_compare_and_swap64(ptr, old, new) cvmx_atomic_compare_and_store64(ptr, old, new) 34 | 35 | #define __SYNC CVMX_SYNCWS 36 | 37 | unsigned long long core_time_now_ns(); 38 | uint64_t core_time_now_us(); 39 | inline uint16_t nic_htons(uint16_t x); 40 | inline uint16_t nic_ntohs(uint16_t x); 41 | inline uint32_t nic_htonl(uint32_t x); 42 | inline uint32_t nic_ntohl(uint32_t x); 43 | inline uint64_t nic_htonp(uint64_t x); 44 | inline uint64_t nic_ntohp(uint64_t x); 45 | #define htonp(x) x 46 | #define ntohp(x) x 47 | int network_send(size_t len, uint8_t *pkt_ptr, int sending_port); 48 | 49 | #define ALIGNMENT 128 50 | #define MEM_SIZE 1024*1024*1024 51 | 52 | void shared_mm_init(); 53 | void* shared_mm_malloc(int size); 54 | void* shared_mm_memalign(int size, int alignment); 55 | void* shared_mm_realloc(void *ptr, int size); 56 | void shared_mm_free(void *ptr); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /apps/storm/storm.h: -------------------------------------------------------------------------------- 1 | #ifndef STORM_H 2 | #define STORM_H 3 | 4 | #define _GNU_SOURCE 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Set FLEXNIC requirement here! 11 | #if defined(BIGFISH_FLEXNIC) || defined(BIGFISH_FLEXNIC_DPDK) || defined(BIGFISH_FLEXNIC_DPDK2) 12 | # define FLEXNIC 13 | //# define NORMAL_QUEUE 14 | #else 15 | # define NORMAL_QUEUE 16 | #endif 17 | 18 | //#define CAVIUM 19 | //#define QUEUE_STAT 20 | //#define DEBUG_MP 21 | //#define DEBUG_DCCP 22 | //#define THREAD_AFFINITY 23 | //#define DEBUG_PERF 24 | //#define QUEUE_STAT 25 | 26 | #define MAX_VECTOR 5 // Max. tuple vector 27 | #define MAX_STR 64 28 | #define MAX_WORKERS 3 29 | #define MAX_EXECUTORS 7 30 | #define MAX_TASKS 100 31 | #define MAX_ELEMS (4 * 1024) // Queue elements 32 | //#define MAX_ELEMS 64 // Queue elements 33 | 34 | struct tuple; 35 | struct executor; 36 | 37 | typedef void (*WorkerExecute)(const struct tuple *t, struct executor *self); 38 | typedef void (*WorkerInit)(struct executor *self); 39 | typedef int (*GrouperFunc)(const struct tuple *t, struct executor *self); 40 | 41 | struct tuple { 42 | uint64_t starttime; 43 | struct { 44 | char str[MAX_STR]; 45 | int integer; 46 | } v[MAX_VECTOR]; 47 | int task, fromtask; 48 | uint8_t status; 49 | uint8_t checksum; 50 | uint8_t pad[26]; 51 | 52 | } __attribute__ ((packed)); 53 | 54 | struct executor { 55 | int taskid, outtasks[MAX_TASKS]; 56 | WorkerExecute execute; 57 | WorkerInit init; 58 | void *state; 59 | GrouperFunc grouper; 60 | bool spout; 61 | bool cpu; 62 | size_t outqueue_empty, outqueue_full, inqueue_empty, inqueue_full; 63 | #ifndef FLEXNIC_EMULATION 64 | size_t get_time, execute_time, numexecutes, emitted, recved, avglatency; 65 | size_t lastexecute_time, lastnumexecutes; 66 | #else 67 | size_t tuples, lasttuples, full; 68 | size_t wait_inq, wait_outq, memcpy_time, batchdone_time, batch_size, batches; 69 | int rx_id, workerid; 70 | #endif 71 | int exe_id; 72 | } __attribute__ ((aligned (64))); 73 | 74 | 75 | void tuple_send(struct tuple *t, struct executor *self); 76 | 77 | static inline uint64_t rdtsc(void) 78 | { 79 | uint32_t eax, edx; 80 | __asm volatile ("rdtsc" : "=a" (eax), "=d" (edx)); 81 | return ((uint64_t)edx << 32) | eax; 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /doc/library-of-c-functions.md: -------------------------------------------------------------------------------- 1 | # Library of C Functions 2 | 3 | This documentation describes utilitly functions that can be used in C implemention of an element. 4 | 5 | 1. [Locks](#Locks) 6 | 2. [Atomic Instructions](#Atomic-Instructions) 7 | 3. [Byte Order Conversion](#Byte-Order-Conversion) 8 | 4. [Memory Allocation](#Memory-Allocation) 9 | 5. [Timing](#Timing) 10 | 11 | 12 | ## 1. Locks 13 | `spinlock_t`: spin lock type 14 | ```c 15 | void spinlock_init(spinlock_t *lock) 16 | void spinlock_lock(spinlock_t *lock) 17 | void spinlock_unlock(spinlock_t *lock) 18 | ``` 19 | 20 | 21 | These are macros for GCC atomic instructions and Cavium atomic instructions. 22 | ## 2. Atomic Instructions 23 | ```c 24 | int32_t __sync_fetch_and_add32(int32_t *ptr, int32_t inc) 25 | int64_t __sync_fetch_and_add64(int64_t *ptr, int64_t inc) 26 | int32_t __sync_fetch_and_sub32(int32_t *ptr, int32_t sub) 27 | int64_t __sync_fetch_and_sub64(int64_t *ptr, int64_t sub) 28 | uint32_t __sync_bool_compare_and_swap32(uint32_t *ptr, uint32_t old_val, uint32_t new_val) 29 | uint64_t __sync_bool_compare_and_swap64(uint64_t *ptr, uint64_t old_val, uint64_t new_val) 30 | ``` 31 | 32 | This command issues a full memory barrier. 33 | ```c 34 | __SYNC; 35 | ``` 36 | 37 | 38 | ## 3. Byte Order Conversion 39 | These functions reverse the byte order when running on a CPU. They are identify functions when running on a NIC. 40 | ```c 41 | uint16_t htons(uint16_t x) 42 | uint32_t htonl(uint32_t x) 43 | uint64_t htonp(uint64_t x) 44 | ``` 45 | 46 | These functions reverse the byte order when running on a NIC. They are identify functions when running on a CPU. 47 | ```c 48 | uint16_t nic_htons(uint16_t x) 49 | uint32_t nic_htonl(uint32_t x) 50 | uint64_t nic_htonp(uint64_t x) 51 | ``` 52 | 53 | 54 | ## 4. Memory Allocation 55 | On a Cavium LiquidiO NIC, `malloc` and `free` are for allocating and deallocating memory local to a core. To allocate a memory that shared between LiquidIO core, users must use the following fucntions. 56 | ```c 57 | void* shared_mm_malloc(int size); 58 | void shared_mm_free(void *ptr); 59 | ``` 60 | 61 | 62 | ## 5. Timing 63 | On a Cavium LiquidiO NIC only. 64 | ```c 65 | uint64_t core_time_now_ns(); // nanoseconds computed from cycle count. 66 | uint64_t core_time_now_us(); // microseconds computed from cycle count. 67 | ``` 68 | -------------------------------------------------------------------------------- /mockup/TCP/tcp.c: -------------------------------------------------------------------------------- 1 | // client->server 2 | app_new_flow_init@call >> enqueue_app2ker@APP_CORE | kernel_context@KERNEL >> dequeue_app2ker@KERNEL >> new_flow_client@KERNEL >> doorbell3 >> send_handshake_syn@NIC >> TO_NET; 3 | 4 | 5 | exception >> exception_queue@NIC | kernel_entry@KERNEL >> recv_handshake_syn_ack@KERNEL >> new_flow_confirm@KERNEL >> doorbell4 >> nic_new_flow@NIC >> send_handshake_ack@NIC >> TO_NET; 6 | new_flow_confirm@KERNEL >> enqueue_ker2app@KERNEL | app_new_flow_ready@call >> dequeue_ker2app@APP_CORE >> app_new_flow_ready@return; 7 | 8 | 9 | 10 | AppNewFlowInt app_new_flow_init; 11 | API AppNewFlowInit@APP_CORE { 12 | .call { 13 | port in(socket,ip,port); 14 | port out(queue_entry); 15 | 16 | .run { out(create entry from in(0), in(1), in(2)); } 17 | } 18 | 19 | // return void 20 | } 21 | 22 | AppNewFlowReady app_new_flow_ready; 23 | API AppNewFlowReady@APP_CORE { 24 | .call { 25 | port in(); 26 | port out(command_type); 27 | 28 | .run { out(0); } 29 | } 30 | 31 | .return { 32 | port in(queue_entry); 33 | port out(socket,in,port,queue*); 34 | 35 | .run { out(extract socket,in,port,queue from in()); } 36 | } 37 | } 38 | 39 | // app_new_flow, new_flow_client, and the first half of doorbell3 run on the same CPU thread. Therefore, syscall1@return actually happens after the write to doorbell. 40 | // There is no semantics different but the meaning of execution order is diffident. 41 | // Is this okay? Or maybe we just need to change the meaning of execution order to fit this behavior 42 | 43 | 44 | Interval@KERNEL interval(1000); // generate signal every 1000 ms 45 | Kernel_entry kernel_entry; 46 | interval@KERNEL >> kernel_entry@KERNEL; 47 | 48 | 49 | exception >> exception_queue@NIC | kernel_entry >> recv_handshake_syn_ack@KERNEL // case: new flow(client) 50 | [ exception >> exception_queue@NIC ] kernel_entry >> recv_handshake_syn@KERNEL // case: new flow (server) 51 | [ exception >> exception_queue@NIC ] kernel_entry >> recv_handshake_ack@KERNEL // case: new flow (server) 52 | 53 | Element Kernel_entry { 54 | .run { 55 | Exception_t exp = get an entry from exception.queue; 56 | int command = exp.command; 57 | switch(command) { 58 | Case 0: out(recv_handshake_syn, exp); break; 59 | Case 1: out(recv_handshake_syn_ack, exp); break; 60 | Case 2: out(recv_handshake_ack, exp); break; 61 | Case 3: out(fix_order, exp); break; 62 | ... 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /floem/programs/smart_queue_entry_simpler.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | a = Field(Int) 5 | a0 = Field(Int) 6 | b0 = Field(Int) 7 | qid = Field(Int) 8 | 9 | 10 | class Save(Element): 11 | def configure(self): 12 | self.inp = Input(Int) 13 | self.out = Output() 14 | 15 | def impl(self): 16 | self.run_c(r'''state.a = inp(); state.qid = 0; output { out(); }''') 17 | 18 | class Classify(Element): 19 | def configure(self): 20 | self.inp = Input() 21 | self.out1 = Output() 22 | self.out2 = Output() 23 | 24 | def impl(self): 25 | self.run_c(r''' 26 | output switch { 27 | case (state.a % 2) == 0: out1(); 28 | else: out2(); } 29 | ''') 30 | 31 | class A0(ElementOneInOut): 32 | def impl(self): 33 | self.run_c(r'''state->a0 = state->a + 100; output { out(); }''') 34 | 35 | 36 | class B0(ElementOneInOut): 37 | def impl(self): 38 | self.run_c(r'''state->b0 = state.a * 2; output { out(); }''') 39 | 40 | class A1(Element): 41 | def configure(self): 42 | self.inp = Input() 43 | 44 | def impl(self): 45 | self.run_c(r'''printf("a1 %d\n", state.a0);''') 46 | 47 | class B1(Element): 48 | def configure(self): 49 | self.inp = Input() 50 | 51 | def impl(self): 52 | self.run_c(r'''printf("b1 %d\n", state->b0);''') 53 | 54 | class main(Flow): 55 | state = PerPacket(MyState) 56 | 57 | def impl(self): 58 | Enq, Deq, Clean = queue_smart.smart_queue("queue", 32, 16, 1, 2) 59 | 60 | class run1(CallableSegment): 61 | def configure(self): 62 | self.inp = Input(Int) 63 | 64 | def impl(self): 65 | save = Save() 66 | classify = Classify() 67 | enq = Enq() 68 | 69 | self.inp >> save >> classify 70 | classify.out1 >> A0() >> enq.inp[0] 71 | classify.out2 >> B0() >> enq.inp[1] 72 | 73 | class run2(CallableSegment): 74 | def configure(self): 75 | self.inp = Input(Int) 76 | 77 | def impl(self): 78 | deq = Deq() 79 | 80 | self.inp >> deq 81 | deq.out[0] >> A1() 82 | deq.out[1] >> B1() 83 | 84 | run1('run1') 85 | run2('run2') 86 | 87 | c = Compiler(main) 88 | c.testing = "run1(123); run1(42); run2(0); run2(0);" 89 | c.generate_code_and_run(['b1', 246, 'a1', 142]) 90 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/smart_queue_entry.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | a = Field(Int) 5 | a0 = Field(Int) 6 | b0 = Field(Int) 7 | qid = Field(Int) 8 | 9 | 10 | class Save(Element): 11 | def configure(self): 12 | self.inp = Input(Int) 13 | self.out = Output() 14 | 15 | def impl(self): 16 | self.run_c(r'''state.a = inp(); state.qid = 0; output { out(); }''') 17 | 18 | class Classify(Element): 19 | def configure(self): 20 | self.inp = Input() 21 | self.out1 = Output() 22 | self.out2 = Output() 23 | 24 | def impl(self): 25 | self.run_c(r''' 26 | output switch { 27 | case (state.a % 2) == 0: out1(); 28 | else: out2(); } 29 | ''') 30 | 31 | class A0(ElementOneInOut): 32 | def impl(self): 33 | self.run_c(r'''state->a0 = state->a + 100; output { out(); }''') 34 | 35 | 36 | class B0(ElementOneInOut): 37 | def impl(self): 38 | self.run_c(r'''state->b0 = state.a * 2; output { out(); }''') 39 | 40 | class A1(Element): 41 | def configure(self): 42 | self.inp = Input() 43 | 44 | def impl(self): 45 | self.run_c(r'''printf("a1 %d\n", state.a0);''') 46 | 47 | class B1(Element): 48 | def configure(self): 49 | self.inp = Input() 50 | 51 | def impl(self): 52 | self.run_c(r'''printf("b1 %d\n", state->b0);''') 53 | 54 | class main(Flow): 55 | state = PerPacket(MyState) 56 | 57 | def impl(self): 58 | Enq, Deq, Clean = queue_smart.smart_queue("queue", 32, 16, 1, 2) 59 | 60 | class run1(CallableSegment): 61 | def configure(self): 62 | self.inp = Input(Int) 63 | 64 | def impl(self): 65 | save = Save() 66 | classify = Classify() 67 | enq = Enq() 68 | 69 | self.inp >> save >> classify 70 | classify.out1 >> A0() >> enq.inp[0] 71 | classify.out2 >> B0() >> enq.inp[1] 72 | 73 | class run2(CallableSegment): 74 | def configure(self): 75 | self.inp = Input(Int) 76 | 77 | def impl(self): 78 | deq = Deq() 79 | 80 | self.inp >> deq 81 | deq.out[0] >> A1() 82 | deq.out[1] >> B1() 83 | 84 | run1('run1') 85 | run2('run2') 86 | 87 | c = Compiler(main) 88 | c.testing = "run1(123); run1(42); run2(0); run2(0);" 89 | c.generate_code_and_run(['b1', 246, 'a1', 142]) 90 | -------------------------------------------------------------------------------- /floem/queue_smart.py: -------------------------------------------------------------------------------- 1 | from dsl import * 2 | import graph_ir 3 | 4 | 5 | def smart_queue(name, entry_size, size, insts, channels, checksum=False, 6 | enq_blocking=False, deq_blocking=False, 7 | enq_atomic=False, deq_atomic=False, clean=False, enq_output=False): 8 | prefix = name + "_" 9 | queue = graph_ir.Queue(name, entry_size=entry_size, size=size, insts=insts, channels=channels, checksum=checksum, 10 | enq_blocking=enq_blocking, enq_atomic=enq_atomic, enq_output=enq_output, 11 | deq_blocking=deq_blocking, deq_atomic=deq_atomic) 12 | 13 | class Enqueue(Element): 14 | def configure(self): 15 | self.inp = [Input() for i in range(channels)] 16 | self.special = queue 17 | if enq_output: 18 | self.done = Output() 19 | 20 | def impl(self): 21 | if enq_output: 22 | self.run_c("state.qid; output { done(); }") 23 | else: 24 | self.run_c("state.qid;") 25 | 26 | def __init__(self, name=None, create=True): 27 | Element.__init__(self, name=name, create=create) 28 | queue.enq.append(self.instance) 29 | 30 | class Dequeue(Element): 31 | def configure(self): 32 | self.inp = Input(Int) # core 33 | self.out = [Output() for i in range(channels)] 34 | self.special = queue 35 | 36 | def impl(self): 37 | src = "" 38 | for i in range(channels): 39 | src += "out%d(); " % i 40 | self.run_c("output { %s }" % src) 41 | 42 | def __init__(self, name=None, create=True): 43 | Element.__init__(self, name=name, create=create) 44 | queue.deq = self.instance 45 | 46 | class Clean(Element): 47 | def configure(self): 48 | self.out = [Output() for i in range(channels)] 49 | self.special = queue 50 | 51 | def impl(self): 52 | src = "" 53 | for i in range(channels): 54 | src += "out%d(); " % i 55 | self.run_c("output { %s }" % src) 56 | 57 | def __init__(self, name=None, create=True): 58 | Element.__init__(self, name=name, create=create) 59 | queue.clean = self.instance 60 | 61 | Enqueue.__name__ = prefix + Enqueue.__name__ 62 | Dequeue.__name__ = prefix + Dequeue.__name__ 63 | Clean.__name__ = prefix + Clean.__name__ 64 | 65 | return Enqueue, Dequeue, Clean if clean else None -------------------------------------------------------------------------------- /floem/programs_cavium/packet_read.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Display(Element): 4 | def configure(self): 5 | self.inp = Input(SizeT, 'void *', 'void *') 6 | self.out = Output('void *', 'void *') 7 | 8 | def impl(self): 9 | self.run_c(r''' 10 | (size_t sz, void* p, void* buff) = inp(); 11 | { 12 | int i; 13 | uint8_t* pkt = (uint8_t*) p; 14 | 15 | for (i = 0; i < 16; i++) { 16 | printf("%x ", pkt[i]); 17 | } 18 | printf("\n"); 19 | } 20 | output { out(p, buff); } 21 | ''') 22 | 23 | 24 | class Const(Element): 25 | def configure(self): 26 | self.out = Output(SizeT) 27 | 28 | def impl(self): 29 | self.run_c("output { out(14 + 20 + 8 + 16); }") 30 | 31 | class Drop(Element): 32 | def configure(self): 33 | self.inp = Input() 34 | 35 | def impl(self): 36 | self.run_c(r'''while (0); ''') 37 | 38 | class PreparePkt(Element): 39 | def configure(self): 40 | self.inp = Input("void *", "void *") 41 | self.out = Output(SizeT, "void *", "void *") # size, dest_port, packet, buffer 42 | 43 | def impl(self): 44 | self.run_c(r''' 45 | (void* pkt_ptr, void* buf) = inp(); 46 | rebuild_ether_header(pkt_ptr); 47 | rebuild_ip_header(pkt_ptr); 48 | rebuild_udp_header(pkt_ptr); 49 | rebuild_payload(pkt_ptr); 50 | recalculate_ip_chksum(pkt_ptr); 51 | recalculate_udp_chksum(pkt_ptr); 52 | output { out(14 + 20 + 8 + 16, pkt_ptr, buf); } 53 | ''') 54 | 55 | from_net = net.FromNet() 56 | from_net_free = net.FromNetFree() 57 | net_alloc = net.NetAlloc() 58 | net_alloc_free = net.NetAllocFree() 59 | to_net = net.ToNet() 60 | 61 | class test(Segment): 62 | def impl(self): 63 | size = Const() 64 | display = Display() 65 | drop = Drop('drop') 66 | from_net.out >> display >> from_net_free 67 | from_net.nothing >> drop 68 | size >> net_alloc 69 | net_alloc.out >> PreparePkt() >> to_net 70 | net_alloc.oom >> drop 71 | net_alloc.out >> net_alloc_free 72 | 73 | run_order(from_net_free, size) 74 | run_order(to_net, net_alloc_free) 75 | 76 | def impl2(self): 77 | from_net.out >> Display() >> PreparePkt() >> to_net 78 | from_net.out >> from_net_free 79 | from_net.nothing >> Drop('drop') 80 | run_order(to_net, from_net_free) 81 | 82 | test('test', device=target.CAVIUM, cores=[0,1,2,3]) 83 | 84 | c = Compiler() 85 | c.include = r'''#include "packet_build.h"''' 86 | c.generate_code_as_header() 87 | -------------------------------------------------------------------------------- /floem/cache_tests/one_in_one_out_state.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class Mult2(Element): 5 | def configure(self): 6 | self.inp = Input() 7 | self.out = Output() 8 | 9 | def impl(self): 10 | self.run_c(r''' 11 | state->val = state->key * 2; 12 | output { out(); } 13 | ''') 14 | 15 | class SaveKey(Element): 16 | def configure(self): 17 | self.inp = Input(Int) 18 | self.out = Output() 19 | 20 | def impl(self): 21 | self.run_c(r''' 22 | (int x) = inp(); 23 | state->key = x; 24 | output { out(); } 25 | ''') 26 | 27 | 28 | class SaveKV(Element): 29 | def configure(self): 30 | self.inp = Input(Int, Int) 31 | self.out = Output() 32 | 33 | def impl(self): 34 | self.run_c(r''' 35 | (int x, int y) = inp(); 36 | state->key = x; 37 | state->val = y; 38 | output { out(); } 39 | ''') 40 | 41 | class OnlyVal(Element): 42 | def configure(self): 43 | self.inp = Input() 44 | self.out = Output(Int) 45 | 46 | def impl(self): 47 | self.run_c(r''' 48 | int val = state->val; 49 | output { out(val); } 50 | ''') 51 | 52 | 53 | CacheGetStart, CacheGetEnd, CacheSetStart, CacheSetEnd, CacheState = \ 54 | cache_smart.smart_cache_with_state('MyCache', (Int, 'key'), [(Int, 'val')], 55 | var_size=False, hash_value=False, 56 | write_policy=Cache.write_back, write_miss=Cache.write_alloc) 57 | 58 | 59 | class MyState(CacheState): 60 | key = Field(Int) 61 | val = Field(Int) 62 | 63 | 64 | class main(Flow): 65 | state = PerPacket(MyState) 66 | 67 | def impl(self): 68 | class compute(CallableSegment): 69 | def configure(self): 70 | self.inp = Input(Int) 71 | self.out = Output(Int) 72 | 73 | def impl(self): 74 | self.inp >> SaveKey() >> CacheGetStart() >> Mult2() >> CacheGetEnd() >> OnlyVal() >> self.out 75 | 76 | class set(CallableSegment): 77 | def configure(self): 78 | self.inp = Input(Int, Int) 79 | 80 | def impl(self): 81 | self.inp >> SaveKV() >> CacheSetStart() >> CacheSetEnd() >> library.Drop() 82 | 83 | compute('compute') 84 | set('set') 85 | 86 | 87 | c = Compiler(main) 88 | c.testing = r''' 89 | set(1, 100); 90 | out(compute(11)); out(compute(1)); out(compute(11)); out(compute(1)); 91 | set(11, 222); out(compute(11)); out(compute(1)); 92 | ''' 93 | c.generate_code_and_run([22,100,22,100, 222, 100]) -------------------------------------------------------------------------------- /mockup/TCP/tcp_component.c: -------------------------------------------------------------------------------- 1 | // main 2 | FROM_NET >> CheckConnection@NIC; 3 | CheckConnection@NIC (known) >> KnownConnection@NIC (send_ack) >> TO_NET; 4 | 5 | // common-case receive 6 | KnownConnection@NIC (in_order) >> (in) InOrder@NIC (to_app) >> (nic_put) MainQueue (app_get) 7 | <> recvInorder@API; 8 | 9 | // out-of-order 10 | KnownConnection@NIC (out_of_order) >> (in) OutOfOrder@NIC >> (nic_put) ExceptionQueue (kernel_get) 11 | <> KernelEntry@KERNEL (OOO) >> (in) OOO@KERNEL >> (kernel_put) ContextQueue (app_get) <> recvOOO@API; 12 | (in) OOO@KERNEL >> (kernel_put) ExceptionQUEUE (nic_get) 13 | >> Classifier@NIC (fix_ooo) >> UpdateFlow@NIC; 14 | 15 | // common-case send 16 | send@API >> (app_put) MainQueue (nic_get) >> CreateResponse@NIC >> TO_NET; 17 | 18 | // new connection (client) 19 | new_connecion@API >> (client_request) NewConnection@APP_CORE >> (app_put) ContextQueue (kernel_get) 20 | <> KernelEntry@KERNEL >> (client_new_connection) ConnectionManager@KERNEL >> (kernel_put) ExceptionQueue (nic_get) 21 | >> Classifier@NIC >> (hs_syn) HandShake@NIC >> TO_NET; 22 | FROM_NET >> CheckConnection@NIC (unknown) >> UnknownConnection@NIC >> (nic_put) ExceptionQueue (kernel_get) 23 | <> KernelEntry@KERNEL >> (hs_syn_ack) ConnectionManager@KERNEL >> (kernel_put) ExceptionQueue (nic_get) 24 | >> Classifier@NIC >> (hs_ack) HandShake@NIC >> TO_NET; 25 | (hs_syn_ack) ConnectionManager@KERNEL >> (kernel_put) ContextQueue (app_get) 26 | <> NewConnection@APP_CORE (check_client_request) <> new_connection_ready@API; 27 | 28 | // new connection (server) 29 | listen@API >> (server_listen) NewConnection@APP_CORE >> (app_put) ContextQueue (kernel_get) 30 | <> KernelEntry@KERNEL >> (server_listen) ConnectionManager@KERNEL; 31 | ExceptionQueue (kernel_get) 32 | <> KernelEntry@KERNEL >> (hs_syn) ConnectionManager@KERNEL >> (kernel_put) ExceptionQueue (nic_get) 33 | >> Classifier@NIC >> (hs_syn_ack) HandShake@NIC >> TO_NET; 34 | ExceptionQueue (kernel_get) 35 | <> KernelEntry@KERNEL >> (hs_ack) ConnectionManager@KERNEL >> (kernel_put) ContextQueue (app_get) 36 | <> NewConnection@APP_CORE (check_and_accept) <> check_and_accept@API; 37 | 38 | // new application thead 39 | init_NIC_interface@API >> (init_worker) APPManager@APP_CORE >> ContextQueue??? ; 40 | // There is no ContextQueue between this worker thread and kernel yet. How do they communicate? 41 | 42 | // congestion control 43 | 44 | // epoll 45 | int epoll_create(int size) 46 | int epoll_create1() 47 | epoll_ctl // register EPOLLIN and EPOLLOUT on all payload buffer 48 | epoll_wait 49 | epoll_pwait 50 | 51 | // Seem like we need global state for TCP because many action require flow state 52 | -------------------------------------------------------------------------------- /apps/benchmarks_network_func/cluster-setup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Cluster network setup information. 3 | * 4 | * This is a static (read-only) loaded table. 5 | */ 6 | #ifndef _CLUSTER_SETUP_H 7 | #define _CLUSTER_SETUP_H 8 | 9 | #ifdef CAVIUM 10 | #include "cvmx.h" 11 | #endif 12 | 13 | #define MAC_ADDRESS_LEN 6 14 | #define IP_ADDRESS_LEN 4 15 | 16 | typedef struct _entity { 17 | uint8_t mac[MAC_ADDRESS_LEN]; 18 | uint8_t ip[IP_ADDRESS_LEN]; 19 | } __attribute__((packed)) entity; 20 | 21 | typedef struct _flow { 22 | entity src; 23 | entity des; 24 | } __attribute__((packed)) flow; 25 | 26 | #ifdef CAVIUM 27 | CVMX_SHARED 28 | #endif 29 | flow mycluster[] = { 30 | { // n72 -> n73 31 | .src = { 32 | .mac = {0x00, 0x02, 0xc9, 0x4e, 0xde, 0xe4}, 33 | .ip = {0x0a, 0x03, 0x00, 0x49}, 34 | }, 35 | .des = { 36 | .mac = {0x00, 0x02, 0xc9, 0x4e, 0xe9, 0x38}, 37 | .ip = {0x0a, 0x03, 0x00, 0x48}, 38 | } 39 | }, 40 | { // n73 -> n72 41 | .src = { 42 | .mac = {0x00, 0x02, 0xc9, 0x4e, 0xe9, 0x38}, 43 | .ip = {0x0a, 0x03, 0x00, 0x48}, 44 | }, 45 | .des = { 46 | .mac = {0x00, 0x02, 0xc9, 0x4e, 0xde, 0xe4}, 47 | .ip = {0x0a, 0x03, 0x00, 0x49}, 48 | } 49 | }, 50 | { // n25 -> n29 51 | .src = { 52 | .mac = {0x3c, 0xfd, 0xfe, 0xaa, 0xde, 0xd0}, 53 | .ip = {0x0a, 0x03, 0x00, 0x19}, 54 | }, 55 | .des = { 56 | .mac = {0x3c, 0xfd, 0xfe, 0xaa, 0xd1, 0xe0}, 57 | .ip = {0x0a, 0x03, 0x00, 0x1d}, 58 | } 59 | }, 60 | { // n29 -> n25 61 | .src = { 62 | .mac = {0x3c, 0xfd, 0xfe, 0xaa, 0xd1, 0xe0}, 63 | .ip = {0x0a, 0x03, 0x00, 0x1d}, 64 | }, 65 | .des = { 66 | .mac = {0x3c, 0xfd, 0xfe, 0xaa, 0xde, 0xd0}, 67 | .ip = {0x0a, 0x03, 0x00, 0x19}, 68 | }, 69 | }, 70 | { // n27 -> n28 71 | .src = { 72 | .mac = {0x3c, 0xfd, 0xfe, 0xaa, 0xd2, 0x28}, 73 | .ip = {0x0a, 0x03, 0x00, 0x1b}, 74 | }, 75 | .des = { 76 | .mac = {0x3c, 0xfd, 0xfe, 0xa1, 0x11, 0x2c}, 77 | .ip = {0x0a, 0x03, 0x00, 0x1c}, 78 | }, 79 | }, 80 | { // n28 -> n27 81 | .src = { 82 | .mac = {0x3c, 0xfd, 0xfe, 0xa1, 0x11, 0x2c}, 83 | .ip = {0x0a, 0x03, 0x00, 0x1c}, 84 | }, 85 | .des = { 86 | .mac = {0x3c, 0xfd, 0xfe, 0xaa, 0xd2, 0x28}, 87 | .ip = {0x0a, 0x03, 0x00, 0x1b}, 88 | }, 89 | } 90 | }; 91 | 92 | #endif /* _CLUSTER_SETUP_H */ 93 | -------------------------------------------------------------------------------- /apps/benchmarks_simple/inqueue2.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_nic_cores = 11 4 | n_queues = 9 5 | 6 | class MyState(State): 7 | key = Field(Int) 8 | qid = Field(Int) 9 | 10 | 11 | class main(Flow): 12 | state = PerPacket(MyState) 13 | 14 | def impl(self): 15 | # Queue 16 | RxEnq, RxDeq, RxScan = queue_smart.smart_queue("rx_queue", entry_size=64, size=1024, insts=n_queues, 17 | channels=1, enq_blocking=True, enq_atomic=True, enq_output=False) 18 | rx_enq = RxEnq() 19 | rx_deq = RxDeq() 20 | 21 | class MakeKey(Element): 22 | def configure(self): 23 | self.out = Output() 24 | 25 | def impl(self): 26 | self.run_c(r''' 27 | state.key = 99; 28 | static int qid = 0; 29 | state.qid= qid; 30 | qid = (qid+1) %s %d; 31 | 32 | output { out(); } 33 | ''' % ('%', n_queues)) 34 | 35 | 36 | class nic_rx(Segment): 37 | def impl(self): 38 | MakeKey() >> rx_enq.inp[0] 39 | 40 | 41 | ############################ CPU ############################# 42 | class Scheduler(Element): 43 | def configure(self): 44 | self.inp = Input(Int) 45 | self.out = Output(Int) 46 | 47 | def impl(self): 48 | self.run_c(r''' 49 | (int core_id) = inp(); 50 | output { out(core_id); } 51 | ''') 52 | 53 | class Display(Element): 54 | def configure(self): 55 | self.inp = Input() 56 | 57 | def impl(self): 58 | self.run_c(r''' 59 | void *key = state.key; 60 | 61 | static __thread size_t count = 0; 62 | static __thread uint64_t lasttime = 0; 63 | count++; 64 | if(count == 1000000) { 65 | struct timeval now; 66 | gettimeofday(&now, NULL); 67 | 68 | uint64_t thistime = now.tv_sec*1000000 + now.tv_usec; 69 | printf("%zu pkts/s %f Gbits/s\n", (count * 1000000)/(thistime - lasttime), (count * 64 * 8.0)/(thistime - lasttime)/1000); 70 | lasttime = thistime; 71 | count = 0; 72 | } 73 | ''') 74 | 75 | class run(Segment): 76 | def impl(self): 77 | self.core_id >> rx_deq 78 | rx_deq.out[0] >> Display() 79 | 80 | nic_rx('nic_rx', device=target.CAVIUM, cores=range(n_nic_cores)) 81 | run('run', process='app', cores=range(n_queues)) 82 | 83 | 84 | c = Compiler(main) 85 | c.include = r''' 86 | #include "protocol_binary.h" 87 | ''' 88 | c.generate_code_as_header() 89 | c.depend = ['app'] 90 | c.compile_and_run("test_queue") 91 | -------------------------------------------------------------------------------- /apps/benchmarks_simple/inout.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_nic_rx = 1 4 | n_nic_tx = 1 5 | n_queues = 1 6 | 7 | class MyState(State): 8 | key = Field(Uint(64)) 9 | qid = Field(Int) 10 | 11 | 12 | class main(Flow): 13 | state = PerPacket(MyState) 14 | 15 | def impl(self): 16 | # Queue 17 | RxEnq, RxDeq, RxScan = queue_smart.smart_queue("rx_queue", entry_size=64, size=1024, insts=n_queues, 18 | channels=1, enq_blocking=True) 19 | TxEnq, TxDeq, TxScan = queue_smart.smart_queue("tx_queue", entry_size=64, size=1024, insts=n_queues, 20 | channels=1, enq_blocking=True) 21 | rx_enq = RxEnq() 22 | rx_deq = RxDeq() 23 | tx_enq = TxEnq() 24 | tx_deq = TxDeq() 25 | 26 | ############################ NIC RX ############################# 27 | class MakeKey(Element): 28 | def configure(self): 29 | self.out = Output() 30 | 31 | def impl(self): 32 | self.run_c(r''' 33 | state.qid= 0; 34 | state.key = core_time_now_us(); 35 | 36 | output { out(); } 37 | ''') 38 | 39 | class nic_rx(Segment): 40 | def impl(self): 41 | MakeKey() >> rx_enq.inp[0] 42 | 43 | 44 | ############################ CPU ############################# 45 | class run(Segment): 46 | def impl(self): 47 | self.core_id >> rx_deq 48 | rx_deq.out[0] >> tx_enq.inp[0] 49 | 50 | ############################ NIC RX ############################# 51 | 52 | class Display(Element): 53 | def configure(self): 54 | self.inp = Input() 55 | 56 | def impl(self): 57 | self.run_c(r''' 58 | uint64_t now = core_time_now_us(); 59 | uint64_t latency = now - state.key; 60 | 61 | static __thread size_t count = 0; 62 | static __thread size_t latency_tot = 0; 63 | count++; 64 | latency_tot += latency; 65 | if(count == 1000) { 66 | printf("latency = %f\n", 1.0*latency_tot/count); 67 | count = latency_tot = 0; 68 | } 69 | ''') 70 | 71 | class nic_tx(Segment): 72 | def impl(self): 73 | self.core_id >> tx_deq 74 | tx_deq.out[0] >> Display() 75 | 76 | nic_rx('nic_rx', device=target.CAVIUM, cores=[1]) 77 | nic_tx('nic_tx', device=target.CAVIUM, cores=[0]) 78 | run('run', process='app', cores=range(n_queues)) 79 | 80 | 81 | c = Compiler(main) 82 | c.generate_code_as_header() 83 | c.depend = ['app'] 84 | c.compile_and_run("test_queue") 85 | -------------------------------------------------------------------------------- /floem/process_handling.py: -------------------------------------------------------------------------------- 1 | from graph import AddressOf 2 | import target 3 | 4 | def assign_process_for_state_instance(g, process, st_inst_name): 5 | st_inst = g.state_instances[st_inst_name] 6 | state = st_inst.state 7 | st_inst.processes.add(process) 8 | state.processes.add(process) 9 | 10 | def inner(inits): 11 | if inits: 12 | for x in inits: 13 | if isinstance(x, AddressOf): 14 | assign_process_for_state_instance(g, process, x.of) 15 | elif isinstance(x, str) and x in g.state_instances: 16 | assign_process_for_state_instance(g, process, x) 17 | elif isinstance(x, list): 18 | inner(x) 19 | 20 | inner(st_inst.init) 21 | 22 | 23 | def annotate_process_info(g): 24 | if g.master_process: 25 | g.processes.add(g.master_process) 26 | 27 | for instance in g.instances.values(): 28 | process = g.process_of_thread(instance.thread) 29 | device = g.device_of_thread(instance.thread) 30 | 31 | if device[0] == target.CAVIUM: 32 | process = device[0] 33 | 34 | g.process2device[process] = device[0] 35 | g.processes.add(process) 36 | g.devices.add(device[0]) 37 | instance.process = process 38 | instance.device = device 39 | for st_inst_name in instance.state_args: 40 | assign_process_for_state_instance(g, process, st_inst_name) 41 | 42 | if g.master_process is None: 43 | if len(g.processes) > 0: 44 | g.master_process = [p for p in g.processes][0] 45 | else: 46 | g.master_process = g.default_process 47 | 48 | for api in g.threads_API: 49 | process = g.process_of_thread(api.name) 50 | api.process = process 51 | 52 | for state_inst in g.state_instances.values(): 53 | if len(state_inst.processes) > 1: 54 | pointer = state_inst.state.content.find('*') 55 | if pointer >= 0: 56 | if state_inst.buffer_for: 57 | raise Exception("Element instance '%s' is receiving data from an instance in a different process.\n" 58 | % state_inst.name 59 | + "The data includes a pointer, which shouldn't be shared between multiple processes.\n" 60 | + "Consider inserting a smart queue between the sender instance and the receiver instance '%s'." 61 | % state_inst.buffer_for) 62 | else: 63 | raise Exception("State instance '%s' is shared between multiple processes (%s), but it contains pointer,\n" 64 | % (state_inst.name, state_inst.processes) 65 | + "which shouldn't be shared between multiple processes.") 66 | -------------------------------------------------------------------------------- /apps/storm/collections/hash_table.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file 3 | * \brief Barrelfish collections library hash table 4 | */ 5 | /* 6 | * Copyright (c) 2010, ETH Zurich. 7 | * All rights reserved. 8 | * 9 | * This file is distributed under the terms in the attached LICENSE file. 10 | * If you do not find this file, copies can be found by writing to: 11 | * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 12 | */ 13 | 14 | #ifndef _HASH_TABLE_H_ 15 | #define _HASH_TABLE_H_ 16 | 17 | #include "list.h" 18 | 19 | /* 20 | * a simple hash table. 21 | */ 22 | 23 | typedef void (* collections_hash_data_free)(void *); 24 | 25 | typedef struct _collections_hash_table { 26 | // number of buckets in the table. 27 | int num_buckets; 28 | 29 | // pointer to the buckets. 30 | collections_listnode **buckets; 31 | 32 | // total number of elements in the table. 33 | uint32_t num_elems; 34 | 35 | // function that knows how to free inserted data resources 36 | collections_hash_data_free data_free; 37 | 38 | // a pointer to keep track of 39 | // traversing the hash table 40 | int32_t cur_bucket_num; 41 | } collections_hash_table; 42 | 43 | /* 44 | * Structure of a hash table element. 45 | */ 46 | typedef struct _collections_hash_elem { 47 | 48 | uint64_t key; 49 | 50 | void *data; 51 | } collections_hash_elem; 52 | 53 | #define NUM_BUCKETS 1013 54 | 55 | #ifdef __cplusplus 56 | extern "C" { 57 | #endif // __cplusplus 58 | 59 | 60 | /* 61 | * functions ... 62 | */ 63 | void collections_hash_create(collections_hash_table **t, collections_hash_data_free f); 64 | void collections_hash_create_with_buckets(collections_hash_table **t, int num_buckets, collections_hash_data_free f); 65 | void collections_hash_release(collections_hash_table *t); 66 | void collections_hash_insert(collections_hash_table *t, uint64_t key, void *data); 67 | void* collections_hash_find(collections_hash_table *t, uint64_t key); 68 | void collections_hash_delete(collections_hash_table *t, uint64_t key); 69 | uint32_t collections_hash_size(collections_hash_table *t); 70 | int32_t collections_hash_traverse_start(collections_hash_table* t); 71 | void* collections_hash_traverse_next(collections_hash_table* t, uint64_t *key); 72 | int32_t collections_hash_traverse_end(collections_hash_table* t); 73 | 74 | /* 75 | * Visitor function: returns 0 when visit should be considered finish. 76 | */ 77 | typedef int (*collections_hash_visitor_func)(uint64_t key, void *data, void *arg); 78 | 79 | /* 80 | * Apply function to all elements in hash table or until function indicates 81 | * function application should stop. 82 | * 83 | * Returns non-zero if all elements in table visited, 0 otherwise. 84 | */ 85 | int collections_hash_visit(collections_hash_table *t, collections_hash_visitor_func collections_hash_visitor, void *arg); 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif // __cplusplus 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/smart_queue_many2one.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | a = Field(Int) 5 | a0 = Field(Int) 6 | b0 = Field(Int) 7 | qid = Field(Int) 8 | 9 | 10 | class Save(Element): 11 | def configure(self): 12 | self.inp = Input(Int) 13 | self.out = Output() 14 | 15 | def impl(self): 16 | self.run_c(r'''state.a = inp(); state.qid = 0; output { out(); }''') 17 | 18 | class Classify(Element): 19 | def configure(self): 20 | self.inp = Input() 21 | self.out1 = Output() 22 | self.out2 = Output() 23 | 24 | def impl(self): 25 | self.run_c(r''' 26 | output switch { 27 | case (state.a % 2) == 0: out1(); 28 | else: out2(); } 29 | ''') 30 | 31 | class A0(ElementOneInOut): 32 | def impl(self): 33 | self.run_c(r'''state.a0 = state.a + 100; output { out(); }''') 34 | 35 | 36 | class B0(ElementOneInOut): 37 | def impl(self): 38 | self.run_c(r'''state.b0 = state.a * 2; output { out(); }''') 39 | 40 | class A1(Element): 41 | def configure(self): 42 | self.inp = Input() 43 | 44 | def impl(self): 45 | self.run_c(r'''printf("a1 %d\n", state.a0);''') 46 | 47 | class B1(Element): 48 | def configure(self): 49 | self.inp = Input() 50 | 51 | def impl(self): 52 | self.run_c(r'''printf("b1 %d\n", state.b0);''') 53 | 54 | class Print(Element): 55 | def configure(self, x): 56 | self.inp = Input() 57 | self.x = x 58 | 59 | def impl(self): 60 | self.run_c(r'''printf("clean %s!\n");''' % self.x) 61 | 62 | class main(Flow): 63 | state = PerPacket(MyState) 64 | 65 | def impl(self): 66 | Enq, Deq, Clean = queue_smart.smart_queue("queue", 32, 1, 1, 2, clean=True) 67 | 68 | class run1(CallableSegment): 69 | def configure(self): 70 | self.inp = Input(Int) 71 | 72 | def impl(self): 73 | save = Save() 74 | classify = Classify() 75 | enq = Enq() 76 | 77 | self.inp >> save >> classify 78 | classify.out1 >> A0() >> enq.inp[0] 79 | classify.out2 >> B0() >> enq.inp[1] 80 | 81 | clean = Clean() 82 | 83 | clean.out[0] >> Print(configure='a') 84 | clean.out[1] >> Print(configure='b') 85 | 86 | 87 | class run2(CallableSegment): 88 | def configure(self): 89 | self.inp = Input(Int) 90 | 91 | def impl(self): 92 | deq = Deq() 93 | 94 | self.inp >> deq 95 | deq.out[0] >> A1() 96 | deq.out[1] >> B1() 97 | 98 | run1('run1') 99 | run2('run2') 100 | 101 | 102 | c = Compiler(main) 103 | c.testing = "run1(123); run2(0); run1(42); run2(0);" 104 | c.generate_code_and_run(['b1', 246, 'clean', 'b!', 'a1', 142]) 105 | -------------------------------------------------------------------------------- /floem/workspace.py: -------------------------------------------------------------------------------- 1 | from collection import InstancesCollection 2 | import program 3 | 4 | 5 | ######################## Scope ########################## 6 | decls = [[]] 7 | decl_dict = {} 8 | scope = [[]] 9 | stack = [] 10 | inst_collection = [InstancesCollection()] 11 | 12 | 13 | def workspace_reset(): 14 | global decls, decl_dict, scope, stack, inst_collection 15 | decls = [[]] 16 | decl_dict = {} 17 | scope = [[]] 18 | stack = [] 19 | inst_collection = [InstancesCollection()] 20 | 21 | 22 | def get_last_decl(): 23 | global decls 24 | assert len(decls) == 1, "Compile error: there are multiple scopes remained." 25 | return decls[0] 26 | 27 | 28 | def decl_append(x): 29 | decls[-1].append(x) 30 | decl_dict[x.name] = x 31 | 32 | 33 | def get_decl(x, env=decl_dict): 34 | if x in env: 35 | return env[x] 36 | elif '__up__' in env: 37 | return get_decl(x, env=env['__up__']) 38 | else: 39 | return False 40 | 41 | 42 | def push_decl(): 43 | decls.append([]) 44 | global decl_dict 45 | decl_dict = {'__up__': decl_dict} 46 | 47 | 48 | def pop_decl(): 49 | global decl_dict 50 | decl_dict = decl_dict['__up__'] 51 | 52 | global decls 53 | decl = decls[-1] 54 | decls = decls[:-1] 55 | return decl 56 | 57 | def get_last_scope(): 58 | global scope 59 | assert len(scope) == 1, "Compile error: there are multiple scopes remained." 60 | return scope[0] 61 | 62 | 63 | def get_current_scope(): 64 | return scope[-1] 65 | 66 | 67 | def scope_append(x): 68 | scope[-1].append(x) 69 | if isinstance(x, program.ElementInstance): 70 | inst_collection[-1].add(x.name) 71 | elif isinstance(x, program.Connect): 72 | inst_collection[-1].add(x.ele1) 73 | inst_collection[-1].add(x.ele2) 74 | 75 | 76 | def scope_prepend(x): 77 | scope[-1].insert(0, x) 78 | 79 | 80 | def push_scope(name): 81 | scope.append([]) 82 | stack.append(name) 83 | inst_collection.append(InstancesCollection()) 84 | 85 | 86 | def merge_scope(): 87 | global scope, stack, inst_collection 88 | stack = stack[:-1] 89 | my_scope = scope[-1] 90 | scope = scope[:-1] 91 | scope[-1] = scope[-1] + my_scope 92 | my_collection = inst_collection[-1] 93 | inst_collection = inst_collection[:-1] 94 | inst_collection[-1].union(my_collection) 95 | return my_collection 96 | 97 | 98 | def pop_scope(): 99 | global scope, stack, inst_collection 100 | stack = stack[:-1] 101 | my_scope = scope[-1] 102 | my_collection = inst_collection[-1] 103 | scope = scope[:-1] 104 | inst_collection = inst_collection[:-1] 105 | return my_scope, my_collection 106 | 107 | 108 | def get_current_collection(): 109 | return inst_collection[-1] 110 | 111 | 112 | def get_node_name(name): 113 | if len(stack) > 0: 114 | return "_".join(stack) + "_" + name 115 | else: 116 | return name 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /apps/benchmarks_simple/inqueue1core.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_queues = 8 4 | n_nic_cores = 11 5 | size = 256 6 | 7 | class MyState(State): 8 | key = Field(Int) 9 | qid = Field(Int) 10 | data = Field('void*', size='state.key') 11 | 12 | 13 | class main(Flow): 14 | state = PerPacket(MyState) 15 | 16 | def impl(self): 17 | # Queue 18 | RxEnq, RxDeq, RxScan = queue_smart.smart_queue("rx_queue", entry_size=size, size=512, insts=n_queues, 19 | channels=1, enq_blocking=True, enq_atomic=True, enq_output=False) 20 | rx_enq = RxEnq() 21 | rx_deq = RxDeq() 22 | 23 | class MakeKey(Element): 24 | def configure(self): 25 | self.out = Output() 26 | 27 | def impl(self): 28 | self.run_c(r''' 29 | static void* p = NULL; 30 | 31 | int n = 246; 32 | if(p == NULL) p = malloc(n); 33 | 34 | state.key = n; 35 | state.data = p; 36 | 37 | static __thread int qid = 0; 38 | state.qid = qid; 39 | qid = (qid + 1) %s %d; 40 | 41 | output { out(); } 42 | ''' % ('%', n_queues)) 43 | 44 | 45 | class nic_rx(Segment): 46 | def impl(self): 47 | MakeKey() >> rx_enq.inp[0] 48 | 49 | 50 | ############################ CPU ############################# 51 | class Scheduler(Element): 52 | def configure(self): 53 | self.inp = Input(Int) 54 | self.out = Output(Int) 55 | 56 | def impl(self): 57 | self.run_c(r''' 58 | (int core_id) = inp(); 59 | output { out(core_id); } 60 | ''') 61 | 62 | class Display(Element): 63 | def configure(self): 64 | self.inp = Input() 65 | 66 | def impl(self): 67 | self.run_c(r''' 68 | void *key = state.key; 69 | state.data; 70 | 71 | static __thread size_t count = 0; 72 | static __thread uint64_t lasttime = 0; 73 | count++; 74 | if(count == 1000000) { 75 | struct timeval now; 76 | gettimeofday(&now, NULL); 77 | 78 | uint64_t thistime = now.tv_sec*1000000 + now.tv_usec; 79 | printf("%s pkts/s %s Gbits/s\n", (count * 1000000)/(thistime - lasttime), (count * %d * 8.0)/(thistime - lasttime)/1000); 80 | lasttime = thistime; 81 | count = 0; 82 | } 83 | ''' % ('%zu', '%f', size)) 84 | 85 | class run(Segment): 86 | def impl(self): 87 | self.core_id >> rx_deq 88 | rx_deq.out[0] >> Display() 89 | 90 | nic_rx('nic_rx', device=target.CAVIUM, cores=range(n_nic_cores)) 91 | run('run', process='app', cores=range(n_queues)) 92 | 93 | 94 | c = Compiler(main) 95 | c.include = r''' 96 | #include "protocol_binary.h" 97 | ''' 98 | c.generate_code_as_header() 99 | c.depend = ['app'] 100 | c.compile_and_run("test_queue") 101 | -------------------------------------------------------------------------------- /apps/memcached_split/nicif.h: -------------------------------------------------------------------------------- 1 | #ifndef NICIF_H_ 2 | #define NICIF_H_ 3 | #include 4 | #define DATA_REGION_NAME "/mykvs_data" 5 | #define INFO_REGION_NAME "/mykvs_info" 6 | #define CORE_REGION_NAME "/mykvs_core%02u" 7 | #define CORE_REGION_NAMEMAX 16 8 | #define INFO_NRETA 128 9 | #define SEG_ITEMHDRSZ 24 10 | 11 | 12 | struct info_region { 13 | uint32_t cores; 14 | uint32_t hash_key[10]; 15 | uint8_t reta[INFO_NRETA]; 16 | uint8_t pad[0x1000 - 44 - INFO_NRETA]; 17 | } __attribute__((packed)); 18 | struct core_region { 19 | uint32_t cq_off; 20 | uint32_t cq_len; 21 | uint32_t eq_off; 22 | uint32_t eq_len; 23 | uint8_t pad[0x1000 - 16]; 24 | } __attribute__((packed)); 25 | #define CQE_ALIGN 8U 26 | #define CQE_FLAG_HWOWN 0x0001 27 | #define CQE_TYPE_SHIFT 8 28 | #define CQE_TYPE_MASK 0xFF00 29 | #define CQE_TYPE_NOP 0x00 30 | #define CQE_TYPE_GRESP 0x01 31 | #define CQE_TYPE_SRESP 0x02 32 | #define CQE_TYPE_ERR 0x03 33 | #define CQE_TYPE_LOG 0x04 34 | typedef struct { 35 | uint16_t flags; 36 | uint16_t len; 37 | } __attribute__((packed)) cq_entry; 38 | typedef struct { 39 | uint16_t flags; 40 | uint16_t len; 41 | //uint32_t client; 42 | //uint32_t vallen; 43 | //uint32_t keylen; 44 | uint64_t opaque; 45 | uint64_t item; 46 | //void* item; 47 | } __attribute__((packed)) cqe_send_getresponse; 48 | typedef struct { 49 | uint16_t flags; 50 | uint16_t len; 51 | //uint32_t client; 52 | uint64_t opaque; 53 | } __attribute__((packed)) cqe_send_setresponse; 54 | typedef struct { 55 | uint16_t flags; 56 | uint16_t len; 57 | uint16_t datalen; 58 | uint16_t error; 59 | uint64_t opaque; 60 | uint8_t data[]; 61 | } __attribute__((packed)) cqe_send_error; 62 | typedef struct { 63 | uint16_t flags; 64 | uint16_t len; 65 | uint32_t pad0; 66 | uint64_t segbase; 67 | uint64_t seglen; 68 | //void* segment; 69 | } __attribute__((packed)) cqe_add_logseg; 70 | #define EQE_ALIGN 8U 71 | #define EQE_FLAG_SWOWN 0x0001 72 | #define EQE_TYPE_SHIFT 8 73 | #define EQE_TYPE_MASK 0xFF00 74 | #define EQE_TYPE_NOP 0x00 75 | #define EQE_TYPE_RXGET 0x01 76 | #define EQE_TYPE_RXSET 0x02 77 | #define EQE_TYPE_SEGFULL 0x03 78 | typedef struct { 79 | uint16_t flags; 80 | uint16_t len; 81 | } __attribute__((packed)) eq_entry; 82 | typedef struct { 83 | uint16_t flags; 84 | uint16_t len; 85 | //uint32_t client; 86 | uint64_t opaque; 87 | uint32_t hash; 88 | uint16_t keylen; 89 | uint8_t key[]; 90 | //void* key; 91 | } __attribute__((packed)) eqe_rx_get; 92 | typedef struct { 93 | uint16_t flags; 94 | uint16_t len; 95 | //uint32_t client; 96 | uint64_t opaque; 97 | uint64_t item; 98 | //void* item; 99 | } __attribute__((packed)) eqe_rx_set; 100 | typedef struct { 101 | uint16_t flags; 102 | uint16_t len; 103 | uint32_t pad0; 104 | uint64_t last; 105 | //void* segment; 106 | } __attribute__((packed)) eqe_seg_full; 107 | #endif // ndef NICIF_H_ -------------------------------------------------------------------------------- /floem/programs/hton1.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | 4 | class protocol_binary_request_header_request(State): 5 | magic = Field(Uint(8)) 6 | opcode = Field(Uint(8)) 7 | keylen = Field(Uint(16)) 8 | extlen = Field(Uint(8)) 9 | datatype = Field(Uint(8)) 10 | status = Field(Uint(16)) 11 | bodylen = Field(Uint(32)) 12 | opaque = Field(Uint(32)) 13 | cas = Field(Uint(64)) 14 | 15 | # Tell compiler not to generate this struct because it's already declared in some other header file. 16 | def init(self): self.declare = False 17 | 18 | class protocol_binary_request_header(State): 19 | request = Field(protocol_binary_request_header_request) 20 | 21 | def init(self): self.declare = False 22 | 23 | 24 | class iokvs_message(State): 25 | ether = Field('struct ether_hdr') 26 | ipv4 = Field('struct ipv4_hdr') 27 | udp = Field('struct udp_hdr') 28 | mcudp = Field('memcached_udp_header') 29 | mcr = Field(protocol_binary_request_header) 30 | payload = Field(Array(Uint(8))) 31 | layout = [ether, ipv4, udp, mcudp, mcr, payload] 32 | 33 | #def init(self): self.declare = False 34 | 35 | 36 | class Display(Element): 37 | def configure(self): 38 | self.inp = Input(SizeT, 'void*', 'void*') 39 | self.out = Output('void*', 'void*') 40 | 41 | def impl(self): 42 | self.run_c(r''' 43 | (size_t size, void* p, void* buff) = inp(); 44 | iokvs_message* m = (iokvs_message*) p; 45 | printf("packet: magic = %d, opcode = %d, keylen = %d, bodylen = %d\n", m->mcr.request.magic, m->mcr.request.opcode, m->mcr.request.keylen, m->mcr.request.bodylen); 46 | //int offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(memcached_udp_header); 47 | //printf("offset = %d, %p - %p\n",offset, &m->mcr.request.magic, m); 48 | 49 | /* uint8_t* x = (uint8_t*) p; 50 | int i; 51 | for(i=0; i<64; i++) { 52 | if(i % 16 == 0) printf("\n"); 53 | printf("%x ", x[i]); 54 | } 55 | printf("---------------\n"); 56 | 57 | for(i=offset; i< offset + 16; i++) { 58 | if(i % 16 == 0) printf("\n"); 59 | printf("%x ", x[i]); 60 | } 61 | */ 62 | output { out(p, buff); } 63 | ''') 64 | 65 | class Drop(Element): 66 | def configure(self): 67 | self.inp = Input() 68 | 69 | def impl(self): 70 | self.run_c("") 71 | 72 | class run(Segment): 73 | def impl(self): 74 | from_net = net.FromNet() 75 | from_net_free = net.FromNetFree() 76 | hton = net.HTON(configure=['iokvs_message']) 77 | 78 | from_net.out >> hton >> Display() >> from_net_free 79 | from_net.nothing >> Drop() 80 | 81 | iokvs_message() 82 | run('run', process='dpdk') 83 | 84 | c = Compiler() 85 | c.include = r''' 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include "protocol_binary.h" 92 | ''' 93 | c.testing = r''' 94 | while(1) pause(); 95 | ''' 96 | c.generate_code_and_run() 97 | -------------------------------------------------------------------------------- /apps/memcached_cpu_only/nicif.h: -------------------------------------------------------------------------------- 1 | #ifndef NICIF_H_ 2 | #define NICIF_H_ 3 | #include 4 | #define DATA_REGION_NAME "/mykvs_data" 5 | #define INFO_REGION_NAME "/mykvs_info" 6 | #define CORE_REGION_NAME "/mykvs_core%02u" 7 | #define CORE_REGION_NAMEMAX 16 8 | #define INFO_NRETA 128 9 | #define SEG_ITEMHDRSZ 24 10 | 11 | 12 | struct info_region { 13 | uint32_t cores; 14 | uint32_t hash_key[10]; 15 | uint8_t reta[INFO_NRETA]; 16 | uint8_t pad[0x1000 - 44 - INFO_NRETA]; 17 | } __attribute__((packed)); 18 | struct core_region { 19 | uint32_t cq_off; 20 | uint32_t cq_len; 21 | uint32_t eq_off; 22 | uint32_t eq_len; 23 | uint8_t pad[0x1000 - 16]; 24 | } __attribute__((packed)); 25 | #define CQE_ALIGN 8U 26 | #define CQE_FLAG_HWOWN 0x0001 27 | #define CQE_TYPE_SHIFT 8 28 | #define CQE_TYPE_MASK 0xFF00 29 | #define CQE_TYPE_NOP 0x00 30 | #define CQE_TYPE_GRESP 0x01 31 | #define CQE_TYPE_SRESP 0x02 32 | #define CQE_TYPE_ERR 0x03 33 | #define CQE_TYPE_LOG 0x04 34 | typedef struct { 35 | uint16_t flags; 36 | uint16_t len; 37 | } __attribute__((packed)) cq_entry; 38 | typedef struct { 39 | uint16_t flags; 40 | uint16_t len; 41 | //uint32_t client; 42 | //uint32_t vallen; 43 | //uint32_t keylen; 44 | uint64_t opaque; 45 | uint64_t item; 46 | //void* item; 47 | } __attribute__((packed)) cqe_send_getresponse; 48 | typedef struct { 49 | uint16_t flags; 50 | uint16_t len; 51 | //uint32_t client; 52 | uint64_t opaque; 53 | } __attribute__((packed)) cqe_send_setresponse; 54 | typedef struct { 55 | uint16_t flags; 56 | uint16_t len; 57 | uint16_t datalen; 58 | uint16_t error; 59 | uint64_t opaque; 60 | uint8_t data[]; 61 | } __attribute__((packed)) cqe_send_error; 62 | typedef struct { 63 | uint16_t flags; 64 | uint16_t len; 65 | uint32_t pad0; 66 | uint64_t segbase; 67 | uint64_t seglen; 68 | //void* segment; 69 | } __attribute__((packed)) cqe_add_logseg; 70 | #define EQE_ALIGN 8U 71 | #define EQE_FLAG_SWOWN 0x0001 72 | #define EQE_TYPE_SHIFT 8 73 | #define EQE_TYPE_MASK 0xFF00 74 | #define EQE_TYPE_NOP 0x00 75 | #define EQE_TYPE_RXGET 0x01 76 | #define EQE_TYPE_RXSET 0x02 77 | #define EQE_TYPE_SEGFULL 0x03 78 | typedef struct { 79 | uint16_t flags; 80 | uint16_t len; 81 | } __attribute__((packed)) eq_entry; 82 | typedef struct { 83 | uint16_t flags; 84 | uint16_t len; 85 | //uint32_t client; 86 | uint64_t opaque; 87 | uint32_t hash; 88 | uint16_t keylen; 89 | uint8_t key[]; 90 | //void* key; 91 | } __attribute__((packed)) eqe_rx_get; 92 | typedef struct { 93 | uint16_t flags; 94 | uint16_t len; 95 | //uint32_t client; 96 | uint64_t opaque; 97 | uint64_t item; 98 | //void* item; 99 | } __attribute__((packed)) eqe_rx_set; 100 | typedef struct { 101 | uint16_t flags; 102 | uint16_t len; 103 | uint32_t pad0; 104 | uint64_t last; 105 | //void* segment; 106 | } __attribute__((packed)) eqe_seg_full; 107 | #endif // ndef NICIF_H_ -------------------------------------------------------------------------------- /floem/include/linux_hugepage.h: -------------------------------------------------------------------------------- 1 | #ifndef LINUX_HUGEPAGE_H 2 | #define LINUX_HUGEPAGE_H 3 | 4 | //#define _LARGEFILE64_SOURCE 5 | //#include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define HUGE_PGSIZE (2 * 1024 * 1024) 17 | 18 | /** Resolve virtual address into physical address */ 19 | static bool huge_virt_to_phys(void *addr, uint64_t *phys) 20 | { 21 | int fd; 22 | bool success = true; 23 | uint64_t val; 24 | size_t page_size; 25 | off64_t off; 26 | 27 | if ((fd = open("/proc/self/pagemap", O_RDONLY)) < 0) { 28 | fprintf(stderr, "page_virt_to_phys: opening pagemap failed\n"); 29 | return false; 30 | } 31 | 32 | page_size = getpagesize(); 33 | off = (uintptr_t) addr / page_size * 8; 34 | if (lseek64(fd, off, SEEK_SET) != off) { 35 | fprintf(stderr, "page_virt_to_phys: lseek failed\n"); 36 | success = false; 37 | } 38 | 39 | if (success && read(fd, &val, sizeof(val)) != sizeof(val)) { 40 | fprintf(stderr, "page_virt_to_phys: read failed\n"); 41 | success = false; 42 | } 43 | close(fd); 44 | 45 | if (success) { 46 | /* See: https://www.kernel.org/doc/Documentation/vm/pagemap.txt 47 | * 48 | * Bits 0-54 page frame number (PFN) if present 49 | * Bits 0-4 swap type if swapped 50 | * Bits 5-54 swap offset if swapped 51 | * Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt) 52 | * Bits 56-60 zero 53 | * Bit 61 page is file-page or shared-anon 54 | * Bit 62 page swapped 55 | * Bit 63 page present 56 | */ 57 | if ((val & (1ULL << 63)) == 0 || (val & (1ULL << 62)) == 1) { 58 | fprintf(stderr, "page_virt_to_phys: read failed\n"); 59 | success = false; 60 | } else { 61 | *phys = (val & ~(-1ULL << 55)) * page_size + 62 | (uintptr_t) addr % page_size; 63 | } 64 | } 65 | 66 | return success; 67 | } 68 | 69 | /** Allocate a huge page (pinned), and return its virt/phys address and size */ 70 | static bool huge_alloc_phys(void **virt, uint64_t *phys, size_t *size) 71 | { 72 | void *map; 73 | 74 | map = mmap(NULL, HUGE_PGSIZE, PROT_READ | PROT_WRITE, 75 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_LOCKED, 76 | -1, 0); 77 | if (map == MAP_FAILED) { 78 | fprintf(stderr, "huge_alloc_phys: mmap failed (%s)\n", strerror(errno)); 79 | return false; 80 | } 81 | 82 | 83 | if (!huge_virt_to_phys(map, phys)) { 84 | fprintf(stderr, "huge_alloc_phys: finding physical address failed\n"); 85 | munmap(map, HUGE_PGSIZE); 86 | return false; 87 | } 88 | 89 | *virt = map; 90 | *size = HUGE_PGSIZE; 91 | return true; 92 | } 93 | 94 | #endif 95 | 96 | 97 | -------------------------------------------------------------------------------- /floem/programs_perpacket_state/cavium_varsize_deq.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | qid = Field(Int) 5 | keylen = Field(Int) 6 | key = Field(Pointer(Uint(8)), size='state.keylen') 7 | p = Field(Pointer(Int), shared='data_region') 8 | 9 | class main(Flow): 10 | state = PerPacket(MyState) 11 | 12 | class Save(Element): 13 | def configure(self): 14 | self.inp = Input(Int, Uint(8)) 15 | self.out = Output() 16 | 17 | def impl(self): 18 | self.run_c(r''' 19 | (int len, uint8_t data) = inp(); 20 | state.qid = 0; 21 | state.key = (uint8_t *) malloc(len); 22 | state.keylen = len; 23 | int i; 24 | for(i=0; i> main.Save() >> main.Enq() 80 | 81 | main.Scan() >> main.DisplayClean() 82 | 83 | class pop(Segment): 84 | def impl(self): 85 | main.Zero() >> main.Deq() >> main.Display() 86 | 87 | def impl(self): 88 | MemoryRegion("data_region", 4 * 100) 89 | main.push('push', process="varsize_deq") 90 | main.pop('pop', device=target.CAVIUM, cores=range(4)) # process="queue_shared_data2") 91 | 92 | master_process("varsize_deq") 93 | 94 | c = Compiler(main) 95 | c.generate_code_as_header() 96 | c.depend = ["varsize_deq"] 97 | c.compile_and_run("cavium_varsize_deq_test") 98 | -------------------------------------------------------------------------------- /apps/storm/dccp.h: -------------------------------------------------------------------------------- 1 | #ifndef DCCP_H 2 | #define DCCP_H 3 | 4 | #include "worker.h" 5 | #include 6 | 7 | #define MAX(a,b) ((a) < (b) ? (b) : (a)) 8 | 9 | /** Ethernet header */ 10 | struct eth_hdr { 11 | #if ETH_PAD_SIZE 12 | uint8_t padding[ETH_PAD_SIZE]; 13 | #endif 14 | struct eth_addr dest; 15 | struct eth_addr src; 16 | uint16_t type; 17 | } __attribute__ ((packed)); 18 | 19 | #define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) 20 | 21 | typedef struct ip_addr ip_addr_p_t; 22 | 23 | struct ip_hdr { 24 | /* version / header length */ 25 | uint8_t _v_hl; 26 | /* type of service */ 27 | uint8_t _tos; 28 | /* total length */ 29 | uint16_t _len; 30 | /* identification */ 31 | uint16_t _id; 32 | /* fragment offset field */ 33 | uint16_t _offset; 34 | /* time to live */ 35 | uint8_t _ttl; 36 | /* protocol*/ 37 | uint8_t _proto; 38 | /* checksum */ 39 | uint16_t _chksum; 40 | /* source and destination IP addresses */ 41 | ip_addr_p_t src; 42 | ip_addr_p_t dest; 43 | } __attribute__ ((packed)); 44 | 45 | #define IPH_V(hdr) ((hdr)->_v_hl >> 4) 46 | #define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) 47 | #define IPH_TOS(hdr) ((hdr)->_tos) 48 | #define IPH_LEN(hdr) ((hdr)->_len) 49 | #define IPH_ID(hdr) ((hdr)->_id) 50 | #define IPH_OFFSET(hdr) ((hdr)->_offset) 51 | #define IPH_TTL(hdr) ((hdr)->_ttl) 52 | #define IPH_PROTO(hdr) ((hdr)->_proto) 53 | #define IPH_CHKSUM(hdr) ((hdr)->_chksum) 54 | 55 | #define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl)) 56 | #define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) 57 | #define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) 58 | #define IPH_ID_SET(hdr, id) (hdr)->_id = (id) 59 | #define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) 60 | #define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (uint8_t)(ttl) 61 | #define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (uint8_t)(proto) 62 | #define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) 63 | 64 | #define IP_HLEN 20 65 | 66 | #define IP_PROTO_IP 0 67 | #define IP_PROTO_ICMP 1 68 | #define IP_PROTO_IGMP 2 69 | #define IP_PROTO_IPENCAP 4 70 | #define IP_PROTO_UDP 17 71 | #define IP_PROTO_UDPLITE 136 72 | #define IP_PROTO_TCP 6 73 | #define IP_PROTO_DCCP 33 74 | 75 | #define ETHTYPE_IP 0x0800U 76 | 77 | #define DCCP_TYPE_DATA 2 78 | #define DCCP_TYPE_ACK 3 79 | 80 | struct dccp_hdr { 81 | uint16_t src, dst; 82 | uint8_t data_offset; 83 | uint8_t ccval_cscov; 84 | uint16_t checksum; 85 | uint8_t res_type_x; 86 | uint8_t seq_high; 87 | uint16_t seq_low; 88 | } __attribute__ ((packed)); 89 | 90 | struct dccp_ack { 91 | struct dccp_hdr hdr; 92 | uint32_t ack; 93 | } __attribute__ ((packed)); 94 | 95 | struct pkt_dccp_headers { 96 | struct eth_hdr eth; 97 | struct ip_hdr ip; 98 | struct dccp_hdr dccp; 99 | } __attribute__ ((packed)); 100 | 101 | struct pkt_dccp_ack_headers { 102 | struct eth_hdr eth; 103 | struct ip_hdr ip; 104 | struct dccp_ack dccp; 105 | } __attribute__ ((packed)); 106 | 107 | struct connection { 108 | int32_t cwnd, pipe; 109 | int32_t seq; 110 | int32_t lastack; 111 | size_t acks; 112 | } __attribute__ ((aligned (64))); 113 | 114 | void init_header_template(struct pkt_dccp_headers *p); 115 | void init_congestion_control(struct connection* connections); 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /mockup/memcached/memcached.c: -------------------------------------------------------------------------------- 1 | 2 | /**********************************************************************/ 3 | /* Receiving */ 4 | 5 | 6 | ExtractKey extract_key; 7 | SteeringQueue steering_queue; 8 | APPRecv app_recv; 9 | 10 | FROM_NET >> extract_key@NIC >>2 steering_queue; // extract_key sends two tokens to 11 | app_recv@call >> steering_queue >> app_recv@return; 12 | 13 | 14 | Element ExtractKey@NIC { 15 | port in(udp_t); 16 | port out(packet_mod); 17 | 18 | .run { 19 | compute key 20 | append key to packet 21 | remove some fields 22 | } 23 | } 24 | 25 | Flow SteeringQueue { 26 | port in(packet_mod, uint32_t, signal_t); 27 | port out(packet_mod); 28 | 29 | .flow { 30 | EnqueueRx enqueue_rx; 31 | DequeueRx dequeue_rx; 32 | in(0), in(1) >> enqueue_rx@NIC | in(2) >> dequeue_rx@APP_CORE >> out(); 33 | // OR in(packet_raw), in(uint32_t) >> enqueue_rx@NIC | in(signal_t) >> dequeue_rx@APP_CORE >> out(); 34 | } 35 | } 36 | 37 | 38 | Element EnqueueRx@NIC { 39 | port in(packet_mod, uint32_t); 40 | 41 | .run { 42 | DMA: put packet in(0) to circular queue whose core id = key in(1) 43 | update tail locally 44 | } 45 | } 46 | 47 | Element DequeueRx@APP_CORE { 48 | port in(signal_t); 49 | port out(packet_mod); 50 | 51 | .run { 52 | get packet 53 | update head 54 | } 55 | } 56 | 57 | API APPRecv@APP_CORE { 58 | .call { 59 | port in(); // argument types of API function 60 | port out(); 61 | 62 | .run { out(); } 63 | } 64 | 65 | .return { 66 | port in(packet_mod); 67 | port out(packet_mod); // return type of API function 68 | 69 | .run { out(in()); } 70 | } 71 | } 72 | 73 | 74 | /**********************************************************************/ 75 | /* Receiving */ 76 | 77 | TxQueue tx_queue; 78 | Repacket re packet; 79 | APPSend app_send; 80 | 81 | app_send@call >> tx_queue >> repacket@NIC >> TO_NET; 82 | // implicit return when @APP_CORE is done. 83 | 84 | API APPSend@APP_CORE { 85 | .call { 86 | port in(packet_ret); 87 | port out(packet_ret); 88 | 89 | .run { out(in()); } 90 | } 91 | } 92 | 93 | Flow TxQueue { 94 | port in(packet_ret); 95 | port out(packet_ret); 96 | 97 | .flow { 98 | EnqueueTx enqueue_tx; 99 | DequeueTx dequeue_tx; 100 | Doorbell doorbell; 101 | in() >> enqueue_tx@APP_CORE >>2 doorbell >>2 dequeue_tx@NIC >> out(); 102 | // Does doorbell need to integrate parsing in order to reconstruct val??? 103 | } 104 | } 105 | 106 | Element EnqueueTx@APP_CORE { 107 | port in(packet_ret); 108 | port out(uint32_t, doorbell_t); 109 | .run { 110 | put packet in(0) to circular queue 111 | update tail 112 | BATCH: 113 | - multiple packets 114 | - Rx head 115 | - Tx tail 116 | write to doorbell 117 | } 118 | } 119 | 120 | Element DequeueTx@NIC { 121 | port in(uint32_t, doorbell_t); 122 | port out(packet_ret); 123 | 124 | .run { 125 | doorbell_t db = in(doorbell_t); 126 | rx_head = db.rx_head; 127 | while(tx_tail < db.tx_tail) { 128 | DMA: read packet from circular queue 129 | out(packet); 130 | } // ??? loop here!!! 131 | tx_tail = db.tx_tail; 132 | } 133 | } 134 | 135 | Element Repacket@NIC { 136 | port in(packet_ret); 137 | port out(full_packet_ret); 138 | } 139 | -------------------------------------------------------------------------------- /apps/memcached_split/settings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "iokvs.h" 6 | 7 | struct settings settings; 8 | 9 | void settings_init(char *argv[]) 10 | { 11 | settings.udpport = 11211; 12 | settings.verbose = 1; 13 | settings.segsize = 2 * 1024 * 1024; // 2048 14 | settings.segmaxnum = 512; 15 | settings.segcqsize = 8 * 1024; 16 | struct ip_addr ip = { .addr = {0x0a, 0x03, 0x00, 0x23} }; // n35 17 | settings.localip = ip; 18 | } 19 | 20 | iokvs_message template = { 21 | .ipv4 = { ._v_hl = 0x45, ._ttl = 0x40, ._proto = 0x11}, 22 | #ifndef CAVIUM 23 | .ether = { .type = 0x0008 }, 24 | .mcudp = { .n_data = 0x0100 } 25 | #else 26 | .ether = { .type = 0x0800 }, 27 | .mcudp = { .n_data = 1 } 28 | #endif 29 | }; // CAVIUM 30 | 31 | iokvs_message* iokvs_template() { 32 | return &template; 33 | } 34 | 35 | iokvs_message* get_packet(int size) { 36 | iokvs_message *m = (iokvs_message *) malloc(size); 37 | m->ether.type = htons(ETHERTYPE_IPv4); 38 | m->ipv4._proto = 17; 39 | m->ipv4.dest = settings.localip; 40 | m->udp.dest_port = htons(11211); 41 | return m; 42 | } 43 | 44 | iokvs_message* random_get_request(uint8_t v, uint8_t id) { 45 | uint16_t keylen = (v % 4) + 1; 46 | uint16_t extlen = 4; 47 | 48 | printf("get: v = %d, id = %d\n", v, id); 49 | 50 | iokvs_message *m = get_packet(sizeof(iokvs_message) + extlen + keylen); 51 | m->mcr.request.opcode = PROTOCOL_BINARY_CMD_GET; 52 | m->mcr.request.magic = id; // PROTOCOL_BINARY_REQ 53 | m->mcr.request.opaque = id; // PROTOCOL_BINARY_REQ 54 | m->mcr.request.keylen = keylen; 55 | m->mcr.request.datatype = PROTOCOL_BINARY_RAW_BYTES; 56 | m->mcr.request.status = 0; 57 | 58 | m->mcr.request.extlen = extlen; 59 | m->mcr.request.bodylen = extlen + keylen; 60 | *((uint32_t *)m->payload) = 0; 61 | 62 | uint8_t* key = m->payload + extlen; 63 | uint16_t i; 64 | for(i=0; imcr.request.opcode = PROTOCOL_BINARY_CMD_SET; 79 | m->mcr.request.magic = id; 80 | m->mcr.request.opaque = id; 81 | m->mcr.request.keylen = keylen; 82 | m->mcr.request.datatype = PROTOCOL_BINARY_RAW_BYTES; 83 | m->mcr.request.status = 0; 84 | 85 | m->mcr.request.extlen = extlen; 86 | m->mcr.request.bodylen = extlen + keylen + vallen; 87 | *((uint32_t *)m->payload) = 0; 88 | 89 | uint8_t* key = m->payload + extlen; 90 | uint16_t i; 91 | for(i=0; ipayload + extlen + keylen; 95 | for(i=0; iether.src = src; 17 | m->ether.dest = dest; 18 | 19 | m->ipv4.src = src_ip; 20 | m->ipv4.dest = dest_ip; 21 | 22 | static __thread uint16_t sport = 0; 23 | m->udp.src_port = (++sport == 0 ? ++sport : sport); 24 | m->udp.dest_port = m->udp.src_port; 25 | 26 | m->ether.type = htons(ETHERTYPE_IPv4); 27 | m->ipv4._proto = 17; 28 | m->ipv4._len = htons(size - offsetof(iokvs_message, ipv4)); 29 | m->ipv4._ttl = 64; 30 | m->ipv4._chksum = 0; 31 | //m->ipv4._chksum = rte_ipv4_cksum(&m->ipv4); // TODO 32 | 33 | m->udp.len = htons(size - offsetof(iokvs_message, udp)); 34 | m->udp.cksum = 0; 35 | //printf("sizeof(iokvs) = %d, size = %ld\n", sizeof(iokvs_message), size); 36 | 37 | output { out(size, pkt, buff); } 38 | ''') 39 | 40 | class Stat(State): 41 | count = Field(SizeT) 42 | lasttime = Field(SizeT) 43 | 44 | def init(self): 45 | self.count = 0 46 | self.lasttime = 0 47 | 48 | class Reply(Element): 49 | this = Persistent(Stat) 50 | 51 | def configure(self): 52 | self.inp = Input(SizeT, "void*", "void*") 53 | self.out = Output("void*", "void*") 54 | 55 | def states(self): 56 | self.this = Stat() 57 | 58 | def impl(self): 59 | self.run_c(r''' 60 | (size_t size, void* pkt, void* buff) = inp(); 61 | iokvs_message* m = (iokvs_message*) pkt; 62 | 63 | 64 | if(m->mcr.request.magic == PROTOCOL_BINARY_RES) { 65 | //printf("pkt\n"); 66 | uint64_t mycount = __sync_fetch_and_add64(&this->count, 1); 67 | if(mycount == 5000000) { 68 | struct timeval now; 69 | gettimeofday(&now, NULL); 70 | size_t thistime = now.tv_sec * 1000000 + now.tv_usec; 71 | printf("%zu pkts/s\n", (mycount * 1000000)/(thistime - this->lasttime)); 72 | this->lasttime = thistime; 73 | this->count = 0; 74 | } 75 | } 76 | 77 | output { out(pkt, buff); } 78 | ''') 79 | 80 | 81 | class gen(Segment): 82 | def impl(self): 83 | net_alloc = net.NetAlloc() 84 | to_net = net.ToNet(configure=["net_alloc"]) 85 | 86 | library.Constant(configure=[SizeT,64]) >> net_alloc 87 | net_alloc.oom >> library.Drop() 88 | net_alloc.out >> Request() >> to_net 89 | 90 | class recv(Segment): 91 | def impl(self): 92 | from_net = net.FromNet() 93 | free = net.FromNetFree() 94 | 95 | from_net.nothing >> library.Drop() 96 | 97 | from_net >> Reply() >> free 98 | 99 | n = 5 100 | gen('gen', process='dpdk', cores=range(n)) 101 | recv('recv', process='dpdk', cores=range(n)) 102 | c = Compiler() 103 | c.include = r''' 104 | #include "protocol_binary.h" 105 | 106 | struct eth_addr src = { .addr = "\x3c\xfd\xfe\xaa\xd1\xe1" }; // guanaco 107 | struct ip_addr src_ip = { .addr = "\x0a\x64\x14\x08" }; 108 | 109 | struct eth_addr dest = { .addr = "\x02\x78\x1f\x5a\x5b\x01" }; // jaguar 110 | struct ip_addr dest_ip = { .addr = "\x0a\x64\x14\x0b", }; 111 | ''' 112 | c.testing = 'while (1) pause();' 113 | c.generate_code_and_compile() 114 | -------------------------------------------------------------------------------- /floem/programs_cavium/packet_build.h: -------------------------------------------------------------------------------- 1 | #ifndef PACKET_BUILD_H 2 | #define PACKET_BUILD_H 3 | 4 | static uint16_t 5 | in_chksum(uint16_t *addr, int len) 6 | { 7 | int sum = 0; 8 | uint16_t answer = 0; 9 | uint16_t *w = addr; 10 | int nleft = len; 11 | 12 | /* 13 | * Our algorithm is simple, using a 32 bit accumulator (sum), we add 14 | * sequential 16 bit words to it, and at the end, fold back all the 15 | * carry bits from the top 16 bits into the lower 16 bits. 16 | */ 17 | while (nleft > 1) { 18 | sum += *w++; 19 | nleft -= 2; 20 | } 21 | 22 | /*! mop up an odd byte, if necessary */ 23 | if (nleft == 1) { 24 | *(uint8_t *)(&answer) = *(uint8_t *)w; 25 | sum += answer; 26 | } 27 | 28 | /*! add back carry outs from top 16 bits to low 16 bits */ 29 | sum = (sum >> 16) + (sum & 0xffff); /*! add hi 16 to low 16 */ 30 | sum += (sum >> 16); /*! add carry */ 31 | answer = ~sum; /*! truncate to 16 bits */ 32 | return answer; 33 | } 34 | 35 | struct _ethhdr { 36 | uint8_t dest[6]; 37 | uint8_t src[6]; 38 | uint16_t type; 39 | } __attribute__((packed)); 40 | 41 | static void 42 | rebuild_ether_header(uint8_t *pkt_ptr) 43 | { 44 | struct _ethhdr my_ethhdr = { 45 | {0x00, 0x02, 0xc9, 0x4e, 0xe9, 0x38}, // n72 eth4 46 | {0x00, 0x0f, 0xb7, 0x30, 0x3f, 0x58}, // n35 eth2 47 | 0x0800 48 | }; 49 | memcpy(pkt_ptr, &my_ethhdr, sizeof(struct _ethhdr)); 50 | } 51 | 52 | struct _iphdr{ 53 | uint8_t version:4, 54 | ihl:4; 55 | uint8_t tos; 56 | uint16_t tot_len; 57 | uint16_t id; 58 | uint16_t flag_off; 59 | uint8_t ttl; 60 | uint8_t protocol; 61 | uint16_t cksum; 62 | uint8_t saddr[4]; 63 | uint8_t daddr[4]; 64 | } __attribute__((packed)); 65 | 66 | static void 67 | rebuild_ip_header(uint8_t *pkt_ptr) 68 | { 69 | struct _iphdr my_iphdr = { 70 | .version = 0x4, 71 | .ihl = 0x5, 72 | 0x00, 73 | 0x002c, 74 | 0x0000, 75 | 0x4000, 76 | 0x40, 77 | 0x11, 78 | 0x00, 79 | {0x0a, 0x03, 0x00, 0x23}, // n35 80 | {0x0a, 0x03, 0x00, 0x48} // n72 81 | }; 82 | memcpy(pkt_ptr + 14, &my_iphdr, sizeof(struct _iphdr)); 83 | } 84 | 85 | struct _udphdr{ 86 | uint16_t sport; 87 | uint16_t dport; 88 | uint16_t len; 89 | uint16_t cksum; 90 | } __attribute__((packed)); 91 | 92 | static void 93 | rebuild_udp_header(uint8_t *pkt_ptr) 94 | { 95 | struct _udphdr my_udphdr = { 96 | 0x1234, 97 | 0x26fb, 98 | 0x0018, // udp packet size is 24, which is also related with ip header 99 | 0x0000 100 | }; 101 | 102 | memcpy(pkt_ptr + 34, &my_udphdr, sizeof(struct _udphdr)); 103 | } 104 | 105 | static void 106 | rebuild_payload(uint8_t *pkt_ptr) 107 | { 108 | // assume the payload is 16 bytes 109 | uint8_t *payload; 110 | payload = (uint8_t *)malloc(sizeof(uint8_t) * 16); 111 | 112 | memset(payload, 0x61, 16); 113 | memcpy(pkt_ptr + 42, payload, 16); 114 | free(payload); 115 | } 116 | 117 | static void 118 | recalculate_ip_chksum(uint8_t *pkt_ptr) 119 | { 120 | *(uint16_t*)(pkt_ptr + 24) = 0x0000; 121 | *(uint16_t*)(pkt_ptr + 24) = in_chksum((uint16_t *)(pkt_ptr + 14), 20); 122 | } 123 | 124 | static void 125 | recalculate_udp_chksum(uint8_t *pkt_ptr) 126 | { 127 | *(uint16_t*)(pkt_ptr + 40) = 0x0000; 128 | } 129 | 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /apps/benchmarks_param_update/request.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class Request(Element): 4 | def configure(self): 5 | self.inp = Input(SizeT, "void*", "void*") 6 | self.out = Output(SizeT, "void*", "void*") 7 | 8 | def impl(self): 9 | self.run_c(r''' 10 | (size_t size, void* pkt, void* buff) = inp(); 11 | param_message* m = (param_message*) pkt; 12 | 13 | m->ether.src = src; 14 | m->ether.dest = dest; 15 | 16 | m->ipv4.src = src_ip; 17 | m->ipv4.dest = dest_ip; 18 | 19 | static __thread uint16_t sport = 0; 20 | m->udp.src_port = (++sport == 0 ? ++sport : sport); 21 | m->udp.dest_port = m->udp.src_port; 22 | 23 | m->ether.type = htons(ETHERTYPE_IPv4); 24 | m->ipv4._proto = 17; 25 | m->ipv4._len = htons(size - offsetof(param_message, ipv4)); 26 | m->ipv4._ttl = 64; 27 | m->ipv4._chksum = 0; 28 | //m->ipv4._chksum = rte_ipv4_cksum(&m->ipv4); // TODO 29 | 30 | m->udp.len = htons(size - offsetof(param_message, udp)); 31 | m->udp.cksum = 0; 32 | 33 | m->pool = rand() % 8; 34 | m->param = (double)rand() / (double)RAND_MAX; 35 | 36 | output { out(size, pkt, buff); } 37 | ''') 38 | 39 | class Stat(State): 40 | count = Field(SizeT) 41 | lasttime = Field(SizeT) 42 | 43 | def init(self): 44 | self.count = 0 45 | self.lasttime = 0 46 | 47 | class Recieve(Element): 48 | this = Persistent(Stat) 49 | 50 | def configure(self): 51 | self.inp = Input(SizeT, "void*", "void*") 52 | self.out = Output("void*", "void*") 53 | 54 | def states(self): 55 | self.this = Stat() 56 | 57 | def impl(self): 58 | self.run_c(r''' 59 | (size_t size, void* pkt, void* buff) = inp(); 60 | param_message* m = (param_message*) pkt; 61 | 62 | 63 | if(m->status == 1) { 64 | //printf("pkt\n"); 65 | uint64_t mycount = __sync_fetch_and_add64(&this->count, 1); 66 | if(mycount == 100000) { 67 | struct timeval now; 68 | gettimeofday(&now, NULL); 69 | size_t thistime = now.tv_sec * 1000000 + now.tv_usec; 70 | printf("%zu pkts/s\n", (mycount * 1000000)/(thistime - this->lasttime)); 71 | this->lasttime = thistime; 72 | this->count = 0; 73 | } 74 | } 75 | 76 | output { out(pkt, buff); } 77 | ''') 78 | 79 | 80 | class gen(Segment): 81 | def impl(self): 82 | net_alloc = net.NetAlloc() 83 | to_net = net.ToNet(configure=["net_alloc"]) 84 | 85 | library.Constant(configure=[SizeT,'sizeof(param_message)']) >> net_alloc 86 | net_alloc.oom >> library.Drop() 87 | net_alloc.out >> Request() >> to_net 88 | 89 | class recv(Segment): 90 | def impl(self): 91 | from_net = net.FromNet() 92 | free = net.FromNetFree() 93 | 94 | from_net.nothing >> library.Drop() 95 | 96 | from_net >> Recieve() >> free 97 | 98 | n = 5 99 | gen('gen', process='dpdk', cores=range(n)) 100 | recv('recv', process='dpdk', cores=range(n)) 101 | c = Compiler() 102 | c.include = r''' 103 | #include "protocol_binary.h" 104 | 105 | struct eth_addr src = { .addr = "\x68\x05\xca\x33\x13\x40" }; // n30 106 | //struct eth_addr dest = { .addr = "\x68\x05\xca\x33\x11\x3c" }; // n33 107 | struct eth_addr dest = { .addr = "\x00\x0f\xb7\x30\x3f\x58" }; // n35 108 | 109 | struct ip_addr src_ip = { .addr = "\x0a\x03\x00\x1e" }; 110 | //struct ip_addr dest_ip = { .addr = "\x0a\x03\x00\x21" }; // n33 111 | struct ip_addr dest_ip = { .addr = "\x0a\x03\x00\x23" }; // n35 112 | ''' 113 | c.testing = 'while (1) pause();' 114 | c.generate_code_and_compile() 115 | -------------------------------------------------------------------------------- /apps/benchmarks_network_func/count-min-sketch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Count-min Sketch implementation 3 | */ 4 | 5 | #include "count-min-sketch.h" 6 | #include "pkt-utils.h" 7 | 8 | #ifdef CAVIUM 9 | #include "cvmx.h" 10 | #include "cvmx-atomic.h" 11 | #include "floem-util.h" 12 | #else 13 | #include 14 | #endif 15 | 16 | /* 17 | * Note that we support atomic read/write on the count-min sketch 18 | * table (cm_sketch). This requires all the table cell to be 64-bits 19 | * aligned. Therefore, we start at an aligned address and each cell 20 | * address is also an aligned address. 21 | */ 22 | #ifdef CAVIUM 23 | CVMX_SHARED uint64_t *cm_sketch; 24 | 25 | void 26 | cm_sketch_init() 27 | { 28 | cm_sketch = (uint64_t *)shared_mm_memalign(sizeof(uint64_t) * 29 | CM_ROW_NUM * CM_COL_NUM, 8); 30 | memset(cm_sketch, 0x00, sizeof(uint64_t) * CM_ROW_NUM * CM_COL_NUM); 31 | } 32 | #else 33 | uint64_t *cm_sketch; 34 | 35 | void 36 | cm_sketch_init() 37 | { 38 | cm_sketch = (uint64_t *) malloc(sizeof(uint64_t) * 39 | CM_ROW_NUM * CM_COL_NUM); 40 | memset(cm_sketch, 0x00, sizeof(uint64_t) * CM_ROW_NUM * CM_COL_NUM); 41 | } 42 | #endif 43 | 44 | /* 45 | * Experienced method online. The result is nearly good as AES. 46 | */ 47 | uint32_t 48 | cm_hash1 (uint32_t x) 49 | { 50 | x = ((x >> 16) ^ x) * 0x45d9f3b; 51 | x = ((x >> 16) ^ x) * 0x45d9f3b; 52 | x = (x >> 16) ^ x; 53 | return x; 54 | } 55 | 56 | /* 57 | * Robert Jenkin's hashing method 58 | */ 59 | uint32_t 60 | cm_hash2 (uint32_t a) 61 | { 62 | a = (a+0x7ed55d16) + (a<<12); 63 | a = (a^0xc761c23c) ^ (a>>19); 64 | a = (a+0x165667b1) + (a<<5); 65 | a = (a+0xd3a2646c) ^ (a<<9); 66 | a = (a+0xfd7046c5) + (a<<3); 67 | a = (a^0xb55a4f09) ^ (a>>16); 68 | return a; 69 | } 70 | 71 | /* 72 | * Thomas Wang's hashing method 73 | */ 74 | uint32_t 75 | cm_hash3(uint32_t a) 76 | { 77 | a = (a ^ 61) ^ (a >> 16); 78 | a = a + (a << 3); 79 | a = a ^ (a >> 4); 80 | a = a * 0x27d4eb2d; 81 | a = a ^ (a >> 15); 82 | return a; 83 | } 84 | 85 | /* 86 | * Knuth's multiplicative hashing method 87 | */ 88 | uint32_t 89 | cm_hash4(uint32_t v) 90 | { 91 | return v * UINT32_C(2654435761); 92 | } 93 | 94 | uint32_t 95 | flow_to_hash(int row, 96 | uint32_t flow_id) 97 | { 98 | uint32_t ret; 99 | 100 | switch (row) { 101 | case 0: ret = cm_hash1(flow_id); break; 102 | case 1: ret = cm_hash2(flow_id); break; 103 | case 2: ret = cm_hash3(flow_id); break; 104 | case 3: ret = cm_hash4(flow_id); break; 105 | default: ret = flow_id; break; 106 | } 107 | 108 | return ret; 109 | } 110 | 111 | uint64_t 112 | cm_sketch_read(int row, 113 | uint32_t flow_id) 114 | { 115 | uint32_t bucket_id = flow_to_hash (row, flow_id) % CM_COL_NUM; 116 | uint64_t ret_val = cm_sketch[row * CM_ROW_NUM + bucket_id]; 117 | 118 | return ret_val; 119 | } 120 | 121 | #define MAX(a,b) (((a)>(b))?(a):(b)) 122 | 123 | void 124 | cm_sketch_update(int row, 125 | uint32_t flow_id, 126 | uint64_t new_val) 127 | { 128 | uint32_t bucket_id = flow_to_hash (row, flow_id) % CM_COL_NUM; 129 | uint64_t *write_addr = cm_sketch + row * CM_ROW_NUM + bucket_id; 130 | uint64_t old_val = *write_addr; 131 | 132 | while (!__sync_bool_compare_and_swap64(write_addr, old_val, new_val)) { 133 | old_val = *write_addr; 134 | new_val = MAX(old_val, new_val); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /floem/include/shm.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_H 2 | #define SHM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* create and map a shared memory region, returns address */ 17 | static void *util_create_shmsiszed(const char *name, size_t size) 18 | { 19 | int fd; 20 | void *p; 21 | 22 | if ((fd = shm_open(name, O_CREAT | O_RDWR, 0666)) == -1) { 23 | perror("shm_open failed"); 24 | goto error_out; 25 | } 26 | if (ftruncate(fd, size) != 0) { 27 | perror("ftruncate failed"); 28 | goto error_remove; 29 | } 30 | 31 | if ((p = mmap(NULL, size, PROT_READ | PROT_WRITE, 32 | MAP_SHARED | MAP_POPULATE, fd, 0)) == (void *) -1) 33 | { 34 | perror("mmap failed"); 35 | goto error_remove; 36 | } 37 | 38 | memset(p, 0, size); 39 | 40 | close(fd); 41 | return p; 42 | 43 | error_remove: 44 | close(fd); 45 | shm_unlink(name); 46 | error_out: 47 | return NULL; 48 | } 49 | 50 | /* map a shared memory region, returns address */ 51 | static void *util_map_shm(const char *name, size_t size) 52 | { 53 | int fd; 54 | void *p; 55 | 56 | if ((fd = shm_open(name, O_RDWR, 0666)) == -1) { 57 | perror("shm_open failed"); 58 | return NULL; 59 | } 60 | 61 | p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, 62 | fd, 0); 63 | close(fd); 64 | if (p == (void *) -1) { 65 | perror("mmap failed"); 66 | return NULL; 67 | } 68 | 69 | return p; 70 | } 71 | 72 | static void* util_map_dma() { 73 | void* virt; 74 | uint64_t phys; 75 | size_t size; 76 | bool s; 77 | s = huge_alloc_phys(&virt, &phys, &size); 78 | if(!s) exit(1); 79 | printf("physical address = %p, size = %ld\n", (void*) phys, size); 80 | printf("logical address = %p\n", virt); 81 | return virt; 82 | } 83 | 84 | /* 85 | #define UIO_DEV "/dev/uio0" 86 | #define UIO_ADDR "/sys/class/uio/uio0/maps/map0/addr" 87 | #define UIO_SIZE "/sys/class/uio/uio0/maps/map0/size" 88 | 89 | static char uio_addr_buf[16], uio_size_buf[16]; 90 | static int uio_fd, addr_fd, size_fd; 91 | 92 | static void* util_map_dma() 93 | { 94 | int i; 95 | int uio_size; 96 | void* uio_addr, *access_address; 97 | 98 | uio_fd = open(UIO_DEV, O_RDWR); 99 | addr_fd = open(UIO_ADDR, O_RDONLY); 100 | size_fd = open(UIO_SIZE, O_RDONLY); 101 | if( addr_fd < 0 || size_fd < 0 || uio_fd < 0) { 102 | fprintf(stderr, "mmap: %s\n", strerror(errno)); 103 | exit(-1); 104 | } 105 | read(addr_fd, uio_addr_buf, sizeof(uio_addr_buf)); 106 | read(size_fd, uio_size_buf, sizeof(uio_size_buf)); 107 | uio_addr = (void*)strtoul(uio_addr_buf, NULL, 0); 108 | uio_size = (int)strtol(uio_size_buf, NULL, 0); 109 | 110 | access_address = mmap(NULL, uio_size, PROT_READ | PROT_WRITE, 111 | MAP_SHARED, uio_fd, 0); 112 | if ( access_address == (void*) -1) { 113 | fprintf(stderr, "mmap: %s\n", strerror(errno)); 114 | exit(-1); 115 | } 116 | printf("The device address %p (lenth %d)\n" 117 | "can be accessed over\n" 118 | "logical address %p\n", uio_addr, uio_size, access_address); 119 | 120 | return access_address; 121 | } 122 | 123 | static void util_unmap_dma() { 124 | close(uio_fd); 125 | close(addr_fd); 126 | close(size_fd); 127 | } 128 | */ 129 | 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /floem/programs/smart_queue_entry.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | a = Field(Int) 5 | a0 = Field(Int) 6 | b0 = Field(Int) 7 | qid = Field(Int) 8 | 9 | class main(Flow): 10 | state = PerPacket(MyState) 11 | 12 | class Save(Element): 13 | def configure(self): 14 | self.inp = Input(Int) 15 | self.out = Output() 16 | 17 | def impl(self): 18 | self.run_c(r''' 19 | state.a = inp(); 20 | state.qid = 0; 21 | output { out(); } 22 | ''') 23 | 24 | class Classify(Element): 25 | def configure(self): 26 | self.inp = Input() 27 | self.out = [Output(), Output()] 28 | 29 | def impl(self): 30 | self.run_c(r''' 31 | output switch { 32 | case (state.a % 2) == 0: out0(); 33 | else: out1(); } 34 | ''') 35 | 36 | class A0(Element): 37 | def configure(self): self.inp = Input(); self.out = Output() 38 | def impl(self): self.run_c(r'''state.a0 = state.a + 100; output { out(); }''') 39 | 40 | class B0(Element): 41 | def configure(self): self.inp = Input(); self.out = Output() 42 | def impl(self): self.run_c(r'''state.b0 = state.a * 2; output { out(); }''') 43 | 44 | class A1(Element): 45 | def configure(self): self.inp = Input() 46 | def impl(self): self.run_c(r'''printf("a1 %d\n", state.a0);''') 47 | 48 | class B1(Element): 49 | def configure(self): self.inp = Input() 50 | def impl(self): self.run_c(r'''printf("b1 %d\n", state.b0);''') 51 | 52 | class PrintClean(Element): 53 | def configure(self, letter): self.inp = Input(); self.letter = letter 54 | def impl(self): self.run_c(r'''printf("clean %s!\n");''' % self.letter) 55 | 56 | class Display(Element): 57 | def configure(self): 58 | self.inp = Input() 59 | 60 | def impl(self): 61 | self.run_c(r'''printf("done %d\n", state.a);''') 62 | 63 | Enq, Deq, Clean = queue_smart.smart_queue("queue", entry_size=32, size=3, insts=2, channels=2, clean=True, 64 | enq_output=True) 65 | 66 | class run1(CallableSegment): 67 | def configure(self): 68 | self.inp = Input(Int) 69 | 70 | def impl(self): 71 | classify = main.Classify() 72 | enq = main.Enq() 73 | 74 | self.inp >> main.Save() >> classify 75 | classify.out[0] >> main.A0() >> enq.inp[0] 76 | classify.out[1] >> main.B0() >> enq.inp[1] 77 | enq.done >> main.Display() 78 | 79 | scan = main.Clean() 80 | scan.out[0] >> main.PrintClean(configure=['a']) 81 | scan.out[1] >> main.PrintClean(configure=['b']) 82 | 83 | class run2(CallableSegment): 84 | def configure(self): 85 | self.inp = Input(Int) 86 | 87 | def impl(self): 88 | deq = main.Deq() 89 | 90 | self.inp >> deq 91 | deq.out[0] >> main.A1() 92 | deq.out[1] >> main.B1() 93 | 94 | def impl(self): 95 | main.run1('run1') 96 | main.run2('run2') 97 | 98 | 99 | c = Compiler(main) 100 | c.testing = "run1(123); run1(42); run2(0); run2(0); run1(1); run1(2);" 101 | #c.generate_code_and_run(['done', 123, 'done', 42, 'b1', 246, 'a1', 142, 'clean', 'b!', 'clean', 'a!', 'done', '1', 'done', '2']) 102 | c.generate_code_and_run(['done', 123, 'done', 42, 'b1', 246, 'a1', 142, 'done', '1', 'clean', 'b!', 'clean', 'a!', 'done', '2']) -------------------------------------------------------------------------------- /apps/benchmarks_simple/inqueue.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_nic_cores = 10 4 | n_queues = 7 5 | 6 | class MyState(State): 7 | pkt = Field('void*') 8 | pkt_buff = Field('void*') 9 | key = Field('void*', size=64) 10 | qid = Field(Int) 11 | 12 | 13 | class main(Flow): 14 | state = PerPacket(MyState) 15 | 16 | def impl(self): 17 | # Queue 18 | RxEnq, RxDeq, RxScan = queue_smart.smart_queue("rx_queue", entry_size=96, size=1024, insts=n_queues, 19 | channels=1, enq_blocking=True, enq_atomic=True, enq_output=True) 20 | rx_enq = RxEnq() 21 | rx_deq = RxDeq() 22 | 23 | class MakeKey(Element): 24 | def configure(self): 25 | self.inp = Input(SizeT, "void *", "void *") 26 | self.out = Output() 27 | 28 | def impl(self): 29 | self.run_c(r''' 30 | (size_t size, void* pkt, void* buff) = inp(); 31 | state.pkt = pkt; 32 | state.pkt_buff = buff; 33 | iokvs_message* m = (iokvs_message*) pkt; 34 | 35 | state.key = m; 36 | static int qid = 0; 37 | state.qid= qid; 38 | qid = (qid+1) %s %d; 39 | 40 | output { out(); } 41 | ''' % ('%', n_queues)) 42 | 43 | class GetPktBuff(Element): 44 | def configure(self): 45 | self.inp = Input() 46 | self.out = Output("void*", "void*") 47 | 48 | def impl(self): 49 | self.run_c(r''' 50 | void* pkt = state.pkt; 51 | void* pkt_buff = state.pkt_buff; 52 | output { out(pkt, pkt_buff); } 53 | ''') 54 | 55 | class nic_rx(Segment): 56 | def impl(self): 57 | from_net = net.FromNet() 58 | from_net_free = net.FromNetFree() 59 | 60 | from_net >> MakeKey() >> rx_enq.inp[0] 61 | rx_enq.done >> GetPktBuff() >> from_net_free 62 | from_net.nothing >> library.Drop() 63 | 64 | 65 | ############################ CPU ############################# 66 | class Scheduler(Element): 67 | def configure(self): 68 | self.inp = Input(Int) 69 | self.out = Output(Int) 70 | 71 | def impl(self): 72 | self.run_c(r''' 73 | (int core_id) = inp(); 74 | output { out(core_id); } 75 | ''') 76 | 77 | class Display(Element): 78 | def configure(self): 79 | self.inp = Input() 80 | 81 | def impl(self): 82 | self.run_c(r''' 83 | void *key = state.key; 84 | 85 | static __thread size_t count = 0; 86 | static __thread uint64_t lasttime = 0; 87 | count++; 88 | if(count == 1000000) { 89 | struct timeval now; 90 | gettimeofday(&now, NULL); 91 | 92 | uint64_t thistime = now.tv_sec*1000000 + now.tv_usec; 93 | printf("%zu pkts/s %f Gbits/s\n", (count * 1000000)/(thistime - lasttime), (count * 64 * 8.0)/(thistime - lasttime)/1000); 94 | lasttime = thistime; 95 | count = 0; 96 | } 97 | ''') 98 | 99 | class run(Segment): 100 | def impl(self): 101 | self.core_id >> rx_deq 102 | rx_deq.out[0] >> Display() 103 | 104 | nic_rx('nic_rx', device=target.CAVIUM, cores=range(n_nic_cores)) 105 | run('run', process='app', cores=range(n_queues)) 106 | 107 | 108 | c = Compiler(main) 109 | c.include = r''' 110 | #include "protocol_binary.h" 111 | ''' 112 | c.generate_code_as_header() 113 | c.depend = ['app'] 114 | c.compile_and_run("test_queue") 115 | -------------------------------------------------------------------------------- /apps/memcached_cpu_only/loc/cloc_nic_offload.py: -------------------------------------------------------------------------------- 1 | class QID(Element): 2 | def configure(self): 3 | self.inp = Input() 4 | self.out = Output() 5 | 6 | def impl(self): 7 | self.run_c(r''' 8 | state->qid = state->hash %s %d; 9 | output { out(); } 10 | ''' % ('%', n_cores)) 11 | 12 | 13 | # Queue 14 | 15 | 16 | RxEnq, RxDeq, RxScan = queue_smart.smart_queue("rx_queue", entry_size=192, size=256, insts=n_cores, 17 | channels=2, enq_blocking=True, enq_atomic=True, enq_output=False) 18 | rx_enq = RxEnq() 19 | rx_deq = RxDeq() 20 | 21 | TxEnq, TxDeq, TxScan = queue_smart.smart_queue("tx_queue", entry_size=192, size=256, insts=n_cores, 22 | channels=2, checksum=False, enq_blocking=True, deq_atomic=True, 23 | enq_output=True) 24 | tx_enq = TxEnq() 25 | tx_deq = TxDeq() 26 | 27 | 28 | ######################## CPU ####################### 29 | class process_one_pkt(Pipeline): 30 | def impl(self): 31 | self.core_id >> main.CleanLog() >> rx_deq 32 | rx_deq.out[0] >> main.HashGet() >> tx_enq.inp[0] 33 | rx_deq.out[1] >> main.GetItemSpec() >> main.HashPut() >> tx_enq.inp[1] 34 | tx_enq.done >> main.Unref() >> library.Drop() 35 | 36 | 37 | ######################## NIC ####################### 38 | class nic_rx(Pipeline): 39 | def impl(self): 40 | from_net = net.FromNet('from_net') 41 | from_net_free = net.FromNetFree('from_net_free') 42 | to_net = net.ToNet('to_net', configure=['from_net']) 43 | classifier = main.Classifer() 44 | check_packet = main.CheckPacket() 45 | hton = net.HTON(configure=['iokvs_message']) 46 | arp = main.HandleArp() 47 | drop = main.Drop() 48 | 49 | # from_net 50 | from_net >> hton >> check_packet >> main.SaveState() >> main.GetKey() >> main.JenkinsHash() >> classifier 51 | from_net.nothing >> drop 52 | 53 | classifier.out_get >> main.Key2State() >> CacheGetStart() >> main.QID() >> rx_enq.inp[0] 54 | classifier.out_set >> main.KV2State() >> CacheSetStart() >> main.QID() >> rx_enq.inp[1] 55 | 56 | # exception 57 | check_packet.slowpath >> arp >> to_net 58 | arp.drop >> from_net_free 59 | check_packet.drop >> from_net_free 60 | 61 | 62 | class nic_tx(Pipeline): 63 | def impl(self): 64 | prepare_header = main.PrepareHeader() 65 | get_result = main.GetResult() 66 | get_response = main.PrepareGetResp() 67 | get_response_null = main.PrepareGetNullResp() 68 | set_result = main.SetResult() 69 | set_response = main.PrepareSetResp(configure=['PROTOCOL_BINARY_RESPONSE_SUCCESS']) 70 | set_reponse_fail = main.PrepareSetResp(configure=['PROTOCOL_BINARY_RESPONSE_ENOMEM']) 71 | hton = net.HTON(configure=['iokvs_message']) 72 | to_net = net.ToNet('to_net', configure=['from_net']) 73 | 74 | self.core_id >> main.TxScheduler() >> tx_deq 75 | 76 | # get 77 | tx_deq.out[0] >> CacheGetEnd() >> get_result 78 | get_result.hit >> main.SizeGetResp() >> main.SizePktBuff() >> get_response >> prepare_header 79 | get_result.miss >> main.SizeGetNullResp() >> main.SizePktBuff() >> get_response_null >> prepare_header 80 | 81 | # set 82 | tx_deq.out[1] >> CacheSetEnd() >> set_result 83 | set_result.success >> main.SizeSetResp() >> main.SizePktBuff() >> set_response >> prepare_header 84 | set_result.fail >> main.SizeSetResp() >> main.SizePktBuff() >> set_reponse_fail >> prepare_header 85 | 86 | # send 87 | prepare_header >> hton >> to_net 88 | 89 | nic_rx('nic_rx', device=target.CAVIUM, cores=[nic_threads + x for x in range(nic_threads)]) 90 | nic_tx('nic_tx', device=target.CAVIUM, cores=range(nic_threads)) -------------------------------------------------------------------------------- /floem/programs/queue_default.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | n_cores = 4 4 | 5 | class Entry(State): 6 | flag = Field(Uint(8)) 7 | task = Field(Uint(8)) 8 | len = Field(Uint(16)) 9 | checksum = Field(Uint(8)) 10 | pad = Field(Uint(8)) 11 | val = Field(Int) 12 | layout = [flag, task, len, checksum, pad, val] 13 | 14 | EnqAlloc, EnqSubmit, DeqGet, DeqRelease, clean = \ 15 | queue.queue_default("queue", 32, 3, n_cores, enq_atomic=True, deq_atomic=True, clean=True) 16 | 17 | class ComputeQID(Element): 18 | def configure(self): 19 | self.inp = Input(Int, Int) # val, qid 20 | self.out_size_qid = Output(Int, Int) # size, qid 21 | self.out_val = Output(Int) 22 | 23 | def impl(self): 24 | self.run_c(r''' 25 | (int x, int qid) = inp(); 26 | output { out_val(x); out_size_qid(4, qid); } 27 | ''') 28 | 29 | class FillEntry(Element): 30 | def configure(self): 31 | self.in_entry = Input(queue.q_buffer) 32 | self.in_val = Input(Int) 33 | self.out = Output(queue.q_buffer) 34 | 35 | def impl(self): 36 | self.run_c(r''' 37 | (q_buffer buff) = in_entry(); 38 | Entry* e = (Entry*) buff.entry; 39 | int v = in_val(); 40 | if(e != NULL) { 41 | e->val = v; 42 | printf("%d enq\n", v); 43 | } 44 | output switch { case (e != NULL): out(buff); } 45 | ''') 46 | 47 | 48 | class CleanPrint(Element): 49 | def configure(self): 50 | self.inp = Input(queue.q_buffer) 51 | 52 | def impl(self): 53 | self.run_c(r''' 54 | (q_buffer buff) = inp(); 55 | Entry* e = (Entry*) buff.entry; 56 | if(e->val) printf("%d clean\n", e->val); 57 | ''') 58 | 59 | 60 | class rx_write(CallableSegment): 61 | def configure(self): 62 | self.inp = Input(Int, Int) # val, qid 63 | 64 | def impl(self): 65 | compute_qid = ComputeQID() 66 | fill_entry = FillEntry() 67 | self.inp >> compute_qid 68 | compute_qid.out_size_qid >> EnqAlloc() >> fill_entry.in_entry 69 | compute_qid.out_val >> fill_entry.in_val 70 | fill_entry >> EnqSubmit() 71 | 72 | clean >> CleanPrint() 73 | 74 | class rx_read(CallableSegment): 75 | def configure(self): 76 | self.inp = Input(Int) 77 | self.out = Output(queue.q_buffer) 78 | 79 | def impl(self): 80 | self.inp >> DeqGet() >> self.out 81 | 82 | class rx_release(CallableSegment): 83 | def configure(self): 84 | self.inp = Input(queue.q_buffer) 85 | 86 | def impl(self): 87 | self.inp >> DeqRelease() 88 | 89 | Entry(instance=False) 90 | rx_write('rx_write') 91 | rx_read('rx_read') 92 | rx_release('rx_release') 93 | 94 | c = Compiler() 95 | c.testing = r''' 96 | Entry* e; 97 | q_buffer buff; 98 | rx_write(1,1); 99 | rx_write(2,2); 100 | rx_write(5,1); 101 | 102 | buff = rx_read(1); 103 | e = (Entry*) buff.entry; 104 | out(e->val); 105 | rx_release(buff); 106 | 107 | buff = rx_read(1); 108 | e = (Entry*) buff.entry; 109 | out(e->val); 110 | rx_release(buff); 111 | 112 | buff = rx_read(2); 113 | e = (Entry*) buff.entry; 114 | out(e->val); 115 | rx_release(buff); 116 | 117 | buff = rx_read(2); 118 | e = (Entry*) buff.entry; 119 | out(e); 120 | 121 | 122 | rx_write(11,1); 123 | rx_write(12,1); 124 | rx_write(13,1); 125 | rx_write(14,1); 126 | buff = rx_read(1); 127 | e = (Entry*) buff.entry; 128 | out(e->val); 129 | rx_release(buff); 130 | rx_write(14,1); 131 | 132 | ''' 133 | 134 | c.generate_code_and_run([1,"enq",2,"enq", 5, "enq", 1, 5, 2, 0, 11, "enq", 1, "clean", 5, "clean", 12, "enq", 13, "enq", 11, 11, "clean", 14, "enq"]) 135 | #c.generate_code_and_run([1,"enq",2,"enq", 5, "enq", 1, 5, 2, 0, 1, "clean", 5, "clean", 11, "enq", 12, "enq", 13, "enq", 11, 11, "clean", 14, "enq"]) -------------------------------------------------------------------------------- /floem/programs_perpacket_state/cavium_varsize_enq.py: -------------------------------------------------------------------------------- 1 | from floem import * 2 | 3 | class MyState(State): 4 | qid = Field(Int) 5 | keylen = Field(Int) 6 | key = Field(Pointer(Uint(8)), size='state.keylen') 7 | p = Field(Pointer(Int), shared='data_region') 8 | 9 | class Count(State): 10 | count = Field(Int) 11 | def init(self): 12 | self.count = 0 13 | 14 | class main(Flow): 15 | state = PerPacket(MyState) 16 | 17 | class Save(Element): 18 | this = Persistent(Count) 19 | 20 | def configure(self): 21 | self.inp = Input(SizeT, 'void*', 'void*') 22 | self.out = Output() 23 | self.this = Count() 24 | 25 | def impl(self): 26 | self.run_c(r''' 27 | inp(); 28 | this->count++; 29 | printf("inject = %d\n", this->count); 30 | state.qid = 0; 31 | state.key = (uint8_t *) malloc(this->count); 32 | state.keylen = this->count; 33 | int i; 34 | for(i=0; icount ; i++) 35 | state.key[i] = this->count; 36 | 37 | int* p = data_region; 38 | p[this->count] = 100 + this->count; 39 | state.p = &p[this->count]; 40 | output { out(); } 41 | ''') 42 | 43 | def impl_cavium(self): 44 | self.run_c(r''' 45 | inp(); 46 | this->count++; 47 | printf("inject = %d\n", this->count); 48 | state.qid = 0; 49 | state.key = (uint8_t *) malloc(this->count); 50 | state.keylen = this->count; 51 | int i; 52 | for(i=0; icount ; i++) 53 | state.key[i] = this->count; 54 | 55 | int* p = data_region; 56 | void* addr = &p[Count0->count]; 57 | int* x; 58 | dma_buf_alloc((void**) &x); 59 | *x = nic_ntohl(100 + Count0->count); 60 | dma_write((uintptr_t) addr, sizeof(int), x); 61 | dma_free(x); 62 | _state->p = addr; 63 | 64 | output { out(); } 65 | ''') 66 | 67 | class Display(Element): 68 | def configure(self): 69 | self.inp = Input() 70 | 71 | def impl(self): 72 | self.run_c(r''' 73 | printf("%d %d %d %d\n", state.keylen, state.key[0], state.key[state.keylen-1], *state.p); 74 | fflush(stdout); 75 | ''') 76 | 77 | class Drop(Element): 78 | def configure(self): 79 | self.inp = Input() 80 | 81 | def impl(self): 82 | self.run_c(r'''while (0); ''') 83 | 84 | class DisplayPacket(Element): 85 | def configure(self): 86 | self.inp = Input(SizeT, "void *", "void *") 87 | self.out = Output("void *", "void *") 88 | 89 | def impl(self): 90 | self.run_c(r''' 91 | (size_t len, void *pkt, void *buf) = inp(); 92 | if (pkt != NULL) 93 | printf("Got packet\n"); 94 | output { out(pkt, buf); } 95 | ''') 96 | 97 | Enq, Deq, Scan = queue_smart.smart_queue("queue", 256, 2, 1, enq_blocking=False) 98 | 99 | class push(Segment): 100 | def impl(self): 101 | from_net = net.FromNet() 102 | from_net_free = net.FromNetFree() 103 | 104 | from_net.out >> main.Save() >> main.Enq() 105 | from_net.out >> main.DisplayPacket() >> from_net_free 106 | 107 | from_net.nothing >> main.Drop() 108 | 109 | class pop(Segment): 110 | 111 | def impl(self): 112 | self.core_id >> main.Deq() >> main.Display() 113 | 114 | def impl(self): 115 | MemoryRegion("data_region", 4 * 100) 116 | main.push('push', device=target.CAVIUM) 117 | main.pop('pop', process="varsize_enq") 118 | 119 | master_process("varsize_enq") 120 | 121 | c = Compiler(main) 122 | c.generate_code_as_header() 123 | c.depend = ["varsize_enq"] 124 | c.compile_and_run("cavium_varsize_enq_test") 125 | --------------------------------------------------------------------------------