215 : translate(translate), collect(collect), graph(graph), structure(structure) {}
226 ingressParserResidualChecksumDecls, egressParserResidualChecksumDecls;
228 unsigned residualChecksumCnt = 0;
237 struct CollectExtractMembers :
public Inspector {
239 : stateToExtracts(stateToExtracts), extractToState(extractToState) {}
244 void postorder(
const IR::MethodCallStatement *statement)
override {
245 auto *call = statement->methodCall;
247 auto *method = call->method->to<IR::Member>();
248 auto *state = findContext<IR::ParserState>();
250 if (method && method->member ==
"extract") {
251 for (
auto m : *(call->arguments)) {
252 stateToExtracts[state].push_back(m->expression);
253 extractToState[m->expression] = state;
260 CollectExtractMembers cem(stateToExtracts, extractToState);
262 return Inspector::init_apply(root);
266 static bool equiv(
const IR::Expression *a,
const IR::Expression *b) {
267 if (a == b)
return true;
268 if (
typeid(*a) !=
typeid(*b))
return false;
269 if (
auto ma = a->to<IR::Member>()) {
270 auto mb = b->to<IR::Member>();
271 return ma->member == mb->member && equiv(ma->expr, mb->expr);
273 if (
auto pa = a->to<IR::PathExpression>()) {
274 auto pb = b->to<IR::PathExpression>();
275 return pa->path->name == pb->path->name;
280 static bool belongsTo(
const IR::Member *a,
const IR::Member *b) {
281 if (!a || !b)
return false;
284 if (equiv(a, b))
return true;
287 if (a->type->is<IR::Type::Bits>()) {
288 if (equiv(a->expr, b))
return true;
299 const IR::Path *replaceSrcInfo(
const IR::Path *path,
const Util::SourceInfo &srcInfo) {
300 if (!srcInfo.isValid())
return path;
302 auto *newPath = path->clone();
303 newPath->srcInfo = srcInfo;
304 newPath->name =
IR::ID(srcInfo, newPath->name.name, newPath->name.originalName);
309 const IR::PathExpression *replaceSrcInfo(
const IR::PathExpression *pe,
311 if (!srcInfo.isValid())
return pe;
313 auto *newPE = pe->clone();
314 newPE->srcInfo = srcInfo;
315 newPE->path = replaceSrcInfo(newPE->path, srcInfo);
320 const IR::Member *replaceSrcInfo(
const IR::Member *member,
const Util::SourceInfo &srcInfo) {
321 if (!srcInfo.isValid())
return member;
323 auto *newMember = member->clone();
324 newMember->srcInfo = srcInfo;
326 if (
const auto *exprMember = newMember->expr->to<IR::Member>()) {
327 newMember->expr = replaceSrcInfo(exprMember, srcInfo);
328 }
else if (
const auto *exprPathExpression = newMember->expr->to<IR::PathExpression>()) {
329 newMember->expr = replaceSrcInfo(exprPathExpression, srcInfo);
335 void implementVerifyChecksum(
const IR::MethodCallStatement *vc,
const IR::ParserState *state) {
336 cstring stateName = state->name;
337 auto &extracts = stateToExtracts[state];
339 auto mc = vc->methodCall->to<IR::MethodCallExpression>();
341 auto fieldlist = mc->arguments->at(1)->expression;
342 auto destfield = mc->arguments->at(2)->expression;
347 const IR::Declaration *decl =
nullptr;
349 if (verifyDeclarationMap.count(vc)) {
350 decl = verifyDeclarationMap.at(vc);
352 decl = createChecksumDeclaration(structure, vc);
353 verifyDeclarationMap[vc] = decl;
354 structure->ingressParserDeclarations.push_back(decl);
357 if (fieldlist->is<IR::ListExpression>()) {
358 for (
auto f : fieldlist->to<IR::ListExpression>()->components) {
359 for (
auto extract : extracts) {
360 if (belongsTo(f->to<IR::Member>(), extract->to<IR::Member>())) {
361 if (
const auto *member = f->to<IR::Member>()) {
362 f = replaceSrcInfo(member, state->srcInfo);
364 auto addCall =
new IR::MethodCallStatement(
366 new IR::MethodCallExpression(
368 new IR::Member(
new IR::PathExpression(decl->name),
"add"),
372 structure->ingressParserStatements[stateName].push_back(addCall);
373 translate->ingressVerifyDeclToStates[decl].insert(state->name);
377 }
else if (fieldlist->is<IR::StructExpression>()) {
378 for (
auto fld : fieldlist->to<IR::StructExpression>()->components) {
379 auto f = fld->expression;
380 for (
auto extract : extracts) {
381 if (belongsTo(f->to<IR::Member>(), extract->to<IR::Member>())) {
382 if (
const auto *member = f->to<IR::Member>()) {
383 f = replaceSrcInfo(member, state->srcInfo);
385 auto addCall =
new IR::MethodCallStatement(
387 new IR::MethodCallExpression(
389 new IR::Member(
new IR::PathExpression(decl->name),
"add"),
393 structure->ingressParserStatements[stateName].push_back(addCall);
394 translate->ingressVerifyDeclToStates[decl].insert(state->name);
395 LOG1(
"B: Adding add call: " << addCall);
401 auto *destfieldAdj = destfield;
402 if (
const auto *member = destfield->to<IR::Member>()) {
403 destfieldAdj = replaceSrcInfo(member, state->srcInfo);
405 for (
auto extract : extracts) {
406 if (belongsTo(destfieldAdj->to<IR::Member>(), extract->to<IR::Member>())) {
407 BUG_CHECK(decl,
"No fields have been added before verify?");
409 auto addCall =
new IR::MethodCallStatement(
411 new IR::MethodCallExpression(
412 mc->srcInfo,
new IR::Member(
new IR::PathExpression(decl->name),
"add"),
416 structure->ingressParserStatements[stateName].push_back(addCall);
417 translate->ingressVerifyDeclToStates[decl].insert(state->name);
423 const IR::ParserState *state) {
426 auto descendants = graph->get_all_descendants(state);
428 for (
auto d : descendants) {
429 auto &extracts = stateToExtracts[d];
430 for (
auto m : extracts) rv.insert(m);
436 void implementParserResidualChecksum(
const IR::MethodCallStatement *rc,
437 const IR::ParserState *state,
438 const std::vector<gress_t> &parserUpdateLocations,
439 const std::vector<gress_t> &deparserUpdateLocations) {
440 cstring stateName = state->name;
441 auto &extracts = stateToExtracts[state];
443 auto mc = rc->methodCall->to<IR::MethodCallExpression>();
445 auto condition = mc->arguments->at(0)->expression;
446 auto fieldlist = mc->arguments->at(1)->expression;
447 auto destfield = mc->arguments->at(2)->expression;
448 if (parserUpdateLocations.size() == 1 && parserUpdateLocations[0] == INGRESS &&
449 deparserUpdateLocations.size() == 1 && deparserUpdateLocations[0] == EGRESS) {
450 translate->needBridging.insert(destfield);
453 if (!translate->residualChecksums.count(destfield)) {
454 auto *compilerMetadataPath =
new IR::PathExpression(COMPILER_META);
455 auto *compilerMetadataDecl =
const_cast<IR::Type_Struct *
>(
456 structure->type_declarations.at(
"compiler_generated_metadata_t"_cs)
457 ->to<IR::Type_Struct>());
458 compilerMetadataDecl->annotations = {
459 new IR::Annotation(
IR::ID(
"__compiler_generated"), {})};
461 std::stringstream residualFieldName;
462 residualFieldName <<
"residual_checksum_";
463 residualFieldName << residualChecksumCnt++;
465 auto *residualChecksum =
new IR::Member(IR::Type::Bits::get(16), compilerMetadataPath,
466 residualFieldName.str().c_str());
468 compilerMetadataDecl->fields.push_back(
469 new IR::StructField(residualFieldName.str().c_str(), IR::Type::Bits::get(16)));
471 translate->residualChecksums[destfield] = residualChecksum;
472 translate->destToGressToState[destfield][deparserUpdateLocations[0]] = state;
475 for (
auto location : parserUpdateLocations) {
476 std::vector<const IR::Declaration *> *parserDeclarations =
nullptr;
477 std::vector<const IR::StatOrDecl *> *parserStatements =
nullptr;
480 *parserResidualChecksumDecls =
nullptr;
482 if (location == INGRESS) {
483 parserDeclarations = &structure->ingressParserDeclarations;
484 parserStatements = &structure->ingressParserStatements[stateName];
485 parserResidualChecksumDecls = &ingressParserResidualChecksumDecls;
486 }
else if (location == EGRESS) {
487 parserDeclarations = &structure->egressParserDeclarations;
488 parserStatements = &structure->egressParserStatements[stateName];
489 parserResidualChecksumDecls = &egressParserResidualChecksumDecls;
492 IR::Declaration_Instance *decl =
nullptr;
493 auto it = parserResidualChecksumDecls->find(rc);
494 if (it == parserResidualChecksumDecls->end()) {
495 decl = createChecksumDeclaration(structure, rc);
496 parserDeclarations->push_back(decl);
497 (*parserResidualChecksumDecls)[rc] = decl;
499 decl = parserResidualChecksumDecls->at(rc);
501 const IR::Expression *constant =
nullptr;
502 for (
auto extract : extracts) {
503 std::vector<const IR::Expression *> exprList;
504 if (fieldlist->is<IR::ListExpression>()) {
505 for (
auto f : fieldlist->to<IR::ListExpression>()->components) {
506 if (f->is<IR::Constant>()) {
508 }
else if (belongsTo(f->to<IR::Member>(), extract->to<IR::Member>())) {
510 exprList.emplace_back(constant);
516 exprList.emplace_back(f);
522 }
else if (fieldlist->is<IR::StructExpression>()) {
523 for (
auto fld : fieldlist->to<IR::StructExpression>()->components) {
524 auto f = fld->expression;
525 if (f->is<IR::Constant>()) {
527 }
else if (belongsTo(f->to<IR::Member>(), extract->to<IR::Member>())) {
529 exprList.emplace_back(constant);
535 exprList.emplace_back(f);
542 for (
auto e : exprList) {
543 auto subtractCall =
new IR::MethodCallStatement(
545 new IR::MethodCallExpression(
547 new IR::Member(
new IR::PathExpression(decl->name),
"subtract"),
551 parserStatements->push_back(subtractCall);
554 if (belongsTo(destfield->to<IR::Member>(), extract->to<IR::Member>())) {
555 auto subtractCall =
new IR::MethodCallStatement(
557 new IR::MethodCallExpression(
559 new IR::Member(
new IR::PathExpression(decl->name),
"subtract"),
563 parserStatements->push_back(subtractCall);
564 auto *residualChecksum = translate->residualChecksums.at(destfield);
566 auto *deposit =
new IR::MethodCallStatement(
568 new IR::MethodCallExpression(
570 new IR::Member(
new IR::PathExpression(decl->name),
571 "subtract_all_and_deposit"),
576 ->checksumDepositToHeader[location][extract->to<IR::Member>()->member] =
578 if (
auto boolLiteral = condition->to<IR::BoolLiteral>()) {
579 if (!boolLiteral->value) {
586 auto payloadFields = collectResidualChecksumPayloadFields(state);
587 translate->residualChecksumPayloadFields[destfield] = payloadFields;
594 void postorder(
const IR::ParserState *state)
override {
597 for (
auto *vc : collect->verifyChecksums) {
598 implementVerifyChecksum(vc, state);
601 for (
auto *rc : collect->residualChecksums) {
602 implementParserResidualChecksum(rc, state, collect->parserUpdateLocations.at(rc),
603 collect->deparserUpdateLocations.at(rc));