source: cfg_itronx+oil_gcc/cfg/cfg3.cpp@ 54

Last change on this file since 54 was 54, checked in by ertl-ishikawa, 12 years ago

cfg+oil対応コンフィギュレータを追加

File size: 12.9 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2007-2011 by TAKAGI Nobuhisa
6 *
7 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 */
37#include <fstream>
38#include <sstream>
39#include "toppers/diagnostics.hpp"
40#include "toppers/s_record.hpp"
41#include "toppers/macro_processor.hpp"
42#include "toppers/itronx/component.hpp"
43#include "toppers/itronx/component.hpp"
44#include "cfg.hpp"
45#include <boost/spirit/include/classic.hpp>
46#include <boost/filesystem/path.hpp>
47#include <boost/filesystem/operations.hpp>
48
49namespace
50{
51 using toppers::text_line;
52 typedef toppers::macro_processor::element element;
53 typedef toppers::macro_processor::var_t var_t;
54 typedef toppers::macro_processor::context context;
55
56 /*!
57 * \brief シンボルに対応するアドレスの取得
58 * \param[in] line 行番号
59 * \param[in] arg_list マクロ実引数リスト
60 * \param[in] p_ctx マクロコンテキスト
61 * \retval マクロ返却値
62 */
63 template < class checker >
64 var_t bf_symbol( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
65 {
66 using namespace toppers;
67 using namespace toppers::itronx;
68
69 if ( macro_processor::check_arity( line, arg_list.size(), 1, "SYMBOL" ) )
70 {
71 std::string symbol( macro_processor::to_string( arg_list[0], p_ctx ) );
72 std::tr1::shared_ptr< checker > chk = get_global< std::tr1::shared_ptr< checker > >( "checker" );
73 nm_symbol::entry entry = chk->find( symbol );
74 if ( entry.type >= 0 )
75 {
76 element e;
77 e.i = entry.address;
78 return var_t( 1, e );
79 }
80 }
81 return var_t();
82 }
83
84 // VMA アドレス解決用テーブル
85 std::vector< std::pair< std::tr1::int64_t, std::vector< unsigned char > > > vma_table;
86
87 /*!
88 * \brief 指定したアドレスに格納されている値の取得
89 * \param[in] line 行番号
90 * \param[in] arg_list マクロ実引数リスト
91 * \param[in] p_ctx マクロコンテキスト
92 * \retval マクロ返却値
93 *
94 * 第1引数にアドレスを、第2引数に読み込むバイト数を指定します。
95 */
96 template < class checker >
97 var_t bf_peek( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
98 {
99 using namespace toppers;
100 using namespace toppers::itronx;
101
102 if ( macro_processor::check_arity( line, arg_list.size(), 2, "PEEK" ) )
103 {
104 std::size_t address = static_cast< std::size_t >( macro_processor::to_integer( arg_list[0], p_ctx ) );
105 std::size_t size = static_cast< std::size_t >( macro_processor::to_integer( arg_list[1], p_ctx ) );
106 std::tr1::shared_ptr< checker > chk = get_global< std::tr1::shared_ptr< checker > >( "checker" );
107
108 std::map< std::string, var_t >::const_iterator le_iter( p_ctx->var_map.find( "LITTLE_ENDIAN" ) );
109 if ( le_iter != p_ctx->var_map.end() )
110 {
111 bool little_endian = !!( *le_iter->second.front().i );
112 long pos = -1;
113 long base = 0;
114 element e;
115
116 for ( std::size_t i = 0, n = vma_table.size(); i < n; i++ )
117 {
118 if ( vma_table[i].first <= address && address < vma_table[i].first + vma_table[i].second.size() )
119 {
120 pos = i;
121 base = static_cast< long >( address - vma_table[i].first );
122 }
123 }
124 if ( pos >= 0 ) // VMA から読み取る
125 {
126 std::tr1::uint64_t value = 0;
127 if ( little_endian )
128 {
129 for ( long j = static_cast< long >( size-1 ); j >= 0; j-- )
130 {
131 int t = vma_table[ pos ].second[ base + j ];
132 if ( t < 0 )
133 {
134 return var_t();
135 }
136 value = ( value << 8 ) | ( t & 0xff );
137 }
138 }
139 else
140 {
141 for ( std::size_t j = 0; j < size; j++ )
142 {
143 int t = vma_table[ pos ].second[ base + j ];
144 if ( t < 0 )
145 {
146 return var_t();
147 }
148 value = ( value << 8 ) | ( t & 0xff );
149 }
150 }
151 e.i = value;
152 }
153 else // VMA ではないので、Sレコードから読み取る
154 {
155 e.i = chk->get( address, size, !!little_endian );
156 }
157 return var_t( 1, e );
158 }
159 }
160 return var_t();
161 }
162
163 /*!
164 * \brief メモリブロックの転送
165 * \param[in] line 行番号
166 * \param[in] arg_list マクロ実引数リスト
167 * \param[in] p_ctx マクロコンテキスト
168 * \retval マクロ返却値
169 *
170 * 第1引数に転送元アドレス、第2引数に転送先アドレス、第3引数に転送するバイト数を指定します。
171 * 指定したコピー元アドレスからコピー先アドレスへ、指定バイト数のメモリブロックを転送します。
172 * この関数は、LMAからVMAへのアドレス変換を目的として使用することを想定しています。
173 *
174 * \attention この組み込み関数は、LMAからVMAへのアドレス変換を想定しているため、頻繁に転送を
175 * 繰り返すような状況には対応していません(メモリ不足が発生します)。
176 */
177 template < class checker >
178 var_t bf_bcopy( text_line const& line, std::vector< var_t > const& arg_list, context* p_ctx )
179 {
180 using namespace toppers;
181 using namespace toppers::itronx;
182
183 if ( macro_processor::check_arity( line, arg_list.size(), 3, "BCOPY" ) )
184 {
185 std::size_t src = static_cast< std::size_t >( macro_processor::to_integer( arg_list[0], p_ctx ) );
186 std::size_t dst = static_cast< std::size_t >( macro_processor::to_integer( arg_list[1], p_ctx ) );
187 std::size_t size = static_cast< std::size_t >( macro_processor::to_integer( arg_list[2], p_ctx ) );
188 std::tr1::shared_ptr< checker > chk = get_global< std::tr1::shared_ptr< checker > >( "checker" );
189
190 std::pair< std::tr1::int64_t, std::vector< unsigned char > > block;
191 block.first = dst;
192 block.second.reserve( size );
193 for ( std::tr1::int64_t i = 0; i < size; i++ )
194 {
195 block.second.push_back( static_cast< unsigned char >( chk->get( static_cast< std::size_t >( src + i ), 1, true ) ) );
196 }
197 vma_table.push_back( block );
198 }
199 return var_t();
200 }
201
202}
203
204using namespace toppers;
205template < class checker >
206static inline bool cfg3_main_tf( std::auto_ptr< macro_processor > mproc, boost::any template_file )
207{
208 namespace fs = boost::filesystem;
209
210 // ↓ 追加組み込み関数の登録
211 toppers::macro_processor::func_t func_info = {};
212 func_info.name = "SYMBOL";
213 func_info.f = &bf_symbol< checker >;
214 mproc->add_builtin_function( func_info );
215
216 func_info.name = "PEEK";
217 func_info.f = &bf_peek< checker >;
218 mproc->add_builtin_function( func_info );
219
220 func_info.name = "BCOPY";
221 func_info.f = &bf_bcopy< checker >;
222 mproc->add_builtin_function( func_info );
223 // ↑ 追加組み込み関数の登録
224
225 fs::path cfg_dir( get_global< std::string >( "cfg-directory" ) ); // filesystem3対応
226 std::vector< std::string > include_paths = get_global< std::vector< std::string > >( "include-path" );
227 include_paths.push_back( cfg_dir.empty() ? "." : cfg_dir.string() ); // filesystem3対応
228
229 toppers::text in_text;
230 toppers::text pp_text;
231 std::string file_name( boost::any_cast< std::string& >( template_file ) );
232
233 in_text.set_line( file_name, 1 );
234 std::ifstream ifs( file_name.c_str() );
235 if ( !ifs.is_open() )
236 {
237 fatal( _( "`%1%` can not be found." ), file_name );
238 }
239
240 in_text.append( ifs );
241 macro_processor::preprocess( in_text, pp_text );
242 mproc->evaluate( pp_text );
243
244 if ( get_error_count() > 0 )
245 {
246 return false;
247 }
248 // 出力ファイルがあるかどうか分からないが、一応セーブする。
249 output_file::save();
250
251 return true;
252}
253
254namespace toppers{ namespace itronx{
255 bool cfg3_main_mproc( itronx::factory factory, std::auto_ptr< itronx::cfg1_out > cfg1_out, boost::any template_file )
256 {
257 using namespace toppers::itronx;
258
259 // テンプレート処理
260 std::auto_ptr< macro_processor > mproc;
261 std::auto_ptr< component > component_ptr;
262
263 if ( get_global< bool >( "with-software-components" ) )
264 {
265 mproc = factory.create_macro_processor( *cfg1_out, cfg1_out->get_static_api_array() );
266 component_ptr.reset( new component( mproc.get() ) );
267 }
268 else
269 {
270 cfg1_out::static_api_map api_map( cfg1_out->merge() );
271 toppers::itronx::assign_id( api_map ); // ID番号の割付け
272 mproc = factory.create_macro_processor( *cfg1_out, api_map );
273 }
274 return cfg3_main_tf< checker >( mproc, template_file );
275 }
276}}
277
278namespace toppers{ namespace oil{
279 bool cfg3_main_mproc( oil::factory factory, std::auto_ptr< oil::cfg1_out > cfg1_out, boost::any template_file )
280 {
281 using namespace toppers::oil;
282
283 // テンプレート処理
284 std::auto_ptr< macro_processor > mproc;
285 //std::auto_ptr< component > component_ptr;
286
287 if ( get_global< bool >( "with-software-components" ) )
288 {
289 error( _( "with-software-components is not supported." ) );
290 }
291 else // 従来仕様(ソフトウェア部品非対応)
292 {
293 cfg1_out::cfg_obj_map cfg_obj_map( cfg1_out->merge() );
294 toppers::oil::assign_id(cfg_obj_map); // ID番号の割付け
295 mproc = factory.create_macro_processor( *cfg1_out, cfg_obj_map );
296 }
297 return cfg3_main_tf< checker >( mproc, template_file );
298 }
299}}
300
301
302
303template < class T, class checker, class U, class V, class W >
304static inline bool cfg3_main_init( U factory, V cfg3_info, W* p_func_mproc )
305{
306 using namespace toppers::itronx;
307 using namespace toppers::oil;
308
309 global( "factory" ) = &factory;
310
311 // *.cfgとcfg1_out.srecの読み込み
312 std::string input_file;
313 try
314 {
315 input_file = get_global< std::string >( "input-file" );
316 }
317 catch ( boost::bad_any_cast& )
318 {
319 fatal( _( "no input files" ) );
320 }
321 std::string cfg1_out_name( get_global< std::string >( "cfg1_out" ) );
322 std::auto_ptr< T > cfg1_out( factory.create_cfg1_out( cfg1_out_name ) );
323
324 codeset_t codeset = get_global< codeset_t >( "codeset" );
325 cfg1_out->load_cfg( input_file, codeset, cfg3_info );
326 cfg1_out->load_srec();
327
328 std::auto_ptr< checker > p_checker( factory.create_checker() );
329 std::tr1::shared_ptr< checker > chk( p_checker );
330 global( "checker" ) = chk;
331 std::string rom_image( get_global< std::string >( "rom-image" ) );
332 std::string symbol_table( get_global< std::string >( "symbol-table" ) );
333 chk->load_rom_image( rom_image, symbol_table );
334
335 // テンプレートファイル
336 boost::any template_file( global( "template-file" ) );
337 if ( template_file.empty() )
338 {
339 // テンプレートファイルが指定されていなければ最低限のチェックのみ(後方互換性のため)
340 // パラメータチェック
341 if ( !chk->check( *cfg1_out ) )
342 {
343 return false;
344 }
345 }
346 else
347 {
348 if( !p_func_mproc( factory, cfg1_out, template_file ) )
349 {
350 return false;
351 }
352 }
353
354 // パス4以降からも流用されるため、現在処理中のパスを調べる。
355 int pass = get_global< int >( "pass" );
356 int max_pass = get_global< int >( "max-pass" );
357 if ( max_pass == pass ) // 最終段階のパスが成功したときに"check complete"メッセージを出す。
358 {
359 std::cerr << _( "check complete" ) << std::endl;
360 }
361
362 return true;
363}
364
365bool cfg3_main()
366{
367 std::string kernel( get_global< std::string >( "kernel" ) );
368
369 if ( kernel == "atk1" )
370 {
371 using namespace toppers::oil;
372 factory factory( kernel );
373 return cfg3_main_init< cfg1_out, checker >( factory, factory.get_object_definition_info(), &cfg3_main_mproc );
374 }
375 else
376 {
377 using namespace toppers::itronx;
378 factory factory( kernel );
379 return cfg3_main_init< cfg1_out, checker >( factory, *factory.get_static_api_info_map(), &cfg3_main_mproc );
380 }
381
382}
Note: See TracBrowser for help on using the repository browser.