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::bool_;
56 using qi::lit;
57 using qi::lexeme;
58 using ascii::char_;
59 using qi::_1;
61 // Rules for parsing layer id assignments: { {int, int}, ... }
62 id2group = '{' >> int_ >> ',' >> int_ >> '}';
63 id2groups = '{' >> id2group >> *(qi::lit(',') >> id2group) >> '}';
65 // Rules for parsing paths. Discard '"'
66 path %= lexeme[+(char_ - '"')];
67 q_path = qi::omit[*char_('"')] >> path >> qi::omit[*char_('"')];
69 // Grammar for parsing configuration file
70 entry %=
71 lit("layerIndex2LayerGroupId") >> '=' >>
72 id2groups[ph::ref(x.layerIndex2LayerGroupId) = _1] |
73 lit("#") >> *(char_) /* discard comments */ |
74 lit("numFrames") >> '=' >> int_[ph::ref(x.numFrames) = _1] |
75 lit("preProcType") >> '=' >> int_[ph::ref(x.preProcType) = _1] |
76 lit("inWidth") >> '=' >> int_[ph::ref(x.inWidth) = _1] |
77 lit("inHeight") >> '=' >> int_[ph::ref(x.inHeight) = _1] |
78 lit("inNumChannels") >> '=' >> int_[ph::ref(x.inNumChannels) = _1] |
79 lit("inData") >> '=' >> q_path[ph::ref(x.inData) = _1] |
80 lit("outData") >> '=' >> q_path[ph::ref(x.outData) = _1] |
81 lit("netBinFile") >> '=' >> q_path[ph::ref(x.netBinFile) = _1] |
82 lit("paramsBinFile") >> '=' >> q_path[ph::ref(x.paramsBinFile) = _1] |
83 lit("enableTrace") >> '=' >> bool_[ph::ref(x.enableOutputTrace)= _1] |
84 lit("quantHistoryParam1") >> '=' >>
85 int_[ph::ref(x.quantHistoryParam1)= _1] |
86 lit("quantHistoryParam2") >> '=' >>
87 int_[ph::ref(x.quantHistoryParam2)= _1] |
88 lit("quantMargin") >> '=' >> int_[ph::ref(x.quantMargin)= _1]
89 ;
90 }
92 qi::rule<Iterator, std::string(), ascii::space_type> path;
93 qi::rule<Iterator, std::string(), ascii::space_type> q_path;
94 qi::rule<Iterator, ascii::space_type> entry;
96 qi::rule<Iterator, std::pair<int, int>(), ascii::space_type> id2group;
97 qi::rule<Iterator, std::map<int, int>(), ascii::space_type> id2groups;
98 };
100 bool Configuration::ReadFromFile(const std::string &file_name)
101 {
102 std::ifstream IFS(file_name);
104 if (!IFS.good())
105 return false;
107 typedef ConfigParser<std::string::const_iterator> ConfigParser;
109 ConfigParser G(*this);
110 std::string str;
112 bool result = true;
114 int line_num = 0;
115 while (getline(IFS, str))
116 {
117 line_num++;
119 // Skip lines with whitespace
120 auto f = [](unsigned char const c) { return std::isspace(c); };
121 if (std::all_of(str.begin(),str.end(), f))
122 continue;
124 result = phrase_parse(str.cbegin(), str.cend(), G, ascii::space);
126 if (!result)
127 {
128 std::cout << "Parsing failed on line " << line_num
129 << ": " << str << std::endl;
130 break;
131 }
132 }
134 IFS.close();
136 // If read failed, return false
137 if (!result)
138 return false;
140 // If validate fails, return false
141 if (!Validate())
142 return false;
144 return true;
145 }
147 #if 0
148 --- test.cfg ---
149 numFrames = 1
150 preProcType = 0
151 inData = ../test/testvecs/input/preproc_0_224x224.y
152 outData = stats_tool_out.bin
153 netBinFile = ../test/testvecs/config/tidl_models/tidl_net_imagenet_jacintonet11v2.bin
154 paramsBinFile = ../test/testvecs/config/tidl_models/tidl_param_imagenet_jacintonet11v2.bin
155 inWidth = 224
156 inHeight = 224
157 inNumChannels = 3
159 # Enable tracing of output buffers
160 enableTrace = true
162 # Override layer group id assignments in the network
163 layerIndex2LayerGroupId = { {12, 2}, {13, 2}, {14, 2} }
164 ----------------
165 #endif
167 #if TEST_PARSING
168 int main()
169 {
170 Configuration c;
171 c.ReadFromFile("test.cfg");
173 return 0;
174 }
175 #endif