P4C
The P4 Compiler
Loading...
Searching...
No Matches
bf-asm/jbay/meter.h
1
17
18#ifndef BACKENDS_TOFINO_BF_ASM_JBAY_METER_H_
19#define BACKENDS_TOFINO_BF_ASM_JBAY_METER_H_
20
21template <typename REGS>
22void MeterTable::setup_teop_regs_2(REGS &regs, int meter_group_index) {
23 BUG_CHECK(teop >= 0 && teop < 4, "teop out of range");
24 BUG_CHECK(gress == EGRESS, "gress must be EGRESS");
25
26 auto &adrdist = regs.rams.match.adrdist;
27 if (!teop_initialized) {
28 // assume this stage driving teop
29 auto delay = stage->pipelength(gress) - stage->pred_cycle(gress) - 7;
30 adrdist.teop_bus_ctl[teop].teop_bus_ctl_delay = delay;
31 adrdist.teop_bus_ctl[teop].teop_bus_ctl_delay_en = 1;
32 adrdist.teop_bus_ctl[teop].teop_bus_ctl_meter_en = 1;
33
34 adrdist.meter_to_teop_adr_oxbar_ctl[teop].enabled_2bit_muxctl_select = meter_group_index;
35 adrdist.meter_to_teop_adr_oxbar_ctl[teop].enabled_2bit_muxctl_enable = 1;
36 teop_initialized = true;
37 }
38
39 adrdist.teop_to_meter_adr_oxbar_ctl[meter_group_index].enabled_2bit_muxctl_select = teop;
40 adrdist.teop_to_meter_adr_oxbar_ctl[meter_group_index].enabled_2bit_muxctl_enable = 1;
41
42 // count all tEOP events
43 adrdist.dp_teop_meter_ctl[meter_group_index].dp_teop_meter_ctl_err = 0;
44 // Refer to JBAY uArch Section 6.4.4.10.8
45 //
46 // The user of the incoming tEOP address needs to consider the original
47 // driver. For instance, a meter address driver will be aliged with the LSB
48 // of the 18b incoming address, whereas a single-entry stats driver will be
49 // already padded with 2 zeros.
50 //
51 // For example, dp_teop_meter_ctl.dp_teop_meter_ctl_rx_shift must be
52 // programmed to 2 to compensate for the single-entry stats address driver:
53 //
54 // Meter (23b) = {4b CMD+Color, ((dp_teop{6b VPN, 10b addr, 2b subword
55 // zeros} >> 2) + 7b zero pad)}
56 //
57 // As per above, the dp_teop_meter_ctl_rx_shift is set based on the original
58 // driver. For a meter address driving there is no need for any shift,
59 // however if a stats address is driving then it needs to be shifted by 2.
60 // Compiler currently does not use this mechanism where a stats address is
61 // driving the meter, this is scope for optimization in future.
62 adrdist.dp_teop_meter_ctl[meter_group_index].dp_teop_meter_ctl_rx_shift = 0;
63 adrdist.dp_teop_meter_ctl[meter_group_index].dp_teop_meter_ctl_rx_en = 1;
64
65 auto &meter = regs.rams.map_alu.meter_group[meter_group_index].meter;
66 meter.meter_ctl_teop_en = 1;
67}
68
69template <typename REGS>
70void MeterTable::write_alu_vpn_range_2(REGS &regs) {
71 auto &adrdist = regs.rams.match.adrdist;
72 int minvpn, sparevpn;
73
74 // Used to validate the BFA VPN configuration
75 std::set<int> vpn_processed;
76 bitvec vpn_range;
77
78 // Get Spare VPN
79 layout_vpn_bounds(minvpn, sparevpn, false);
80
81 for (int home_row : home_rows) {
82 bool block_start = false;
83 bool block_end = false;
84 int min = 1000000;
85 int max = -1;
86 for (Layout &logical_row : layout) {
87 // Block Start with the home row and End with the Spare VPN
88 if (logical_row.row == home_row) block_start = true;
89
90 if (block_start) {
91 for (auto v : logical_row.vpns) {
92 if (v == sparevpn) {
93 block_end = true;
94 break;
95 }
96 if (vpn_processed.count(v))
97 error(home_lineno, "Multiple instance of the VPN %d detected", v);
98 else
99 vpn_processed.insert(v);
100
101 if (v < min) min = v;
102 if (v > max) max = v;
103 }
104 }
105 if (block_end) {
106 BUG_CHECK(min != 1000000 && max != -1, "Invalid VPN range");
107
108 bitvec block_range(min, max - min + 1);
109 if (vpn_range.intersects(block_range))
110 error(home_lineno, "Overlapping of VPN range detected");
111 else
112 vpn_range |= block_range;
113
114 adrdist.mau_meter_alu_vpn_range[home_row / 4].meter_vpn_base = min;
115 adrdist.mau_meter_alu_vpn_range[home_row / 4].meter_vpn_limit = max;
116 adrdist.mau_meter_alu_vpn_range[home_row / 4].meter_vpn_range_check_enable = 1;
117 for (MatchTable *m : match_tables)
118 adrdist.meter_alu_adr_range_check_icxbar_map[home_row / 4] |= 1U
119 << m->logical_id;
120 break;
121 }
122 }
123 BUG_CHECK(block_start && block_end, "Invalid VPN range");
124 }
125
126 if (vpn_range != bitvec(minvpn, sparevpn - minvpn))
127 error(home_lineno, "VPN range not entirely covered");
128}
129
130template <>
131void MeterTable::setup_teop_regs(Target::JBay::mau_regs &regs, int meter_group_index) {
132 setup_teop_regs_2(regs, meter_group_index);
133}
134
135template <>
136void MeterTable::write_alu_vpn_range(Target::JBay::mau_regs &regs) {
137 write_alu_vpn_range_2(regs);
138}
139
140#endif /* BACKENDS_TOFINO_BF_ASM_JBAY_METER_H_ */
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58