3ad0d2ccaf84672261aab81acd14de6cde1628b0
[tidl/tidl-api.git] / tidl_api / src / configuration_parser.cpp
1 /******************************************************************************
2  * Copyright (c) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *      * Redistributions of source code must retain the above copyright
8  *        notice, this list of conditions and the following disclaimer.
9  *      * Redistributions in binary form must reproduce the above copyright
10  *        notice, this list of conditions and the following disclaimer in the
11  *        documentation and/or other materials provided with the distribution.
12  *      * Neither the name of Texas Instruments Incorporated nor the
13  *        names of its contributors may be used to endorse or promote products
14  *        derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  *  THE POSSIBILITY OF SUCH DAMAGE.
27  *****************************************************************************/
29 #include <boost/spirit/include/qi.hpp>
30 #include <boost/spirit/include/phoenix_operator.hpp>
31 #include <boost/fusion/include/std_pair.hpp>
33 #include <string>
34 #include <fstream>
35 #include <iostream>
36 #include <algorithm>
37 #include <cctype>
38 #include <utility>
39 #include <map>
41 #include "configuration.h"
43 namespace qi = boost::spirit::qi;
44 namespace ascii = boost::spirit::ascii;
45 namespace ph = boost::phoenix;
47 using namespace tidl;
49 template <typename Iterator>
50 struct ConfigParser : qi::grammar<Iterator, ascii::space_type>
51 {
52     ConfigParser(Configuration &x) : ConfigParser::base_type(entry)
53     {
54         using qi::int_;
55         using qi::float_;
56         using qi::bool_;
57         using qi::lit;
58         using qi::lexeme;
59         using ascii::char_;
60         using qi::_1;
62         // Rules for parsing layer id assignments: { {int, int}, ... }
63         id2group  = '{' >> int_ >> ',' >> int_ >> '}';
64         id2groups = '{' >> id2group >> *(qi::lit(',') >> id2group) >> '}';
66         // Rules for parsing paths. Discard '"'
67         path %= lexeme[+(char_ - '"')];
68         q_path = qi::omit[*char_('"')] >> path >> qi::omit[*char_('"')];
70         // Rules for parsing subgraph data conversion information
71         intvec = int_ >> *int_;
72         floatvec = float_ >> *float_;
74         // Grammar for parsing configuration file
75         entry %=
76          lit("layerIndex2LayerGroupId") >> '=' >>
77                         id2groups[ph::ref(x.layerIndex2LayerGroupId) = _1]    |
78          lit("#")             >>  *(char_) /* discard comments */             |
79          lit("numFrames")     >> '=' >> int_[ph::ref(x.numFrames) = _1]       |
80          lit("preProcType")   >> '=' >> int_[ph::ref(x.preProcType) = _1]     |
81          lit("inWidth")       >> '=' >> int_[ph::ref(x.inWidth) = _1]         |
82          lit("inHeight")      >> '=' >> int_[ph::ref(x.inHeight) = _1]        |
83          lit("inNumChannels") >> '=' >> int_[ph::ref(x.inNumChannels) = _1]   |
84          lit("inData")        >> '=' >> q_path[ph::ref(x.inData) = _1]        |
85          lit("outData")       >> '=' >> q_path[ph::ref(x.outData) = _1]       |
86          lit("netBinFile")    >> '=' >> q_path[ph::ref(x.netBinFile) = _1]    |
87          lit("paramsBinFile") >> '=' >> q_path[ph::ref(x.paramsBinFile) = _1] |
88          lit("enableTrace")   >> '=' >> bool_[ph::ref(x.enableOutputTrace)= _1] |
89          lit("quantHistoryParam1")   >> '=' >>
90                                    int_[ph::ref(x.quantHistoryParam1)= _1] |
91          lit("quantHistoryParam2")   >> '=' >>
92                                    int_[ph::ref(x.quantHistoryParam2)= _1] |
93          lit("quantMargin")   >> '=' >> int_[ph::ref(x.quantMargin)= _1] |
94          lit("inConvType")    >> '=' >> intvec[ph::ref(x.inConvType) = _1] |
95          lit("inIsSigned")    >> '=' >> intvec[ph::ref(x.inIsSigned) = _1] |
96          lit("inScaleF2Q")    >> '=' >> floatvec[ph::ref(x.inScaleF2Q) = _1] |
97          lit("inIsNCHW")      >> '=' >> intvec[ph::ref(x.inIsNCHW) = _1] |
98          lit("outConvType")   >> '=' >> intvec[ph::ref(x.outConvType) = _1] |
99          lit("outIsSigned")   >> '=' >> intvec[ph::ref(x.outIsSigned) = _1] |
100          lit("outScaleF2Q")   >> '=' >> floatvec[ph::ref(x.outScaleF2Q) = _1] |
101          lit("outIsNCHW")     >> '=' >> intvec[ph::ref(x.outIsNCHW) = _1]
102          ;
103     }
105     qi::rule<Iterator, std::string(), ascii::space_type> path;
106     qi::rule<Iterator, std::string(), ascii::space_type> q_path;
107     qi::rule<Iterator, ascii::space_type> entry;
109     qi::rule<Iterator, std::pair<int, int>(), ascii::space_type> id2group;
110     qi::rule<Iterator, std::map<int, int>(), ascii::space_type> id2groups;
112     qi::rule<Iterator, std::vector<int>(), ascii::space_type> intvec;
113     qi::rule<Iterator, std::vector<float>(), ascii::space_type> floatvec;
114 };
116 bool Configuration::ReadFromFile(const std::string &file_name)
118     std::ifstream IFS(file_name);
120     if (!IFS.good())
121         return false;
123     typedef ConfigParser<std::string::const_iterator> ConfigParser;
125     ConfigParser G(*this);
126     std::string str;
128     bool result = true;
130     int line_num = 0;
131     while (getline(IFS, str))
132     {
133         line_num++;
135         // Skip lines with whitespace
136         auto f = [](unsigned char const c) { return std::isspace(c); };
137         if (std::all_of(str.begin(),str.end(), f))
138             continue;
140         result = phrase_parse(str.cbegin(), str.cend(), G, ascii::space);
142         if (!result)
143         {
144             std::cout << "Parsing failed on line " << line_num
145                       << ": " << str << std::endl;
146             break;
147         }
148     }
150     IFS.close();
152     // If read failed, return false
153     if (!result)
154         return false;
156     // If validate fails, return false
157     if (!Validate())
158         return false;
160     return true;
163 #if 0
164 --- test.cfg ---
165 numFrames     = 1
166 preProcType   = 0
167 inData        = ../test/testvecs/input/preproc_0_224x224.y
168 outData       = stats_tool_out.bin
169 netBinFile    = ../test/testvecs/config/tidl_models/tidl_net_imagenet_jacintonet11v2.bin
170 paramsBinFile = ../test/testvecs/config/tidl_models/tidl_param_imagenet_jacintonet11v2.bin
171 inWidth       = 224
172 inHeight      = 224
173 inNumChannels = 3
175 # Enable tracing of output buffers
176 enableTrace = true
178 # Override layer group id assignments in the network
179 layerIndex2LayerGroupId = { {12, 2}, {13, 2}, {14, 2} }
180 ----------------
181 #endif
183 #if TEST_PARSING
184 int main()
186     Configuration c;
187     c.ReadFromFile("test.cfg");
189     return 0;
191 #endif