P4C
The P4 Compiler
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
data_switchbox.h
1
17
18#ifndef BACKENDS_TOFINO_BF_ASM_DATA_SWITCHBOX_H_
19#define BACKENDS_TOFINO_BF_ASM_DATA_SWITCHBOX_H_
20
21#include "backends/tofino/bf-asm/stage.h"
22#include "backends/tofino/bf-asm/tables.h"
23
24/*
25 * Code to handle programming of the Ram Data Bus Horizontal/Vertical Switchbox
26 * see section 6.2.4.4 of the MAU uArch docs
27 */
28
29template <class REGS>
30class DataSwitchboxSetup {
31 REGS &regs;
32 Table *tbl;
33 unsigned home_row, home_row_logical, prev_row, top_ram_row, bottom_ram_row;
34
35 public:
36 unsigned get_home_row() { return home_row; }
37 unsigned get_home_row_logical() { return home_row_logical; }
38 DataSwitchboxSetup(REGS &regs, Table *t, int home = -1, int next_home = -1)
39 : regs(regs), tbl(t) {
40 if (home >= 0)
41 top_ram_row = prev_row = home_row = home / 2U;
42 else
43 top_ram_row = prev_row = home_row = tbl->layout[0].row / 2U;
44 bottom_ram_row = tbl->layout.back().row / 2U;
45 if (next_home >= 0) {
46 for (auto it = tbl->layout.rbegin(); it != tbl->layout.rend(); ++it) {
47 if (it->row > next_home) {
48 bottom_ram_row = it->row / 2U;
49 break;
50 }
51 }
52 }
53
54 // Counter ALU's are on even rows on right side of RAM array. Set
55 // home_row to the correct ALU
56 if (tbl->table_type() == Table::COUNTER)
57 prev_row = home_row = prev_row % 2 ? prev_row + 1 : prev_row;
58 // Stateful/Selection/Meter ALU's are on odd rows on right side of RAM
59 // array. Set home_row to the correct ALU
60 else if (tbl->table_type() == Table::STATEFUL || tbl->table_type() == Table::SELECTION ||
61 tbl->table_type() == Table::METER)
62 prev_row = home_row = prev_row % 2 ? prev_row : prev_row + 1;
63 home_row_logical = home_row * 2 + 1;
64 }
74 void setup_row(unsigned row) {
75 auto &map_alu = regs.rams.map_alu;
76 auto &swbox = regs.rams.array.switchbox.row;
77 auto &map_alu_row = map_alu.row[row];
78 int side = 1; // always -- currently no maprams on left side
79 auto &syn2port_ctl = map_alu_row.i2portctl.synth2port_fabric_ctl[0][side];
80 map_alu_row.i2portctl.synth2port_ctl.synth2port_enable = 1;
81 while (prev_row != row) {
82 auto &prev_syn2port_ctl = map_alu.row[prev_row].i2portctl.synth2port_fabric_ctl[0];
83 if (prev_row == home_row) {
84 swbox[prev_row].ctl.r_stats_alu_o_mux_select.r_stats_alu_o_sel_oflo_rd_b_i = 1;
85 swbox[prev_row].ctl.b_oflo_wr_o_mux_select.b_oflo_wr_o_sel_stats_wr_r_i = 1;
86 prev_syn2port_ctl[side].stats_to_vbus_below = 1;
87 } else {
88 // If a row is in the middle of possible rows, must program the switchbox
89 // to have data pass through the bottom of the switch box to the top of
90 // the switchbox
91 swbox[prev_row].ctl.t_oflo_rd_o_mux_select.t_oflo_rd_o_sel_oflo_rd_b_i = 1;
92 swbox[prev_row].ctl.b_oflo_wr_o_mux_select.b_oflo_wr_o_sel_oflo_wr_t_i = 1;
93 // below2above only means that there is no synth2port RAMs on this row, but
94 // the signal needs to pass between the rows
95 prev_syn2port_ctl[side].synth2port_connect_below2above = 1;
96 /* need to also program left side below2above connections
97 * see ram_bus_path.py:254 -- 'Mike F.' comment */
98 prev_syn2port_ctl[0].synth2port_connect_below2above = 1;
99 prev_syn2port_ctl[side].oflo_to_vbus_below = 1;
100 }
101 auto &next_syn2port_ctl =
102 map_alu.row[prev_row - 1].i2portctl.synth2port_fabric_ctl[0][side];
103 // From RTL, it only appears that oflo_to_vbus_below/above should be programmed
104 // when RAMs appear on the RAM line, but the model asserts if these are not enabled.
105 // Keeping this, as it is what is DV'ed against
106 next_syn2port_ctl.oflo_to_vbus_above = 1;
107 prev_row--;
108 }
109 // FIXME: Should this be top_ram_row?
110 if (row == home_row) {
111 swbox[row].ctl.r_stats_alu_o_mux_select.r_stats_alu_o_sel_stats_rd_r_i = 1;
112 } else {
113 // The oflo signal of this row must go through the overflow bus
114 swbox[row].ctl.t_oflo_rd_o_mux_select.t_oflo_rd_o_sel_oflo_rd_r_i = 1;
115 swbox[row].ctl.r_oflo_wr_o_mux_select = 1;
116 syn2port_ctl.synth2port_connect_above = 1;
117 }
118
119 if (row != bottom_ram_row) {
120 // To determine whether data flows back down. Doesn't flow down on the lowest row
121 syn2port_ctl.synth2port_connect_below = 1;
122 }
123 }
124 void setup_row_col(unsigned row, unsigned col, int vpn) {
125 int side = col >= 6;
126 unsigned logical_col = col % 6U;
127 auto &ram = regs.rams.array.row[row].ram[col];
128 auto &map_alu = regs.rams.map_alu;
129 auto &map_alu_row = map_alu.row[prev_row];
130 auto &unitram_config = map_alu_row.adrmux.unitram_config[side][logical_col];
131 unitram_config.unitram_type = tbl->unitram_type();
132 unitram_config.unitram_logical_table = tbl->logical_id;
133 if (!options.match_compiler) // FIXME -- compiler doesn't set this?
134 unitram_config.unitram_vpn = vpn;
135 if (tbl->gress == INGRESS || tbl->gress == GHOST)
136 unitram_config.unitram_ingress = 1;
137 else
138 unitram_config.unitram_egress = 1;
139 unitram_config.unitram_enable = 1;
140
141 auto &ram_address_mux_ctl = map_alu_row.adrmux.ram_address_mux_ctl[side][logical_col];
142 ram_address_mux_ctl.ram_unitram_adr_mux_select = UnitRam::AdrMux::STATS_METERS;
143 if (row == home_row) {
144 ram.unit_ram_ctl.match_ram_write_data_mux_select = UnitRam::DataMux::STATISTICS;
145 ram.unit_ram_ctl.match_ram_read_data_mux_select = UnitRam::DataMux::STATISTICS;
146 if (tbl->adr_mux_select_stats())
147 ram_address_mux_ctl.ram_stats_meter_adr_mux_select_stats = 1;
148 else
149 ram_address_mux_ctl.ram_stats_meter_adr_mux_select_meter = 1;
150 ram_address_mux_ctl.ram_ofo_stats_mux_select_statsmeter = 1;
151 ram_address_mux_ctl.synth2port_radr_mux_select_home_row = 1;
152 } else {
153 ram.unit_ram_ctl.match_ram_write_data_mux_select = UnitRam::DataMux::OVERFLOW;
154 ram.unit_ram_ctl.match_ram_read_data_mux_select = UnitRam::DataMux::OVERFLOW;
155 ram_address_mux_ctl.ram_oflo_adr_mux_select_oflo = 1;
156 ram_address_mux_ctl.ram_ofo_stats_mux_select_oflo = 1;
157 ram_address_mux_ctl.synth2port_radr_mux_select_oflo = 1;
158 }
159 ram_address_mux_ctl.map_ram_wadr_mux_select = MapRam::Mux::SYNTHETIC_TWO_PORT;
160 ram_address_mux_ctl.map_ram_wadr_mux_enable = 1;
161 ram_address_mux_ctl.map_ram_radr_mux_select_smoflo = 1;
162 int syn2port_bus = prev_row == top_ram_row ? 0 : 1;
163 auto &syn2port_members = map_alu_row.i2portctl.synth2port_hbus_members[syn2port_bus][side];
164 syn2port_members |= 1U << logical_col;
165 }
166};
167
168#endif /* BACKENDS_TOFINO_BF_ASM_DATA_SWITCHBOX_H_ */
void setup_row(unsigned row)
Definition data_switchbox.h:74
Definition tables.h:98