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);
456 new IR::Annotations({
new IR::Annotation(
IR::ID(
"__compiler_generated"), {})});
458 auto *compilerMetadataDecl =
const_cast<IR::Type_Struct *
>(
459 structure->type_declarations.at(
"compiler_generated_metadata_t"_cs)
460 ->to<IR::Type_Struct>());
461 compilerMetadataDecl->annotations = cgAnnotation;
463 std::stringstream residualFieldName;
464 residualFieldName <<
"residual_checksum_";
465 residualFieldName << residualChecksumCnt++;
467 auto *residualChecksum =
new IR::Member(IR::Type::Bits::get(16), compilerMetadataPath,
468 residualFieldName.str().c_str());
470 compilerMetadataDecl->fields.push_back(
471 new IR::StructField(residualFieldName.str().c_str(), IR::Type::Bits::get(16)));
473 translate->residualChecksums[destfield] = residualChecksum;
474 translate->destToGressToState[destfield][deparserUpdateLocations[0]] = state;
477 for (
auto location : parserUpdateLocations) {
478 std::vector<const IR::Declaration *> *parserDeclarations =
nullptr;
479 std::vector<const IR::StatOrDecl *> *parserStatements =
nullptr;
482 *parserResidualChecksumDecls =
nullptr;
484 if (location == INGRESS) {
485 parserDeclarations = &structure->ingressParserDeclarations;
486 parserStatements = &structure->ingressParserStatements[stateName];
487 parserResidualChecksumDecls = &ingressParserResidualChecksumDecls;
488 }
else if (location == EGRESS) {
489 parserDeclarations = &structure->egressParserDeclarations;
490 parserStatements = &structure->egressParserStatements[stateName];
491 parserResidualChecksumDecls = &egressParserResidualChecksumDecls;
494 IR::Declaration_Instance *decl =
nullptr;
495 auto it = parserResidualChecksumDecls->find(rc);
496 if (it == parserResidualChecksumDecls->end()) {
497 decl = createChecksumDeclaration(structure, rc);
498 parserDeclarations->push_back(decl);
499 (*parserResidualChecksumDecls)[rc] = decl;
501 decl = parserResidualChecksumDecls->at(rc);
503 const IR::Expression *constant =
nullptr;
504 for (
auto extract : extracts) {
505 std::vector<const IR::Expression *> exprList;
506 if (fieldlist->is<IR::ListExpression>()) {
507 for (
auto f : fieldlist->to<IR::ListExpression>()->components) {
508 if (f->is<IR::Constant>()) {
510 }
else if (belongsTo(f->to<IR::Member>(), extract->to<IR::Member>())) {
512 exprList.emplace_back(constant);
518 exprList.emplace_back(f);
524 }
else if (fieldlist->is<IR::StructExpression>()) {
525 for (
auto fld : fieldlist->to<IR::StructExpression>()->components) {
526 auto f = fld->expression;
527 if (f->is<IR::Constant>()) {
529 }
else if (belongsTo(f->to<IR::Member>(), extract->to<IR::Member>())) {
531 exprList.emplace_back(constant);
537 exprList.emplace_back(f);
544 for (
auto e : exprList) {
545 auto subtractCall =
new IR::MethodCallStatement(
547 new IR::MethodCallExpression(
549 new IR::Member(
new IR::PathExpression(decl->name),
"subtract"),
553 parserStatements->push_back(subtractCall);
556 if (belongsTo(destfield->to<IR::Member>(), extract->to<IR::Member>())) {
557 auto subtractCall =
new IR::MethodCallStatement(
559 new IR::MethodCallExpression(
561 new IR::Member(
new IR::PathExpression(decl->name),
"subtract"),
565 parserStatements->push_back(subtractCall);
566 auto *residualChecksum = translate->residualChecksums.at(destfield);
568 auto *deposit =
new IR::MethodCallStatement(
570 new IR::MethodCallExpression(
572 new IR::Member(
new IR::PathExpression(decl->name),
573 "subtract_all_and_deposit"),
578 ->checksumDepositToHeader[location][extract->to<IR::Member>()->member] =
580 if (
auto boolLiteral = condition->to<IR::BoolLiteral>()) {
581 if (!boolLiteral->value) {
588 auto payloadFields = collectResidualChecksumPayloadFields(state);
589 translate->residualChecksumPayloadFields[destfield] = payloadFields;
596 void postorder(
const IR::ParserState *state)
override {
599 for (
auto *vc : collect->verifyChecksums) {
600 implementVerifyChecksum(vc, state);
603 for (
auto *rc : collect->residualChecksums) {
604 implementParserResidualChecksum(rc, state, collect->parserUpdateLocations.at(rc),
605 collect->deparserUpdateLocations.at(rc));