P4C
The P4 Compiler
Loading...
Searching...
No Matches
tofino/stage.cpp
1
17
18/* mau stage template specializations for tofino -- #included directly in top-level stage.cpp */
19
20template <>
21void Stage::write_regs(Target::Tofino::mau_regs &regs, bool) {
22 write_common_regs<Target::Tofino>(regs);
23 auto &merge = regs.rams.match.merge;
24 for (gress_t gress : Range(INGRESS, EGRESS)) {
25 if (stageno == 0) {
26 merge.predication_ctl[gress].start_table_fifo_delay0 = pred_cycle(gress) - 1;
27 merge.predication_ctl[gress].start_table_fifo_delay1 = 0;
28 merge.predication_ctl[gress].start_table_fifo_enable = 1;
29 } else {
30 switch (stage_dep[gress]) {
31 case MATCH_DEP:
32 merge.predication_ctl[gress].start_table_fifo_delay0 =
33 this[-1].pipelength(gress) - this[-1].pred_cycle(gress) +
34 pred_cycle(gress) - 1;
35 merge.predication_ctl[gress].start_table_fifo_delay1 =
36 this[-1].pipelength(gress) - this[-1].pred_cycle(gress);
37 merge.predication_ctl[gress].start_table_fifo_enable = 3;
38 break;
39 case ACTION_DEP:
40 merge.predication_ctl[gress].start_table_fifo_delay0 = 1;
41 merge.predication_ctl[gress].start_table_fifo_delay1 = 0;
42 merge.predication_ctl[gress].start_table_fifo_enable = 1;
43 break;
44 case CONCURRENT:
45 merge.predication_ctl[gress].start_table_fifo_enable = 0;
46 break;
47 default:
48 BUG("bad stage dependency");
49 }
50 }
51 if (stageno != 0) {
52 regs.dp.cur_stage_dependency_on_prev[gress] = MATCH_DEP - stage_dep[gress];
53 if (stage_dep[gress] == CONCURRENT) regs.dp.stage_concurrent_with_prev |= 1U << gress;
54 }
55 if (stageno != AsmStage::numstages() - 1)
56 regs.dp.next_stage_dependency_on_cur[gress] = MATCH_DEP - this[1].stage_dep[gress];
57 else if (AsmStage::numstages() < Target::NUM_MAU_STAGES())
58 regs.dp.next_stage_dependency_on_cur[gress] = 2;
59 auto &deferred_eop_bus_delay = regs.rams.match.adrdist.deferred_eop_bus_delay[gress];
60 deferred_eop_bus_delay.eop_internal_delay_fifo = pred_cycle(gress) + 3;
61 /* FIXME -- making this depend on the dependency of the next stage seems wrong */
62 if (stageno == AsmStage::numstages() - 1) {
63 if (AsmStage::numstages() < Target::NUM_MAU_STAGES())
64 deferred_eop_bus_delay.eop_output_delay_fifo = 0;
65 else
66 deferred_eop_bus_delay.eop_output_delay_fifo = pipelength(gress) - 1;
67 } else if (this[1].stage_dep[gress] == MATCH_DEP)
68 deferred_eop_bus_delay.eop_output_delay_fifo = pipelength(gress) - 1;
69 else if (this[1].stage_dep[gress] == ACTION_DEP)
70 deferred_eop_bus_delay.eop_output_delay_fifo = 1;
71 else
72 deferred_eop_bus_delay.eop_output_delay_fifo = 0;
73 deferred_eop_bus_delay.eop_delay_fifo_en = 1;
74 }
75
76 for (gress_t gress : Range(INGRESS, EGRESS))
77 if (table_use[gress] & USE_TCAM)
78 regs.tcams.tcam_piped |= options.match_compiler ? 3 : 1 << gress;
79
80 bitvec in_use = match_use[INGRESS] | action_use[INGRESS] | action_set[INGRESS];
81 bitvec eg_use = match_use[EGRESS] | action_use[EGRESS] | action_set[EGRESS];
82 if (options.match_compiler) {
83 /* the glass compiler occasionally programs extra uses of random registers on
84 * busses where it doesn't actually use them. Sometimes, these regs
85 * are in use by the other thread, so rely on the deparser to correctly
86 * set the Phv::use info and strip out registers it says are used by
87 * the other thread */
88 in_use -= Deparser::PhvUse(EGRESS);
89 eg_use -= Deparser::PhvUse(INGRESS);
90 }
91 /* FIXME -- if the regs are live across a stage (even if not used in that stage) they
92 * need to be set in the thread registers. For now we just assume if they are used
93 * anywhere, they need to be marked as live */
94 in_use |= Phv::use(INGRESS);
95 eg_use |= Phv::use(EGRESS);
96 static const int phv_use_transpose[2][14] = {
97 {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 20, 21},
98 {4, 5, 6, 7, 12, 13, 14, 15, 22, 23, 24, 25, 26, 27}};
99 // FIXME -- this code depends on the Phv::Register uids matching the
100 // FIXME -- mau encoding of phv containers. (FIXME-PHV)
101 for (int i = 0; i < 2; i++) {
102 for (int j = 0; j < 14; j++) {
103 regs.dp.phv_ingress_thread_alu[i][j] = regs.dp.phv_ingress_thread_imem[i][j] =
104 regs.dp.phv_ingress_thread[i][j] = in_use.getrange(8 * phv_use_transpose[i][j], 8);
105 regs.dp.phv_egress_thread_alu[i][j] = regs.dp.phv_egress_thread_imem[i][j] =
106 regs.dp.phv_egress_thread[i][j] = eg_use.getrange(8 * phv_use_transpose[i][j], 8);
107 }
108 }
109}
110
111template <>
112void Stage::gen_configuration_cache(Target::Tofino::mau_regs &regs, json::vector &cfg_cache) {
113 Stage::gen_configuration_cache_common(regs, cfg_cache);
114
115 unsigned reg_width = 8; // this means number of hex characters
116 std::string reg_fqname;
117 std::string reg_name;
118 unsigned reg_value;
119 std::string reg_value_str;
120
121 // meter_ctl
122 auto &meter_ctl = regs.rams.map_alu.meter_group;
123 for (int i = 0; i < 4; i++) {
124 reg_fqname = "mau[" + std::to_string(stageno) + "].rams.map_alu.meter_group[" +
125 std::to_string(i) + "]" + ".meter.meter_ctl";
126 reg_name = "stage_" + std::to_string(stageno) + "_meter_ctl_" + std::to_string(i);
127 reg_value = meter_ctl[i].meter.meter_ctl;
128 if ((reg_value != 0) || (options.match_compiler)) {
129 reg_value_str = int_to_hex_string(reg_value, reg_width);
130 add_cfg_reg(cfg_cache, reg_fqname, reg_name, reg_value_str);
131 }
132 }
133}
134
135template <>
136void Stage::gen_mau_stage_extension(Target::Tofino::mau_regs &regs, json::map &extend) {
137 BUG("stage extension not supported on Tofino");
138}
139
140void AlwaysRunTable::write_regs(Target::Tofino::mau_regs &) {
141 BUG("register writes not supported on Tofino");
142}
Definition bitvec.h:120
Definition backends/tofino/bf-asm/json.h:300
Definition backends/tofino/bf-asm/json.h:222