DAPS: Add intrin specs to nontrin specs
We no longer do intrin specs as a separate stimbuff; rather now we do them as a specifier segment within the pipeline spec of a normal nontrin spec.
This commit is contained in:
@@ -12,6 +12,18 @@
|
||||
namespace smo {
|
||||
namespace device {
|
||||
|
||||
/* Carrier used by the DAP spec parser to pass one parenthesized segment
|
||||
* (e.g. postrin(interest-pc=85) or pcloudAmbience(...)) up the reduction
|
||||
* stack; the spec_body reduction classifies segments and populates the
|
||||
* DeviceAttachmentSpec. Defined here so both the parser header and consumers
|
||||
* of the generated header see the type.
|
||||
*/
|
||||
struct DapSegment
|
||||
{
|
||||
std::string name;
|
||||
std::vector<std::pair<std::string, std::string>> params;
|
||||
};
|
||||
|
||||
class DeviceAttachmentSpec
|
||||
{
|
||||
public:
|
||||
@@ -26,6 +38,8 @@ public:
|
||||
{
|
||||
return deviceIdentifier == other.deviceIdentifier &&
|
||||
sensorType == other.sensorType &&
|
||||
postrin == other.postrin &&
|
||||
negtrin == other.negtrin &&
|
||||
qualeIfaceApi == other.qualeIfaceApi &&
|
||||
stimBuffApi == other.stimBuffApi &&
|
||||
provider == other.provider &&
|
||||
@@ -35,6 +49,15 @@ public:
|
||||
public:
|
||||
std::string deviceIdentifier;
|
||||
char sensorType;
|
||||
/* postrin/negtrin hold the literal segment name ("postrin" /
|
||||
* "negtrin") when present, empty string when the DAP spec omits the
|
||||
* corresponding intrin specifier. Params vectors carry the params from
|
||||
* within the postrin(...)/negtrin(...) segment.
|
||||
*/
|
||||
std::string postrin;
|
||||
std::vector<std::pair<std::string,std::string>> postrinParams;
|
||||
std::string negtrin;
|
||||
std::vector<std::pair<std::string,std::string>> negtrinParams;
|
||||
std::string qualeIfaceApi;
|
||||
std::vector<std::pair<std::string,std::string>> qualeIfaceApiParams;
|
||||
std::string stimBuffApi;
|
||||
@@ -43,12 +66,40 @@ public:
|
||||
std::vector<std::pair<std::string,std::string>> providerParams;
|
||||
std::string deviceSelector;
|
||||
|
||||
static void stringifyParams(
|
||||
std::ostream& os,
|
||||
const std::vector<std::pair<std::string,std::string>>& params)
|
||||
{
|
||||
for (const auto& param : params)
|
||||
{
|
||||
os << param.first;
|
||||
if (!param.second.empty()) {
|
||||
os << "=" << param.second;
|
||||
}
|
||||
os << " ";
|
||||
}
|
||||
}
|
||||
|
||||
std::string stringify() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Device Identifier: " << deviceIdentifier
|
||||
<< ", Sensor Type: " << sensorType
|
||||
<< ", QualeIface API: " << qualeIfaceApi << ", QualeIface API Params: (";
|
||||
<< ", Sensor Type: " << sensorType;
|
||||
|
||||
if (!postrin.empty())
|
||||
{
|
||||
os << ", Postrin Params: (";
|
||||
stringifyParams(os, postrinParams);
|
||||
os << ")";
|
||||
}
|
||||
if (!negtrin.empty())
|
||||
{
|
||||
os << ", Negtrin Params: (";
|
||||
stringifyParams(os, negtrinParams);
|
||||
os << ")";
|
||||
}
|
||||
|
||||
os << ", QualeIface API: " << qualeIfaceApi << ", QualeIface API Params: (";
|
||||
for (const auto& param : qualeIfaceApiParams)
|
||||
{
|
||||
os << param.first;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef SMO_USER_INTRIN_H
|
||||
#define SMO_USER_INTRIN_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace smo {
|
||||
namespace intrin {
|
||||
|
||||
/* Generic intrin threshold pair. 'percentage' holds the raw percentage value
|
||||
* (0-100) when the user specified the threshold in percentage form, else 0.
|
||||
* 'threshold' is always the resolved absolute count (computed against the
|
||||
* relevant capacity parameter, e.g. nDgramsPerFrame, when the input was
|
||||
* percentage-based).
|
||||
*/
|
||||
struct IntrinConfig
|
||||
{
|
||||
uint32_t percentage;
|
||||
uint32_t threshold;
|
||||
};
|
||||
|
||||
} // namespace intrin
|
||||
} // namespace smo
|
||||
|
||||
#endif // SMO_USER_INTRIN_H
|
||||
@@ -27,81 +27,41 @@ struct ParsedThresholdParam
|
||||
bool wasSpecified;
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 2> kPosIntPcParamNames = {
|
||||
"postrin-interest-percentage",
|
||||
"postrin-interest-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 3> kPosIntThrParamNames = {
|
||||
"postrin-interest-threshold",
|
||||
"postrin-interest-thresh",
|
||||
"postrin-interest-thr",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 2> kNegIntPcParamNames = {
|
||||
"negtrin-interest-percentage",
|
||||
"negtrin-interest-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 3> kNegIntThrParamNames = {
|
||||
"negtrin-interest-threshold",
|
||||
"negtrin-interest-thresh",
|
||||
"negtrin-interest-thr",
|
||||
};
|
||||
|
||||
// Short interest-* names: only valid on dedicated postrin/negtrin qualeIfaceApi
|
||||
// lines (docs/design/intrin-thresholds.md); never on sensory qualeIfaceApi specs.
|
||||
inline constexpr std::array<std::string_view, 2> kIntrinInterestPcUnprefixed = {
|
||||
/* Canonical unprefixed threshold-param names that live inside postrin(...) /
|
||||
* negtrin(...) segments attached to a nontrin DAP spec. The "-pc" and
|
||||
* "-percentage" variants are Percentage-unit; the "-thr", "-thresh" and
|
||||
* "-threshold" variants are Absolute-unit.
|
||||
*/
|
||||
inline constexpr std::array<std::string_view, 2> kIntrinInterestPcNames = {
|
||||
"interest-percentage",
|
||||
"interest-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 3> kIntrinInterestThrUnprefixed = {
|
||||
inline constexpr std::array<std::string_view, 3> kIntrinInterestThrNames = {
|
||||
"interest-threshold",
|
||||
"interest-thresh",
|
||||
"interest-thr",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 2> kPosDistPcParamNames = {
|
||||
"postrin-distraction-percentage",
|
||||
"postrin-distraction-pc",
|
||||
inline constexpr std::array<std::string_view, 2> kIntrinDistractionPcNames = {
|
||||
"distraction-percentage",
|
||||
"distraction-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 3> kPosDistThrParamNames = {
|
||||
"postrin-distraction-threshold",
|
||||
"postrin-distraction-thresh",
|
||||
"postrin-distraction-thr",
|
||||
inline constexpr std::array<std::string_view, 3> kIntrinDistractionThrNames = {
|
||||
"distraction-threshold",
|
||||
"distraction-thresh",
|
||||
"distraction-thr",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 2> kNegDistPcParamNames = {
|
||||
"negtrin-distraction-percentage",
|
||||
"negtrin-distraction-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 3> kNegDistThrParamNames = {
|
||||
"negtrin-distraction-threshold",
|
||||
"negtrin-distraction-thresh",
|
||||
"negtrin-distraction-thr",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 8> kStupefactionPcParamNames = {
|
||||
"postrin-stupefaction-percentage",
|
||||
"postrin-stupefaction-pc",
|
||||
"postrin-stupefying-percentage",
|
||||
"postrin-stupefying-pc",
|
||||
inline constexpr std::array<std::string_view, 4> kIntrinStupefactionPcNames = {
|
||||
"stupefaction-percentage",
|
||||
"stupefaction-pc",
|
||||
"stupefying-percentage",
|
||||
"stupefying-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 12> kStupefactionThrParamNames = {
|
||||
"postrin-stupefaction-threshold",
|
||||
"postrin-stupefaction-thresh",
|
||||
"postrin-stupefaction-thr",
|
||||
"postrin-stupefying-threshold",
|
||||
"postrin-stupefying-thresh",
|
||||
"postrin-stupefying-thr",
|
||||
inline constexpr std::array<std::string_view, 6> kIntrinStupefactionThrNames = {
|
||||
"stupefaction-threshold",
|
||||
"stupefaction-thresh",
|
||||
"stupefaction-thr",
|
||||
@@ -110,37 +70,30 @@ inline constexpr std::array<std::string_view, 12> kStupefactionThrParamNames = {
|
||||
"stupefying-thr",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 4> kIntolerablePcParamNames = {
|
||||
"negtrin-intolerable-percentage",
|
||||
"negtrin-intolerable-pc",
|
||||
inline constexpr std::array<std::string_view, 2> kIntrinIntolerablePcNames = {
|
||||
"intolerable-percentage",
|
||||
"intolerable-pc",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 6> kIntolerableThrParamNames = {
|
||||
"negtrin-intolerable-threshold",
|
||||
"negtrin-intolerable-thresh",
|
||||
"negtrin-intolerable-thr",
|
||||
inline constexpr std::array<std::string_view, 3> kIntrinIntolerableThrNames = {
|
||||
"intolerable-threshold",
|
||||
"intolerable-thresh",
|
||||
"intolerable-thr",
|
||||
};
|
||||
|
||||
inline constexpr std::array<std::string_view, 10> kForbiddenUnitlessIntrinParamNames = {
|
||||
"postrin-interest",
|
||||
"negtrin-interest",
|
||||
"postrin-distraction",
|
||||
"negtrin-distraction",
|
||||
"postrin-stupefaction",
|
||||
"postrin-stupefying",
|
||||
/* Unitless stems are invalid — authors must name the unit via -pc/-percentage
|
||||
* or -thr/-thresh/-threshold. We reject bare "interest", "distraction", etc.
|
||||
*/
|
||||
inline constexpr std::array<std::string_view, 5> kForbiddenUnitlessIntrinStems = {
|
||||
"interest",
|
||||
"distraction",
|
||||
"stupefaction",
|
||||
"stupefying",
|
||||
"negtrin-intolerable",
|
||||
"intolerable",
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
bool arrayContains(
|
||||
inline bool arrayContains(
|
||||
const std::array<std::string_view, N>& names,
|
||||
std::string_view candidate)
|
||||
{
|
||||
@@ -152,7 +105,7 @@ bool arrayContains(
|
||||
}
|
||||
|
||||
template <typename NameCollectionT>
|
||||
bool namesContain(
|
||||
inline bool namesContain(
|
||||
const NameCollectionT& names,
|
||||
std::string_view candidate)
|
||||
{
|
||||
@@ -163,101 +116,80 @@ bool namesContain(
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isDedicatedIntrinsQualeIfaceApi(std::string_view qualeIfaceApi)
|
||||
inline bool isKnownIntrinThresholdParamName(std::string_view name)
|
||||
{
|
||||
return qualeIfaceApi == "negtrin" || qualeIfaceApi == "postrin";
|
||||
return namesContain(kIntrinInterestPcNames, name)
|
||||
|| namesContain(kIntrinInterestThrNames, name)
|
||||
|| namesContain(kIntrinDistractionPcNames, name)
|
||||
|| namesContain(kIntrinDistractionThrNames, name)
|
||||
|| namesContain(kIntrinStupefactionPcNames, name)
|
||||
|| namesContain(kIntrinStupefactionThrNames, name)
|
||||
|| namesContain(kIntrinIntolerablePcNames, name)
|
||||
|| namesContain(kIntrinIntolerableThrNames, name);
|
||||
}
|
||||
|
||||
inline bool isKnownIntrinsPipelineParamName(std::string_view name)
|
||||
{
|
||||
return namesContain(kPosIntPcParamNames, name)
|
||||
|| namesContain(kPosIntThrParamNames, name)
|
||||
|| namesContain(kNegIntPcParamNames, name)
|
||||
|| namesContain(kNegIntThrParamNames, name)
|
||||
|| namesContain(kIntrinInterestPcUnprefixed, name)
|
||||
|| namesContain(kIntrinInterestThrUnprefixed, name)
|
||||
|| namesContain(kPosDistPcParamNames, name)
|
||||
|| namesContain(kPosDistThrParamNames, name)
|
||||
|| namesContain(kNegDistPcParamNames, name)
|
||||
|| namesContain(kNegDistThrParamNames, name)
|
||||
|| namesContain(kStupefactionPcParamNames, name)
|
||||
|| namesContain(kStupefactionThrParamNames, name)
|
||||
|| namesContain(kIntolerablePcParamNames, name)
|
||||
|| namesContain(kIntolerableThrParamNames, name)
|
||||
|| name == "passband-count-gt-val"
|
||||
|| name == "passband-count-lt-val";
|
||||
}
|
||||
|
||||
inline bool hasNonEmptyFromStimbuffParam(
|
||||
const std::vector<std::pair<std::string, std::string>>& params)
|
||||
{
|
||||
for (const auto& [key, value] : params)
|
||||
{
|
||||
if (key == "from-stimbuff" && !value.empty())
|
||||
{ return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces dedicated-only intrin specs: intrinsic thresholds and passband
|
||||
* comparators appear only on negtrin/postrin qualeIfaceApi specs with
|
||||
* from-stimbuff. Embedding intrins in other qualeIfaceApi parameter lists is
|
||||
* rejected (docs/design/intrin-thresholds.md).
|
||||
/* Intrin threshold params (interest-*, distraction-*, stupefaction-*,
|
||||
* intolerable-*) must appear only inside postrin(...) / negtrin(...) segments
|
||||
* on a DAP spec, never on qualeIfaceApi params. The deprecated `from-stimbuff`
|
||||
* marker is also rejected — postrin/negtrin are now directly attached to the
|
||||
* nontrin stimbuff they trigger from.
|
||||
*/
|
||||
inline void validateIntrinsQualeApiPolicy(
|
||||
inline void validateNoIntrinParamsOnQualeIface(
|
||||
const std::string& qualeIfaceApi,
|
||||
const std::vector<std::pair<std::string, std::string>>& params)
|
||||
{
|
||||
if (isDedicatedIntrinsQualeIfaceApi(qualeIfaceApi))
|
||||
{
|
||||
if (!hasNonEmptyFromStimbuffParam(params))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"qualeIfaceApi '" + qualeIfaceApi + "' requires a non-empty "
|
||||
"'from-stimbuff=<stimbuffQualeIfaceApi>' parameter naming the "
|
||||
"sensory stimbuff that feeds this intrinsic pipeline.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& [name, value] : params)
|
||||
{
|
||||
(void)value;
|
||||
|
||||
if (isKnownIntrinsPipelineParamName(name))
|
||||
if (isKnownIntrinThresholdParamName(name))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Intrinsic threshold and passband comparator params must not "
|
||||
"appear on qualeIfaceApi '" + qualeIfaceApi + "'. Use dedicated "
|
||||
"negtrin(...) or postrin(...) lines with from-stimbuff=... "
|
||||
"(offending param: '" + name + "').");
|
||||
"Intrinsic threshold param '" + name + "' is not valid on "
|
||||
"qualeIfaceApi '" + qualeIfaceApi + "'. Declare it inside a "
|
||||
"postrin(...) or negtrin(...) segment attached to this DAP "
|
||||
"spec.");
|
||||
}
|
||||
|
||||
if (arrayContains(kForbiddenUnitlessIntrinStems, name))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Intrinsic threshold param '" + name + "' on qualeIfaceApi '"
|
||||
+ qualeIfaceApi + "' is invalid without a unit suffix and "
|
||||
"does not belong on qualeIfaceApi params anyway. Use a "
|
||||
"postrin(...) or negtrin(...) segment with a '-pc' or "
|
||||
"'-thr' suffix.");
|
||||
}
|
||||
|
||||
if (name == "from-stimbuff")
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"'from-stimbuff' is only valid on negtrin(...) or postrin(...) "
|
||||
"qualeIfaceApi specs.");
|
||||
"'from-stimbuff' is no longer supported. postrin(...) and "
|
||||
"negtrin(...) are now attached directly to the nontrin DAP "
|
||||
"spec they trigger from; remove 'from-stimbuff' from "
|
||||
"qualeIfaceApi '" + qualeIfaceApi + "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void validateNoForbiddenUnitlessIntrinParams(
|
||||
/* Accepts only unprefixed threshold names and the two passband modifiers that
|
||||
* are defined on the sensory side. Rejects unit-less stems so that mis-typed
|
||||
* params fail loudly.
|
||||
*/
|
||||
inline void validateIntrinSegmentParams(
|
||||
std::string_view intrinKind, // "postrin" or "negtrin"
|
||||
const std::vector<std::pair<std::string, std::string>>& params)
|
||||
{
|
||||
for (const auto& [name, value] : params)
|
||||
{
|
||||
(void)value;
|
||||
|
||||
if (arrayContains(kForbiddenUnitlessIntrinParamNames, name))
|
||||
if (arrayContains(kForbiddenUnitlessIntrinStems, name))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Intrinsic threshold param '" + name
|
||||
+ "' is invalid without a unit suffix. Use a "
|
||||
"'-percentage'/'-pc' or '-threshold'/'-thresh'/'-thr' variant.");
|
||||
std::string(intrinKind) + "(...) param '" + name + "' is "
|
||||
"invalid without a unit suffix. Use '-pc'/'-percentage' or "
|
||||
"'-thr'/'-thresh'/'-threshold'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user