diff --git a/frontends/common/resolveReferences/resolveReferences.cpp b/frontends/common/resolveReferences/resolveReferences.cpp index 77d1c05964..4310887b44 100644 --- a/frontends/common/resolveReferences/resolveReferences.cpp +++ b/frontends/common/resolveReferences/resolveReferences.cpp @@ -448,7 +448,11 @@ bool ResolveReferences::preorder(const IR::P4Parser *p) { bool ResolveReferences::preorder(const IR::Function *function) { refMap->usedName(function->name.name); - checkShadowing(function); + return true; +} + +bool ResolveReferences::preorder(const IR::Method* method) { + refMap->usedName(method->name.name); return true; } diff --git a/frontends/common/resolveReferences/resolveReferences.h b/frontends/common/resolveReferences/resolveReferences.h index bb6501a82b..82ac9244a5 100644 --- a/frontends/common/resolveReferences/resolveReferences.h +++ b/frontends/common/resolveReferences/resolveReferences.h @@ -150,6 +150,7 @@ class ResolveReferences : public Inspector, private ResolutionContext { bool preorder(const IR::P4Parser *t) override; bool preorder(const IR::P4Action *t) override; bool preorder(const IR::Function *t) override; + bool preorder(const IR::Method *t) override; bool preorder(const IR::TableProperties *t) override; bool preorder(const IR::Type_Method *t) override; bool preorder(const IR::ParserState *t) override; diff --git a/frontends/p4/parseAnnotations.cpp b/frontends/p4/parseAnnotations.cpp index b6d8ab1245..d9ec1ed83d 100644 --- a/frontends/p4/parseAnnotations.cpp +++ b/frontends/p4/parseAnnotations.cpp @@ -28,6 +28,9 @@ ParseAnnotations::HandlerMap ParseAnnotations::standardHandlers() { PARSE_EMPTY(IR::Annotation::optionalAnnotation), PARSE_EMPTY(IR::Annotation::pureAnnotation), PARSE_EMPTY(IR::Annotation::noSideEffectsAnnotation), + PARSE_EMPTY(IR::Annotation::localStateAnnotation), + PARSE_EMPTY(IR::Annotation::packetStateAnnotation), + PARSE(IR::Annotation::localIndexedStateAnnotation, Expression), PARSE_EMPTY("disable_optimization"_cs), PARSE_EMPTY("unroll"_cs), PARSE_EMPTY("nounroll"_cs), diff --git a/ir/annotations.cpp b/ir/annotations.cpp index 2401dbdba5..aff29e35de 100644 --- a/ir/annotations.cpp +++ b/ir/annotations.cpp @@ -33,6 +33,9 @@ const cstring IR::Annotation::deprecatedAnnotation = "deprecated"_cs; const cstring IR::Annotation::synchronousAnnotation = "synchronous"_cs; const cstring IR::Annotation::pureAnnotation = "pure"_cs; const cstring IR::Annotation::noSideEffectsAnnotation = "noSideEffects"_cs; +const cstring IR::Annotation::localStateAnnotation = "localState"_cs; +const cstring IR::Annotation::packetStateAnnotation = "packetState"_cs; +const cstring IR::Annotation::localIndexedStateAnnotation = "localIndexedState"_cs; const cstring IR::Annotation::noWarnAnnotation = "noWarn"_cs; const cstring IR::Annotation::matchAnnotation = "match"_cs; const cstring IR::Annotation::fieldListAnnotation = "field_list"_cs; diff --git a/ir/base.def b/ir/base.def index 101515ecf0..3aa72acc69 100644 --- a/ir/base.def +++ b/ir/base.def @@ -285,11 +285,14 @@ class Annotation { static const cstring synchronousAnnotation; /// Synchronous annotation. static const cstring pureAnnotation; /// extern function/method annotation. static const cstring noSideEffectsAnnotation; /// extern function/method annotation. - static const cstring noWarnAnnotation; /// noWarn annotation. + static const cstring localStateAnnotation; /// extern function/method annotation. + static const cstring packetStateAnnotation; /// extern function/method annotation. + static const cstring localIndexedStateAnnotation; /// extern function/method annotation. static const cstring matchAnnotation; /// Match annotation (for value sets). static const cstring fieldListAnnotation; /// Used for recirculate, etc. static const cstring debugLoggingAnnotation; /// Used by compiler implementer to limit debug log to the annotated IR context. static const cstring disableOptimizationAnnotation; /// annotation to disable certain optimization + static const cstring noWarnAnnotation; /// noWarn annotation. toString{ return absl::StrCat("@", name); } validate{ diff --git a/p4include/bmv2/psa.p4 b/p4include/bmv2/psa.p4 index 845afef8eb..6eaaf2560e 100644 --- a/p4include/bmv2/psa.p4 +++ b/p4include/bmv2/psa.p4 @@ -371,6 +371,7 @@ extern bool psa_recirculate(in psa_egress_output_metadata_t istd, * because, if you follow this advice, your program will behave the * same way when assert statements are removed. */ +@localState extern void assert(in bool check); /*** @@ -407,6 +408,7 @@ extern void assert(in bool check); * condition ever evaluates to false when operating in a network, it * is likely that your assumption was wrong, and should be reexamined. */ +@localState extern void assume(in bool check); // BEGIN:Match_kinds @@ -542,13 +544,15 @@ extern Checksum { /// time the object is instantiated, that is, whenever the parser or control /// containing the Checksum object are applied. /// All state maintained by the Checksum object is independent per packet. + @packetState void clear(); /// Add data to checksum + @packetState void update(in T data); /// Get checksum for data added (and not removed) since last clear - @noSideEffects + @packetState @noSideEffects W get(); } // END:Checksum_extern @@ -566,29 +570,33 @@ extern InternetChecksum { /// initialized as if clear() had been called on it, once for each /// time the parser or control it is instantiated within is /// executed. All state maintained by it is independent per packet. + @packetState void clear(); /// Add data to checksum. data must be a multiple of 16 bits long. + @packetState void add(in T data); /// Subtract data from existing checksum. data must be a multiple of /// 16 bits long. + @packetState void subtract(in T data); /// Get checksum for data added (and not removed) since last clear - @noSideEffects + @packetState @noSideEffects bit<16> get(); /// Get current state of checksum computation. The return value is /// only intended to be used for a future call to the set_state /// method. - @noSideEffects + @packetState @noSideEffects bit<16> get_state(); /// Restore the state of the InternetChecksum instance to one /// returned from an earlier call to the get_state method. This /// state could have been returned from the same instance of the /// InternetChecksum extern, or a different one. + @packetState void set_state(in bit<16> checksum_state); } // END:InternetChecksum_extern @@ -608,6 +616,7 @@ enum PSA_CounterType_t { @noWarn("unused") extern Counter { Counter(bit<32> n_counters, PSA_CounterType_t type); + @localIndexedState(index) void count(in S index); } // END:Counter_extern @@ -616,6 +625,7 @@ extern Counter { @noWarn("unused") extern DirectCounter { DirectCounter(PSA_CounterType_t type); + @localState void count(); } // END:DirectCounter_extern @@ -640,11 +650,13 @@ extern Meter { // Use this method call to perform a color aware meter update (see // RFC 2698). The color of the packet before the method call was // made is specified by the color parameter. + @localIndexedState(index) PSA_MeterColor_t execute(in S index, in PSA_MeterColor_t color); // Use this method call to perform a color blind meter update (see // RFC 2698). It may be implemented via a call to execute(index, // MeterColor_t.GREEN), which has the same behavior. + @localIndexedState(index) PSA_MeterColor_t execute(in S index); } // END:Meter_extern @@ -653,7 +665,9 @@ extern Meter { extern DirectMeter { DirectMeter(PSA_MeterType_t type); // See the corresponding methods for extern Meter. + @localState PSA_MeterColor_t execute(in PSA_MeterColor_t color); + @localState PSA_MeterColor_t execute(); } // END:DirectMeter_extern @@ -667,8 +681,9 @@ extern Register { /// initial_value. Register(bit<32> size, T initial_value); - @noSideEffects + @localIndexedState(index) @noSideEffects T read (in S index); + @localIndexedState(index) void write (in S index, in T value); } // END:Register_extern @@ -682,6 +697,7 @@ extern Random { /// arguments to such values if they wish to maximize portability. Random(T min, T max); + @localState T read(); } // END:Random_extern @@ -706,6 +722,7 @@ extern ActionSelector { // BEGIN:Digest_extern extern Digest { Digest(); /// define a digest stream to the control plane + @localState void pack(in T data); /// emit data into the stream } // END:Digest_extern diff --git a/p4include/v1model.p4 b/p4include/v1model.p4 index f285b9669d..7748e95c93 100644 --- a/p4include/v1model.p4 +++ b/p4include/v1model.p4 @@ -159,6 +159,7 @@ extern counter * size-1]. If index >= size, no counter state will be * updated. */ + @localIndexedState(index) #if V1MODEL_VERSION >= 20200408 void count(in I index); #else @@ -195,6 +196,7 @@ extern direct_counter { * packets, regardless of whether the count() method is called in * the body of that action. */ + @localState void count(); } @@ -243,6 +245,7 @@ extern meter * range, the final value of result is not specified, * and should be ignored by the caller. */ + @localIndexedState(index) #if V1MODEL_VERSION >= 20200408 void execute_meter(in I index, out T result); #else @@ -283,6 +286,7 @@ extern direct_meter { * color YELLOW, and 2 for color RED (see RFC 2697 * and RFC 2698 for the meaning of these colors). */ + @noSideEffects @localState void read(out T result); } @@ -317,7 +321,7 @@ extern register * value of result is not specified, and should be * ignored by the caller. */ - @noSideEffects + @noSideEffects @localIndexedState(index) #if V1MODEL_VERSION >= 20200408 void read(out T result, in I index); #else @@ -345,6 +349,7 @@ extern register * parameter's value is written into the register * array element specified by index. */ + @localIndexedState(index) #if V1MODEL_VERSION >= 20200408 void write(in I index, in T value); #else @@ -364,6 +369,7 @@ extern action_profile { * * @param T Must be a type bit */ +@localState extern void random(out T result, in T lo, in T hi); /*** @@ -389,6 +395,7 @@ extern void random(out T result, in T lo, in T hi); * The BMv2 implementation of the v1model architecture ignores the * value of the receiver parameter. */ +@packetState extern void digest(in bit<32> receiver, in T data); enum HashAlgorithm { @@ -403,6 +410,7 @@ enum HashAlgorithm { } @deprecated("Please use mark_to_drop(standard_metadata) instead.") +@packetState extern void mark_to_drop(); /*** @@ -480,6 +488,7 @@ extern Checksum16 { * may be supported). Must be a compile-time * constant. */ +@packetState extern void verify_checksum(in bool condition, in T data, in O checksum, HashAlgorithm algo); /*** @@ -513,6 +522,7 @@ extern void update_checksum(in bool condition, in T data, inout O checksum * Calling verify_checksum_with_payload is only supported in the * VerifyChecksum control. */ +@packetState extern void verify_checksum_with_payload(in bool condition, in T data, in O checksum, HashAlgorithm algo); /** @@ -524,7 +534,7 @@ extern void verify_checksum_with_payload(in bool condition, in T data, in * Calling update_checksum_with_payload is only supported in the * ComputeChecksum control. */ -@noSideEffects +@noSideEffects @packetState extern void update_checksum_with_payload(in bool condition, in T data, inout O checksum, HashAlgorithm algo); /*** @@ -536,6 +546,7 @@ extern void update_checksum_with_payload(in bool condition, in T data, ino */ extern void clone(in CloneType type, in bit<32> session); +@packetState @deprecated("Please use 'resubmit_preserving_field_list' instead") extern void resubmit(in T data); /*** @@ -572,8 +583,10 @@ extern void resubmit(in T data); * and preserve fields x and y of the user metadata. Calling * resubmit_preserving_field_list(2) will only preserve field y. */ +@packetState extern void resubmit_preserving_field_list(bit<8> index); +@packetState @deprecated("Please use 'recirculate_preserving_field_list' instead") extern void recirculate(in T data); /*** @@ -598,8 +611,10 @@ extern void recirculate(in T data); * are preserved. See the v1model architecture documentation (Note 1) * for more details. */ +@packetState extern void recirculate_preserving_field_list(bit<8> index); +@packetState @deprecated("Please use 'clone_preserving_field_list' instead") extern void clone3(in CloneType type, in bit<32> session, in T data); @@ -637,8 +652,10 @@ extern void clone3(in CloneType type, in bit<32> session, in T data); * control, only the last clone session and index are used. See the * v1model architecture documentation (Note 1) for more details. */ +@packetState extern void clone_preserving_field_list(in CloneType type, in bit<32> session, bit<8> index); +@packetState extern void truncate(in bit<32> length); /*** @@ -665,6 +682,7 @@ extern void truncate(in bit<32> length); * because, if you follow this advice, your program will behave the * same way when assert statements are removed. */ +@localState extern void assert(in bool check); /*** @@ -700,6 +718,7 @@ extern void assert(in bool check); * condition ever evaluates to false when operating in a network, it * is likely that your assumption was wrong, and should be reexamined. */ +@localState extern void assume(in bool check); /* @@ -707,7 +726,9 @@ extern void assume(in bool check); * Example: log_msg("User defined message"); * or log_msg("Value1 = {}, Value2 = {}",{value1, value2}); */ +@localState extern void log_msg(string msg); +@localState extern void log_msg(string msg, in T data); // The name 'standard_metadata' is reserved