Line data Source code
1 : /* The sim command spawns a smaller topology for 2 purposes:
2 : 1. read an archive file and reproduce the frags into the storei tile
3 : 2. reproduce the behavior of the replay tile (e.g., the set of forks)
4 :
5 : The smaller topology is:
6 : shred_storei store_replay replay_exec
7 : playback--------------->storei-------------->replay------------>exec
8 : ^ \ ----> | <----- /
9 : | \_______/ | \_____/
10 : | repair_store | stake_out
11 : |______storei_notif______|
12 :
13 : Some tiles are not shown such as the metric tile.
14 :
15 : The playback tile will only send the next frag to the storei tile (
16 : either through shred_storei or through repair_store ) after receiving
17 : a notification for the previous frag from storei_notif.
18 : */
19 :
20 : #include "../../firedancer/topology.h"
21 : #include "../../shared/commands/run/run.h" /* initialize_workspaces */
22 : #include "../../../disco/topo/fd_cpu_topo.h" /* fd_topo_cpus */
23 : #include "../../../disco/topo/fd_topob.h"
24 : #include "../../../util/pod/fd_pod_format.h"
25 :
26 : #include <unistd.h> /* pause */
27 :
28 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
29 : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
30 :
31 : static void
32 0 : sim_topo( config_t * config ) {
33 0 : fd_topo_cpus_t cpus[1];
34 0 : fd_topo_cpus_init( cpus );
35 :
36 0 : fd_topo_t * topo = &config->topo;
37 0 : fd_topob_new( &config->topo, config->name );
38 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
39 :
40 0 : enum{
41 0 : metric_cpu_idx=0,
42 0 : playback_cpu_idx,
43 0 : storei_cpu_idx,
44 0 : replay_cpu_idx,
45 0 : static_end_idx,
46 0 : };
47 :
48 0 : fd_topob_wksp( topo, "metric" );
49 0 : fd_topob_wksp( topo, "metric_in" );
50 0 : fd_topob_tile( topo, "metric", "metric", "metric_in", metric_cpu_idx, 0, 0 );
51 :
52 0 : fd_topob_wksp( topo, "playback" );
53 0 : fd_topob_tile( topo, "arch_p", "playback", "metric_in", playback_cpu_idx, 0, 0 );
54 :
55 0 : fd_topob_wksp( topo, "storei" );
56 0 : fd_topo_tile_t * storei_tile = fd_topob_tile( topo, "storei", "storei", "metric_in", storei_cpu_idx, 0, 0 );
57 :
58 0 : fd_topob_wksp( topo, "replay" );
59 0 : fd_topo_tile_t * replay_tile = fd_topob_tile( topo, "replay", "replay", "metric_in", replay_cpu_idx, 0, 0 );
60 :
61 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
62 :
63 0 : fd_topob_wksp( topo, "exec" );
64 0 : ulong exec_tile_cnt = config->firedancer.layout.exec_tile_count;
65 0 : FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", static_end_idx+i, 0, 0 );
66 :
67 : /**********************************************************************/
68 : /* Setup playback<->storei and storei<->replay links in topo */
69 : /**********************************************************************/
70 0 : fd_topob_wksp( topo, "shred_storei" );
71 0 : fd_topob_wksp( topo, "repair_store" );
72 0 : fd_topob_wksp( topo, "storei_notif" );
73 0 : fd_topob_wksp( topo, "replay_stake" );
74 0 : fd_topob_wksp( topo, "store_replay" );
75 : /* topo, link_name, wksp_name, depth, mtu, burst */
76 0 : fd_topob_link( topo, "shred_storei", "shred_storei", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
77 0 : fd_topob_link( topo, "repair_store", "repair_store", 1024UL*1024UL, FD_SHRED_MAX_SZ, 128UL );
78 0 : fd_topob_link( topo, "storei_notif", "storei_notif", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
79 0 : fd_topob_link( topo, "replay_stake", "replay_stake", 128UL, 40UL + 40200UL * 40UL, 1UL );
80 0 : fd_topob_link( topo, "store_replay", "store_replay", 32768UL, sizeof(ulong), 64UL );
81 :
82 : /* topo, tile_name, tile_kind_id, link_name, link_kind_id */
83 0 : fd_topob_tile_out( topo, "arch_p", 0UL, "shred_storei", 0UL );
84 0 : fd_topob_tile_out( topo, "arch_p", 0UL, "repair_store", 0UL );
85 0 : fd_topob_tile_in( topo, "arch_p", 0UL, "metric_in", "storei_notif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
86 :
87 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
88 0 : fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
89 0 : fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "repair_store", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
90 0 : fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "shred_storei", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
91 :
92 : /* topo, tile_name, tile_kind_id, link_name, link_kind_id */
93 0 : fd_topob_tile_out( topo, "storei", 0UL, "store_replay", 0UL );
94 0 : fd_topob_tile_out( topo, "storei", 0UL, "storei_notif", 0UL );
95 :
96 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
97 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "store_replay", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
98 :
99 : /* topo, tile_name, tile_kind_id, link_name, link_kind_id */
100 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_stake", 0UL );
101 :
102 : /**********************************************************************/
103 : /* Setup replay<->exec links in topo */
104 : /**********************************************************************/
105 0 : fd_topob_wksp( topo, "replay_exec" );
106 0 : for( ulong i=0; i<config->firedancer.layout.exec_tile_count; i++ ) {
107 0 : fd_topob_link( topo, "replay_exec", "replay_exec", 128UL, 10240UL, 1UL );
108 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", i );
109 0 : fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", i, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
110 0 : }
111 0 : fd_topo_tile_t * exec_tile = &topo->tiles[ fd_topo_find_tile( topo, "exec", 0UL ) ];
112 :
113 : /**********************************************************************/
114 : /* Setup the shared objs used by storei, replay and exec tiles */
115 : /**********************************************************************/
116 0 : fd_topob_wksp( topo, "bstore" );
117 0 : fd_topob_wksp( topo, "poh_shred" );
118 0 : fd_topob_wksp( topo, "root_slot" );
119 0 : fd_topob_wksp( topo, "tcache" );
120 0 : fd_topob_wksp( topo, "poh_slot" );
121 0 : fd_topob_wksp( topo, "bank_busy" );
122 0 : fd_topob_wksp( topo, "exec_spad" );
123 0 : fd_topo_obj_t * poh_shred_obj = fd_topob_obj( topo, "fseq", "poh_shred" );
124 0 : fd_topo_obj_t * root_slot_obj = fd_topob_obj( topo, "fseq", "root_slot" );
125 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "tcache",
126 0 : config->firedancer.runtime.max_rooted_slots,
127 0 : config->firedancer.runtime.max_live_slots,
128 0 : config->firedancer.runtime.max_transactions_per_slot );
129 0 : fd_topo_obj_t * poh_slot_obj = fd_topob_obj( topo, "fseq", "poh_slot" );
130 0 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_total_banks, config->firedancer.runtime.max_fork_width );
131 :
132 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, poh_shred_obj->id, "poh_shred" ) );
133 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, root_slot_obj->id, "root_slot" ) );
134 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
135 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, poh_slot_obj->id, "poh_slot" ) );
136 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
137 :
138 0 : fd_topob_tile_uses( topo, storei_tile, poh_shred_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
139 0 : fd_topob_tile_uses( topo, storei_tile, root_slot_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
140 :
141 0 : fd_topob_tile_uses( topo, replay_tile, root_slot_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
142 0 : fd_topob_tile_uses( topo, replay_tile, poh_slot_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
143 0 : fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
144 0 : for( ulong i=0UL; i<config->layout.bank_tile_count; i++ ) {
145 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
146 :
147 0 : fd_topob_tile_uses( topo, replay_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
148 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
149 0 : }
150 :
151 0 : for( ulong i=0UL; i<config->firedancer.layout.exec_tile_count; i++ ) {
152 0 : fd_topo_obj_t * exec_spad_obj = fd_topob_obj( topo, "exec_spad", "exec_spad" );
153 0 : fd_topob_tile_uses( topo, replay_tile, exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
154 0 : fd_topob_tile_uses( topo, exec_tile, exec_spad_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
155 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, exec_spad_obj->id, "exec_spad.%lu", i ) );
156 0 : }
157 :
158 0 : for( ulong i=0UL; i<topo->tile_cnt; i++ ) {
159 0 : fd_topo_tile_t * tile = &topo->tiles[ i ];
160 0 : if( !strcmp( tile->name, "arch_p" ) ) {
161 0 : strncpy( tile->archiver.rocksdb_path, config->tiles.archiver.rocksdb_path, PATH_MAX );
162 0 : if( FD_UNLIKELY( 0==strlen( tile->archiver.rocksdb_path ) ) ) {
163 0 : FD_LOG_ERR(( "Archive file not found for playback" ));
164 0 : } else {
165 0 : FD_LOG_NOTICE(( "Found archive file from config: %s", tile->archiver.rocksdb_path ));
166 0 : }
167 0 : } else {
168 0 : fd_topo_configure_tile( tile, config );
169 0 : }
170 0 : }
171 :
172 : /**********************************************************************/
173 : /* Finish and print out the topo information */
174 : /**********************************************************************/
175 0 : fd_topob_finish( topo, CALLBACKS );
176 0 : fd_topo_print_log( /* stdout */ 1, topo );
177 0 : }
178 :
179 : static void
180 : sim_cmd_fn( args_t * args FD_PARAM_UNUSED,
181 0 : config_t * config ) {
182 0 : sim_topo( config );
183 :
184 0 : initialize_workspaces( config );
185 0 : initialize_stacks( config );
186 0 : fd_topo_t * topo = &config->topo;
187 0 : fd_topo_join_workspaces( topo, FD_SHMEM_JOIN_MODE_READ_WRITE );
188 :
189 : /* FIXME: there's no PoH tile in this mini-topology,
190 : * but replay tile waits for `poh_slot!=ULONG_MAX` before starting to vote
191 : * -- vote updates the root for funk/blockstore publish */
192 0 : ulong poh_slot_obj_id = fd_pod_query_ulong( topo->props, "poh_slot", ULONG_MAX );
193 0 : FD_TEST( poh_slot_obj_id!=ULONG_MAX );
194 0 : ulong * poh = fd_fseq_join( fd_topo_obj_laddr( topo, poh_slot_obj_id ) );
195 0 : fd_fseq_update( poh, 0UL );
196 :
197 0 : fd_topo_run_single_process( topo, 2, config->uid, config->gid, fdctl_tile_run );
198 0 : for(;;) pause();
199 0 : }
200 :
201 : static void
202 : sim_cmd_perm( args_t * args FD_PARAM_UNUSED,
203 : fd_cap_chk_t * chk FD_PARAM_UNUSED,
204 0 : config_t const * config FD_PARAM_UNUSED ) {}
205 :
206 : static void
207 : sim_cmd_args( int * pargc FD_PARAM_UNUSED,
208 : char *** pargv FD_PARAM_UNUSED,
209 0 : args_t * args FD_PARAM_UNUSED ) {}
210 :
211 : action_t fd_action_sim = {
212 : .name = "sim",
213 : .args = sim_cmd_args,
214 : .fn = sim_cmd_fn,
215 : .perm = sim_cmd_perm,
216 : };
|