diag_matcher.hpp 2.96 KB
Newer Older
1 2 3
// Copyright (C) 2018-2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
4 5 6 7 8 9 10 11

#pragma once
#include"gna-api.h"
#include "nnet_base_matcher.hpp"
#include "quantization/quantization.h"

class DiagLayerMatcher : public ::testing::MatcherInterface<const intel_nnet_type_t*> {
    bool matchInserted;
12 13
    int  matchQuantity;
    mutable int  actualQuantity;
14
public:
15 16 17 18
    DiagLayerMatcher(bool matchInserted, int matchQuantity) : matchInserted(matchInserted), matchQuantity(matchQuantity) {}
    bool MatchAndExplain(const intel_nnet_type_t *foo, ::testing::MatchResultListener *listener) const override {
        if (foo == nullptr)
            return false;
19
        actualQuantity = 0;
20 21 22 23 24 25
        for(int i = 0; i < foo->nLayers; i++) {
            if (foo->pLayers[i].nLayerKind != INTEL_AFFINE_DIAGONAL) continue;
            // diagonal layer has to have 1 for weights and 0 for biases

            auto diag = (intel_affine_func_t*)foo->pLayers[i].pLayerStruct;
            bool bWeightsOK = true;
26 27

            int beforePadding = -1;
28
            for (int j =0; j < foo->pLayers[i].nOutputRows; j++) {
29
                auto weights = (int16_t*)diag->pWeights;
30
                auto biases = (int32_t*)diag->pBiases;
31
                // identity matrix transformed to 16384 values
32
                if (weights[j] != MAX_VAL_2B_WEIGHT || biases[j] != 0) {
33 34 35 36 37 38 39 40 41 42
                    beforePadding = j;
                    break;
                }
            }

            for (int j = beforePadding; j < foo->pLayers[i].nOutputRows; j++) {
                auto weights = (int16_t*)diag->pWeights;
                auto biases = (int32_t*)diag->pBiases;
                // identity matrix transformed to 16384 values
                if (weights[j] != 0 || biases[j] != 0) {
43 44 45 46
                    bWeightsOK = false;
                    break;
                }
            }
47 48 49

            // if all weights are zero, or zero value doesn't look like padding
            if (!bWeightsOK && beforePadding == -1) continue;
50 51 52 53 54 55 56 57
            actualQuantity ++;
        }
        // means any quantity > 0
        if (matchQuantity == -1) {
            if (actualQuantity > 0)
                return matchInserted;
            else
                return !matchInserted;
58
        }
59 60 61 62 63
        if (actualQuantity == matchQuantity)
            return matchInserted;
        else
            return !matchInserted;

64 65
    };
    void DescribeTo(::std::ostream *os) const override {
66 67 68
        *os << "should "<< (matchInserted ? "" : "not ") << "have "
            << (matchQuantity == -1 ? "any" : std::to_string(matchQuantity))
            << " Identity Diagonal Primitive primitive as part of nnet structure, but was " << actualQuantity;
69 70 71 72 73 74 75 76 77 78
    }
};

inline ::testing::Matcher<const intel_nnet_type_t*> HasDiagonalLayer(bool matchInserted = false, int matchQuantity = -1) {
    std::unique_ptr<NNetComponentMatcher> c (new NNetComponentMatcher());
    c->add(new DiagLayerMatcher(matchInserted, matchQuantity));
    return ::testing::MakeMatcher(c.release());
}