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/pack/fd_pack.h"
24 : #include "../../../disco/pack/fd_pack_cost.h"
25 : #include "../../../disco/topo/fd_topob.h"
26 : #include "../../../util/pod/fd_pod_format.h"
27 :
28 : #include <unistd.h> /* pause */
29 :
30 : extern fd_topo_obj_callbacks_t * CALLBACKS[];
31 : fd_topo_run_tile_t fdctl_tile_run( fd_topo_tile_t const * tile );
32 :
33 : static void
34 0 : sim_topo( config_t * config ) {
35 0 : fd_topo_cpus_t cpus[1];
36 0 : fd_topo_cpus_init( cpus );
37 :
38 0 : fd_topo_t * topo = &config->topo;
39 0 : fd_topob_new( &config->topo, config->name );
40 0 : topo->max_page_size = fd_cstr_to_shmem_page_sz( config->hugetlbfs.max_page_size );
41 :
42 0 : enum{
43 0 : metric_cpu_idx=0,
44 0 : playback_cpu_idx,
45 0 : storei_cpu_idx,
46 0 : replay_cpu_idx,
47 0 : static_end_idx,
48 0 : };
49 :
50 0 : fd_topob_wksp( topo, "metric" );
51 0 : fd_topob_wksp( topo, "metric_in" );
52 0 : fd_topob_tile( topo, "metric", "metric", "metric_in", metric_cpu_idx, 0, 0 );
53 :
54 0 : fd_topob_wksp( topo, "playback" );
55 0 : fd_topob_tile( topo, "arch_p", "playback", "metric_in", playback_cpu_idx, 0, 0 );
56 :
57 0 : fd_topob_wksp( topo, "storei" );
58 0 : fd_topo_tile_t * storei_tile = fd_topob_tile( topo, "storei", "storei", "metric_in", storei_cpu_idx, 0, 0 );
59 :
60 0 : fd_topob_wksp( topo, "replay" );
61 0 : fd_topo_tile_t * replay_tile = fd_topob_tile( topo, "replay", "replay", "metric_in", replay_cpu_idx, 0, 0 );
62 :
63 0 : #define FOR(cnt) for( ulong i=0UL; i<cnt; i++ )
64 :
65 0 : fd_topob_wksp( topo, "exec" );
66 0 : ulong exec_tile_cnt = config->firedancer.layout.exec_tile_count;
67 0 : FOR(exec_tile_cnt) fd_topob_tile( topo, "exec", "exec", "metric_in", static_end_idx+i, 0, 0 );
68 :
69 : /**********************************************************************/
70 : /* Setup playback<->storei and storei<->replay links in topo */
71 : /**********************************************************************/
72 0 : fd_topob_wksp( topo, "shred_storei" );
73 0 : fd_topob_wksp( topo, "repair_store" );
74 0 : fd_topob_wksp( topo, "storei_notif" );
75 0 : fd_topob_wksp( topo, "replay_stake" );
76 0 : fd_topob_wksp( topo, "store_replay" );
77 : /* topo, link_name, wksp_name, depth, mtu, burst */
78 0 : fd_topob_link( topo, "shred_storei", "shred_storei", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
79 0 : fd_topob_link( topo, "repair_store", "repair_store", 1024UL*1024UL, FD_SHRED_MAX_SZ, 128UL );
80 0 : fd_topob_link( topo, "storei_notif", "storei_notif", 65536UL, 4UL*FD_SHRED_STORE_MTU, 4UL+config->tiles.shred.max_pending_shred_sets );
81 0 : fd_topob_link( topo, "replay_stake", "replay_stake", 128UL, 40UL + 40200UL * 40UL, 1UL );
82 0 : fd_topob_link( topo, "store_replay", "store_replay", 32768UL, sizeof(ulong), 64UL );
83 :
84 : /* topo, tile_name, tile_kind_id, link_name, link_kind_id */
85 0 : fd_topob_tile_out( topo, "arch_p", 0UL, "shred_storei", 0UL );
86 0 : fd_topob_tile_out( topo, "arch_p", 0UL, "repair_store", 0UL );
87 0 : fd_topob_tile_in( topo, "arch_p", 0UL, "metric_in", "storei_notif", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
88 :
89 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
90 0 : fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "replay_stake", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
91 0 : fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "repair_store", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
92 0 : fd_topob_tile_in( topo, "storei", 0UL, "metric_in", "shred_storei", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
93 :
94 : /* topo, tile_name, tile_kind_id, link_name, link_kind_id */
95 0 : fd_topob_tile_out( topo, "storei", 0UL, "store_replay", 0UL );
96 0 : fd_topob_tile_out( topo, "storei", 0UL, "storei_notif", 0UL );
97 :
98 : /* topo, tile_name, tile_kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled */
99 0 : fd_topob_tile_in( topo, "replay", 0UL, "metric_in", "store_replay", 0UL, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
100 :
101 : /* topo, tile_name, tile_kind_id, link_name, link_kind_id */
102 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_stake", 0UL );
103 :
104 : /**********************************************************************/
105 : /* Setup replay-->exec links in topo */
106 : /**********************************************************************/
107 0 : fd_topob_wksp( topo, "replay_exec" );
108 0 : fd_topob_link( topo, "replay_exec", "replay_exec", 16384UL, 2240UL, 1UL );
109 0 : fd_topob_tile_out( topo, "replay", 0UL, "replay_exec", 0UL );
110 0 : for( ulong i=0; i<config->firedancer.layout.exec_tile_count; i++ ) {
111 0 : fd_topob_tile_in( topo, "exec", i, "metric_in", "replay_exec", 0UL, FD_TOPOB_RELIABLE, FD_TOPOB_POLLED );
112 0 : }
113 0 : fd_topo_tile_t * exec_tile = &topo->tiles[ fd_topo_find_tile( topo, "exec", 0UL ) ];
114 :
115 : /**********************************************************************/
116 : /* Setup the shared objs used by storei, replay and exec tiles */
117 : /**********************************************************************/
118 0 : fd_topob_wksp( topo, "bstore" );
119 0 : fd_topob_wksp( topo, "poh_shred" );
120 0 : fd_topob_wksp( topo, "root_slot" );
121 0 : fd_topob_wksp( topo, "txncache" );
122 0 : fd_topob_wksp( topo, "poh_slot" );
123 0 : fd_topob_wksp( topo, "bank_busy" );
124 0 : fd_topob_wksp( topo, "exec_spad" );
125 0 : fd_topo_obj_t * poh_shred_obj = fd_topob_obj( topo, "fseq", "poh_shred" );
126 0 : fd_topo_obj_t * root_slot_obj = fd_topob_obj( topo, "fseq", "root_slot" );
127 0 : fd_topo_obj_t * txncache_obj = setup_topo_txncache( topo, "txncache",
128 0 : config->firedancer.runtime.max_live_slots,
129 0 : fd_ulong_pow2_up( FD_PACK_MAX_TXNCACHE_TXN_PER_SLOT ) );
130 0 : fd_topo_obj_t * poh_slot_obj = fd_topob_obj( topo, "fseq", "poh_slot" );
131 0 : fd_topo_obj_t * banks_obj = setup_topo_banks( topo, "banks", config->firedancer.runtime.max_live_slots, config->firedancer.runtime.max_fork_width );
132 :
133 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, poh_shred_obj->id, "poh_shred" ) );
134 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, root_slot_obj->id, "root_slot" ) );
135 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, txncache_obj->id, "txncache" ) );
136 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, poh_slot_obj->id, "poh_slot" ) );
137 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, banks_obj->id, "banks" ) );
138 :
139 0 : fd_topob_tile_uses( topo, storei_tile, poh_shred_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
140 0 : fd_topob_tile_uses( topo, storei_tile, root_slot_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
141 :
142 0 : fd_topob_tile_uses( topo, replay_tile, root_slot_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
143 0 : fd_topob_tile_uses( topo, replay_tile, poh_slot_obj, FD_SHMEM_JOIN_MODE_READ_ONLY );
144 0 : fd_topob_tile_uses( topo, replay_tile, banks_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
145 0 : for( ulong i=0UL; i<config->layout.bank_tile_count; i++ ) {
146 0 : fd_topo_obj_t * busy_obj = fd_topob_obj( topo, "fseq", "bank_busy" );
147 :
148 0 : fd_topob_tile_uses( topo, replay_tile, busy_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
149 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, busy_obj->id, "bank_busy.%lu", i ) );
150 0 : }
151 :
152 0 : for( ulong i=0UL; i<config->firedancer.layout.exec_tile_count; i++ ) {
153 0 : fd_topo_obj_t * exec_spad_obj = fd_topob_obj( topo, "exec_spad", "exec_spad" );
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 : };
|