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 ;
85 }
87 qi::rule<Iterator, std::string(), ascii::space_type> path;
88 qi::rule<Iterator, std::string(), ascii::space_type> q_path;
89 qi::rule<Iterator, ascii::space_type> entry;
91 qi::rule<Iterator, std::pair<int, int>(), ascii::space_type> id2group;
92 qi::rule<Iterator, std::map<int, int>(), ascii::space_type> id2groups;
93 };
95 bool Configuration::ReadFromFile(const std::string &file_name)
96 {
97 std::ifstream IFS(file_name);
99 if (!IFS.good())
100 return false;
102 typedef ConfigParser<std::string::const_iterator> ConfigParser;
104 ConfigParser G(*this);
105 std::string str;
107 bool result = true;
109 int line_num = 0;
110 while (getline(IFS, str))
111 {
112 line_num++;
114 // Skip lines with whitespace
115 auto f = [](unsigned char const c) { return std::isspace(c); };
116 if (std::all_of(str.begin(),str.end(), f))
117 continue;
119 result = phrase_parse(str.cbegin(), str.cend(), G, ascii::space);
121 if (!result)
122 {
123 std::cout << "Parsing failed on line " << line_num
124 << ": " << str << std::endl;
125 break;
126 }
127 }
129 IFS.close();
131 // If read failed, return false
132 if (!result)
133 return false;
135 // If validate fails, return false
136 if (!Validate())
137 return false;
139 return true;
140 }
142 #if 0
143 --- test.cfg ---
144 numFrames = 1
145 preProcType = 0
146 inData = ../test/testvecs/input/preproc_0_224x224.y
147 outData = stats_tool_out.bin
148 netBinFile = ../test/testvecs/config/tidl_models/tidl_net_imagenet_jacintonet11v2.bin
149 paramsBinFile = ../test/testvecs/config/tidl_models/tidl_param_imagenet_jacintonet11v2.bin
150 inWidth = 224
151 inHeight = 224
152 inNumChannels = 3
154 # Enable tracing of output buffers
155 enableTrace = true
157 # Override layer group id assignments in the network
158 layerIndex2LayerGroupId = { {12, 2}, {13, 2}, {14, 2} }
159 ----------------
160 #endif
162 #if TEST_PARSING
163 int main()
164 {
165 Configuration c;
166 c.ReadFromFile("test.cfg");
168 return 0;
169 }
170 #endif