-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdirectMeterMap.cpp
109 lines (96 loc) · 3.49 KB
/
directMeterMap.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
Copyright 2013-present Barefoot Networks, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "directMeterMap.h"
namespace PSDN {
/**
* @returns direct meter information from the direct meter map
*
*/
DirectMeterMap::DirectMeterInfo* DirectMeterMap::createInfo(const IR::IDeclaration* meter) {
auto prev = ::get(directMeter, meter);
BUG_CHECK(prev == nullptr, "Already created");
auto result = new DirectMeterMap::DirectMeterInfo();
directMeter.emplace(meter, result);
return result;
}
DirectMeterMap::DirectMeterInfo* DirectMeterMap::getInfo(const IR::IDeclaration* meter) {
return ::get(directMeter, meter);
}
/**
* Set the table that a direct meter is attached to.
*/
void DirectMeterMap::setTable(const IR::IDeclaration* meter, const IR::P4Table* table) {
auto info = getInfo(meter);
if (info == nullptr) {
::error(ErrorType::ERR_INVALID,
"table with direct meter %2% must have"
" at least one action with a read method call",
table, meter);
return;
}
if (info->table != nullptr)
::error(ErrorType::ERR_INVALID,
"%1%: Direct meters cannot be attached to multiple tables %2% and %3%",
meter, table, info->table);
info->table = table;
}
/**
* Helper function to check if two expressions are syntactically identical
*/
static bool checkSame(const IR::Expression* expr0, const IR::Expression* expr1) {
if (expr0->node_type_name() != expr1->node_type_name())
return false;
if (auto pe0 = expr0->to<IR::PathExpression>()) {
auto pe1 = expr1->to<IR::PathExpression>();
return pe0->path->name == pe1->path->name &&
pe0->path->absolute == pe1->path->absolute;
} else if (auto mem0 = expr0->to<IR::Member>()) {
auto mem1 = expr1->to<IR::Member>();
return checkSame(mem0->expr, mem1->expr) && mem0->member == mem1->member;
}
BUG("%1%: unexpected expression for meter destination", expr0);
}
/**
* Set the destination that a meter is attached to.
*/
void DirectMeterMap::setDestination(const IR::IDeclaration* meter,
const IR::Expression* destination) {
auto info = getInfo(meter);
if (info == nullptr)
info = createInfo(meter);
if (info->destinationField == nullptr) {
info->destinationField = destination;
} else {
bool same = checkSame(destination, info->destinationField);
if (!same)
::error(ErrorType::ERR_INVALID,
"all meter operations must write to the same destination,"
" however %1% and %2% are different", destination, info->destinationField);
}
}
/**
* Set the size of the table that a meter is attached to.
*/
void DirectMeterMap::setSize(const IR::IDeclaration* meter, unsigned size) {
auto info = getInfo(meter);
if (info == nullptr) {
/* This case may be reached if a table has a direct_meter
* assigned to its 'meters' property, but none of its actions
* have a call to the 'read' method of that meter. An error
* message is already printed elsewhere in this case, but we
* want to avoid a Compiler Bug. */
return;
}
info->tableSize = size;
}
}; // namespace PSDN