Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser graph generation support for graphs backend #969

Merged
merged 5 commits into from
Oct 30, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cpplint fix- tab2whitespace
  • Loading branch information
c3m3gyanesh committed Oct 13, 2017
commit f2a7618dde552eb5cd0bffcb6e9543eaa6a5c49b
4 changes: 2 additions & 2 deletions backends/graphs/controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

#include "graphs.h"

#include <boost/graph/graphviz.hpp>

#include <iostream>

#include "graphs.h"

#include "frontends/p4/methodInstance.h"
#include "frontends/p4/tableApply.h"
#include "lib/log.h"
Expand Down
16 changes: 8 additions & 8 deletions backends/graphs/graphs.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ class ParserGraphs : public Inspector {
enum class VertexType {
HEADER,
PARSER,
DEFAULT,
STATEMENTS
DEFAULT,
STATEMENTS
};
struct Vertex {
cstring name;
Expand Down Expand Up @@ -202,12 +202,12 @@ class ParserGraphs : public Inspector {

void writeGraphToFile(const Graph &g, const cstring &name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as underlined in my comment above, duplicating this method in ControlGraphs and ParserGraphs looks like a bad design

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the code duplication is minimized.


cstring stringRepr(mpz_class value, unsigned bytes);
void convertSimpleKey(const IR::Expression* keySet,
mpz_class& value, mpz_class& mask);
unsigned combine(const IR::Expression* keySet,
const IR::ListExpression* select,
mpz_class& value, mpz_class& mask);
cstring stringRepr(mpz_class value, unsigned bytes);
void convertSimpleKey(const IR::Expression* keySet,
mpz_class& value, mpz_class& mask);
unsigned combine(const IR::Expression* keySet,
const IR::ListExpression* select,
mpz_class& value, mpz_class& mask);

private:
P4::ReferenceMap *refMap; P4::TypeMap *typeMap;
Expand Down
279 changes: 139 additions & 140 deletions backends/graphs/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

#include "graphs.h"

#include <boost/graph/graphviz.hpp>

#include <iostream>

#include "graphs.h"

#include "lib/log.h"
#include "lib/nullstream.h"
#include "lib/path.h"
Expand Down Expand Up @@ -77,8 +77,8 @@ class ParserGraphs::GraphAttributeSetter {
switch (type) {
case VertexType::HEADER:
return "ellipse";
case VertexType::DEFAULT:
return "doublecircle";
case VertexType::DEFAULT:
return "doublecircle";
default:
return "rectangle";
}
Expand All @@ -90,8 +90,8 @@ class ParserGraphs::GraphAttributeSetter {
switch (type) {
case VertexType::STATEMENTS:
return "dashed";
case VertexType::DEFAULT:
return "bold";
case VertexType::DEFAULT:
return "bold";
default:
return "solid";
}
Expand All @@ -111,22 +111,22 @@ void ParserGraphs::writeGraphToFile(const pGraph &g, const cstring &name) {
}

cstring ParserGraphs::stringRepr(mpz_class value, unsigned bytes) {
cstring sign = "";
const char* r;
cstring filler = "";
if (value < 0) {
value =- value;
r = mpz_get_str(nullptr, 16, value.get_mpz_t());
sign = "-";
} else {
r = mpz_get_str(nullptr, 16, value.get_mpz_t());
}
if (bytes > 0) {
int digits = bytes * 2 - strlen(r);
BUG_CHECK(digits >= 0, "Cannot represent %1% on %2% bytes", value, bytes);
filler = std::string(digits, '0');
}
return sign + "0x" + filler + r;
cstring sign = "";
const char* r;
cstring filler = "";
if (value < 0) {
value =- value;
r = mpz_get_str(nullptr, 16, value.get_mpz_t());
sign = "-";
} else {
r = mpz_get_str(nullptr, 16, value.get_mpz_t());
}
if (bytes > 0) {
int digits = bytes * 2 - strlen(r);
BUG_CHECK(digits >= 0, "Cannot represent %1% on %2% bytes", value, bytes);
filler = std::string(digits, '0');
}
return sign + "0x" + filler + r;
}

void ParserGraphs::convertSimpleKey(const IR::Expression* keySet,
Expand Down Expand Up @@ -158,78 +158,77 @@ void ParserGraphs::convertSimpleKey(const IR::Expression* keySet,

unsigned ParserGraphs::combine(const IR::Expression* keySet,
const IR::ListExpression* select,
mpz_class& value, mpz_class& mask) {
value = 0;
mask = 0;
unsigned totalWidth = 0;
if (keySet->is<IR::DefaultExpression>()) {
return totalWidth;
} else if (keySet->is<IR::ListExpression>()) {
auto le = keySet->to<IR::ListExpression>();
BUG_CHECK(le->components.size() == select->components.size(),
"%1%: mismatched select", select);
unsigned index = 0;

bool noMask = true;
for (auto it = select->components.begin();
it != select->components.end(); ++it) {
auto e = *it;
auto keyElement = le->components.at(index);

auto type = typeMap->getType(e, true);
int width = type->width_bits();
BUG_CHECK(width > 0, "%1%: unknown width", e);

mpz_class key_value, mask_value;
convertSimpleKey(keyElement, key_value, mask_value);
unsigned w = 8 * ROUNDUP(width, 8);
totalWidth += ROUNDUP(width, 8);
value = Util::shift_left(value, w) + key_value;
if (mask_value != -1) {
mask = Util::shift_left(mask, w) + mask_value;
noMask = false;
}
LOG3("Shifting " << " into key " << key_value << " &&& " << mask_value <<
" result is " << value << " &&& " << mask);
index++;
}

if (noMask)
mask = -1;
return totalWidth;
} else {
BUG_CHECK(select->components.size() == 1, "%1%: mismatched select/label", select);
convertSimpleKey(keySet, value, mask);
auto type = typeMap->getType(select->components.at(0), true);
return ROUNDUP(type->width_bits(), 8);
}
mpz_class& value, mpz_class& mask) {
value = 0;
mask = 0;
unsigned totalWidth = 0;
if (keySet->is<IR::DefaultExpression>()) {
return totalWidth;
} else if (keySet->is<IR::ListExpression>()) {
auto le = keySet->to<IR::ListExpression>();
BUG_CHECK(le->components.size() == select->components.size(),
"%1%: mismatched select", select);
unsigned index = 0;

bool noMask = true;
for (auto it = select->components.begin();
it != select->components.end(); ++it) {
auto e = *it;
auto keyElement = le->components.at(index);

auto type = typeMap->getType(e, true);
int width = type->width_bits();
BUG_CHECK(width > 0, "%1%: unknown width", e);

mpz_class key_value, mask_value;
convertSimpleKey(keyElement, key_value, mask_value);
unsigned w = 8 * ROUNDUP(width, 8);
totalWidth += ROUNDUP(width, 8);
value = Util::shift_left(value, w) + key_value;
if (mask_value != -1) {
mask = Util::shift_left(mask, w) + mask_value;
noMask = false;
}
LOG3("Shifting " << " into key " << key_value << " &&& " << mask_value <<
" result is " << value << " &&& " << mask);
index++;
}

if (noMask)
mask = -1;
return totalWidth;
} else {
BUG_CHECK(select->components.size() == 1, "%1%: mismatched select/label", select);
convertSimpleKey(keySet, value, mask);
auto type = typeMap->getType(select->components.at(0), true);
return ROUNDUP(type->width_bits(), 8);
}
}

bool ParserGraphs::preorder(const IR::PackageBlock *block) {
for (auto it : block->constantValue) {
if (it.second->is<IR::ParserBlock>()) {
auto name = it.second->to<IR::ParserBlock>()->container->name;
pGraph g_;
g = &g_;
instanceName = boost::none;
boost::get_property(g_, boost::graph_name) = name;
begin_v = add_vertex("_BEGIN_", VertexType::PARSER);
end_v = add_vertex("_END_", VertexType::PARSER);
accept_v = add_vertex("accept", VertexType::DEFAULT);
parents = {{begin_v, new EdgeUnconditional()}};

visit(it.second->getNode());

for (auto parent : defParents)
add_edge(parent.first, accept_v, parent.second->label());
add_edge(accept_v, end_v, (new EdgeUnconditional())->label());
BUG_CHECK(g_.is_root(), "Invalid graph");
GraphAttributeSetter()(g_);
writeGraphToFile(g_, name);

}
}
return false;
for (auto it : block->constantValue) {
if (it.second->is<IR::ParserBlock>()) {
auto name = it.second->to<IR::ParserBlock>()->container->name;
pGraph g_;
g = &g_;
instanceName = boost::none;
boost::get_property(g_, boost::graph_name) = name;
begin_v = add_vertex("_BEGIN_", VertexType::PARSER);
end_v = add_vertex("_END_", VertexType::PARSER);
accept_v = add_vertex("accept", VertexType::DEFAULT);
parents = {{begin_v, new EdgeUnconditional()}};

visit(it.second->getNode());

for (auto parent : defParents)
add_edge(parent.first, accept_v, parent.second->label());
add_edge(accept_v, end_v, (new EdgeUnconditional())->label());
BUG_CHECK(g_.is_root(), "Invalid graph");
GraphAttributeSetter()(g_);
writeGraphToFile(g_, name);
}
}
return false;
}

bool ParserGraphs::preorder(const IR::ParserBlock *block) {
Expand All @@ -238,58 +237,58 @@ bool ParserGraphs::preorder(const IR::ParserBlock *block) {
}

bool ParserGraphs::preorder(const IR::P4Parser *pars) {
for (auto state : pars->states) {
if(state->name == IR::ParserState::start) {
visit(state);
break;
}
}
return false;
for (auto state : pars->states) {
if (state->name == IR::ParserState::start) {
visit(state);
break;
}
}
return false;
}

bool ParserGraphs::preorder(const IR::ParserState *state) {
std::stringstream sstream;

if (state->selectExpression != nullptr) {
auto v = add_and_connect_vertex(state->name, VertexType::HEADER);
parents.clear();

if (state->selectExpression->is<IR::PathExpression>()) {
parents = {{v, new EdgeSwitch(new IR::DefaultExpression())}};
auto stpath = state->selectExpression->to<IR::PathExpression>();
auto decl = refMap->getDeclaration(stpath->path, true);
auto nstate = decl->to<IR::ParserState>();
if (nstate->name == IR::ParserState::accept) {
defParents.emplace_back(v, new EdgeSwitch(new IR::DefaultExpression()));
return false;
}
visit(decl->to<IR::ParserState>());
} else if (state->selectExpression->is<IR::SelectExpression>()) {
auto se = state->selectExpression->to<IR::SelectExpression>();
for (auto sc : se->selectCases) {
auto key = sc->keyset;
auto pexpr = sc->state;
key->dbprint(sstream);
mpz_class value, mask;
unsigned bytes = combine(sc->keyset, se->select, value, mask);
parents = {{v, new EdgeSelect(stringRepr(value, bytes))}};
auto decl = refMap->getDeclaration(pexpr->path, true);
auto nstate = decl->to<IR::ParserState>();
if (nstate->name == IR::ParserState::accept) {
defParents.emplace_back(v, new EdgeSwitch(new IR::DefaultExpression()));
continue;
}
visit(nstate);
}
} else {
LOG1("unexpected selectExpression");
}

} else {
LOG1("default case");
}

return false;
std::stringstream sstream;

if (state->selectExpression != nullptr) {
auto v = add_and_connect_vertex(state->name, VertexType::HEADER);
parents.clear();

if (state->selectExpression->is<IR::PathExpression>()) {
parents = {{v, new EdgeSwitch(new IR::DefaultExpression())}};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these edge classes are not visible from this file; this will break non-unified builds

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what you said? I am pretty new to c++
Can you give little more details, plz. ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well there is no EdgeSwitch declaration visible from this file. It is in controls.cpp. I believe that this is only compiling because we use a unified-build by default, which merges all the source files in this directory before compiling them. Some people build this code in a non-unified way, it which case it would fail. You should try compiling without a unified build (run cmake with UNIFIED_COMPILATION_ENABLED set to false). It really should be a regression for this repo IMO but it's not.

auto stpath = state->selectExpression->to<IR::PathExpression>();
auto decl = refMap->getDeclaration(stpath->path, true);
auto nstate = decl->to<IR::ParserState>();
if (nstate->name == IR::ParserState::accept) {
defParents.emplace_back(v, new EdgeSwitch(new IR::DefaultExpression()));
return false;
}
visit(decl->to<IR::ParserState>());
} else if (state->selectExpression->is<IR::SelectExpression>()) {
auto se = state->selectExpression->to<IR::SelectExpression>();
for (auto sc : se->selectCases) {
auto key = sc->keyset;
auto pexpr = sc->state;
key->dbprint(sstream);
mpz_class value, mask;
unsigned bytes = combine(sc->keyset, se->select, value, mask);
parents = {{v, new EdgeSelect(stringRepr(value, bytes))}};
auto decl = refMap->getDeclaration(pexpr->path, true);
auto nstate = decl->to<IR::ParserState>();
if (nstate->name == IR::ParserState::accept) {
defParents.emplace_back(v, new EdgeSwitch(new IR::DefaultExpression()));
continue;
}
visit(nstate);
}
} else {
LOG1("unexpected selectExpression");
}

} else {
LOG1("default case");
}

return false;
}

} // namespace graphs