Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: src/trusted/validator_arm/dgen_test_output.py

Issue 10191011: Moving dgen_ scripts out of validator_arm into a common directory. (Closed)
Patch Set: Updates per code review. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/trusted/validator_arm/dgen_output.py ('k') | src/trusted/validator_arm/generate_decoder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6 #
7
8 """
9 Responsible for generating the testing decoders based on
10 parsed table representations.
11 """
12
13 # This file generates testing code for our class decoder. The decoder
14 # tables are specifically written to minimize the number of decoder
15 # classes needed to parse valid ARM instructions. For testing, this is
16 # a problem. We can't (easily) tell if the intended instruction rules
17 # of ARM are being met, since there is not a one-to-one mapping from
18 # class decoders to rules.
19 #
20 # For example, consider the following two rows (from armv7.table):
21 #
22 # | 0011x - = Binary4RegisterShiftedOp
23 # Rsb_Rule_144_A1_P288
24 # cccc0000011snnnnddddssss0tt1mmmm
25 # RegsNotPc
26 # | 0100x - = Binary4RegisterShiftedOp
27 # Add_Rule_7_A1_P26
28 # cccc0000100snnnnddddssss0tt1mmmm
29 # RegsNotPc
30 #
31 # Both rows state to return a Binary4RegisterShiftedOp class decoder.
32 # The sequence of four symbols correspond to (in order presented):
33 #
34 # name - The name of the class decoder to use in sel_ldr
35 # rule - A unique name identifying the rule from the manual that
36 # defines what the selected class decoder is to decode.
37 # pattern - The sequence of bits defines by the rule (above)
38 # constraints - Any additional constraints assumed by the rule.
39 #
40 # All but the name is optional. The remaining fields provide
41 # additional documentation and information for testing (which is
42 # used by this file).
43 #
44 # If these two rows had a mergable bit pattern (which they do not),
45 # these rows would still not mergable since the actions are
46 # different. However, for sel_ldr, they both state to use a
47 # Binary4RegisterShiftedOp. The remaining identifiers are added data
48 # for testing only.
49 #
50 # We fix this by defining a notion of "action_filter" where one can
51 # choose to keep only those fields that are applicable. For sel_ldr,
52 # it's only 'name'. For testing, it will include other fields,
53 # depending on the context.
54 #
55 # Note: The current ARM instruction table has both new and old
56 # actions. Old actions only define the 'InstClass' entry. If the
57 # remaining fields are omitted, the corresponding testing for those
58 # entries are omitted.
59 #
60 # Note: See dgen_decoder_output.py for more details on how we build a
61 # decoder for sel_ldr.
62 #
63 # For testing, we would like to know the specific instruction rule
64 # that was being tested. Further, we would like to know what
65 # instruction rule was chosen for each decoder class selection made by
66 # the parse tables. To do this, we do two levels of wrapping.
67 #
68 # This file generates a set of wrapper classes, each a subclass of
69 # NamedClassDecoder. One is generated for each InstClass needed by
70 # sel_ldr (i.e. only the 'name' field). These named classes correspond
71 # to what sel_ldr will select.
72 #
73 # The named version of each named InstClass is:
74 #
75 # class NamedInstClass : public NamedClassDecoder {
76 # public:
77 # inline NamedInstClass()
78 # : NamedClassDecoder(decoder_, "InstClass")
79 # {}
80 # virtual ~NamedInstClass() {}
81 # protected:
82 # explicit inline NamedInstClass(const char* name)
83 # : NamedClassDecoder(decoder_, name) {}
84 # private:
85 # Binary3RegisterShiftedTest decoder_;
86 #};
87 #
88 # This makes sure that each decoder class can be identified using a
89 # separate class decoder. The public constructor is for table rows
90 # that don't have rule names. The protected constructor is for table
91 # rows that have a rule name, and will be a subclass of this class.
92 # The class defined for rows with a Rule name is:
93 #
94 # class NamedRuleInstClass : public NamedInstClass {
95 # public:
96 # inline NamedRuleInstClass()
97 # : NamedInstClass("RuleInstClass")
98 # {}
99 # virtual ~NamedRuleInstClass() {}
100 #};
101 #
102 # The base class for NamedClassDecoder is specified in
103 # "named_class_decoder.h". This file defines a class that takes a
104 # ClassDecoder (reference) C and a print name NAME, and builds a
105 # corresponding ClassDecoder that acts like C, but will print out
106 # NAME. The behaviour of C is maintained by dispatching each virtual
107 # on the NamedClassDecoder to the corresponding virtual on C.
108 #
109 # We then define the class decoder Decoder, by defining a derived
110 # instance of DecoderState as follows:
111 #
112 # class NamedDecoder : DecoderState {
113 # public:
114 # explicit NamedDecoder();
115 # virtual ~NamedDecoder();
116 # const NamedClassDecoder& decode_named(const Instruction) const;
117 # virtual const ClassDecoder& decode(const Instruction) const;
118 # ...
119 # };
120 #
121 # The method decode is the expected API for the NamedDecoder, which is
122 # an instance of DecoderState (defined in decode.h). The method
123 # decode_named is the same, but returns NamedClassDecoder's so that
124 # good error messages can be generated by the test harnesses for
125 # ClassDecoder's (see decoder_tester.h for more details on
126 # ClassDecoder test harnesses).
127 #
128 # To the NamedDecoder, we add a constant field NamedClassDecoder for
129 # each possible class decoder method decode_named could return, or
130 # that we could use in automatically generated tests. These fields
131 # allow us to only create the corresponding decoder classes once
132 # (during constructor initialization).
133 #
134 # Finally, we add a method corresponding to each defined decoder
135 # table. The forms of these decoders is:
136 #
137 # inline const NamedClassDecoder& decode_TABLE(
138 # const nacl_arm_dec::Instruction insn) const;
139 #
140 # Each of these methods are defined as inline methods so that they can
141 # be optimized away in the corresponding top level methods (i.e.
142 # decode_named and decode).
143 #
144 # For testing, there are three files generated:
145 #
146 # decoder_named_classes.h
147 # decoder_named_decoder.h
148 # decoder_named.cc
149 # decoder_tests.cc
150 #
151 # File decoder_named_classes.h defines the class declarations for the
152 # generated Rule classes, and named class decoder classes. File
153 # decoder_named_decoder.h defines the decoder class NamedDecoder
154 # (discussed above). decoder_named.cc contains the corresponding
155 # implementations of the constructors and methods of these classes.
156 #
157 # decoder_tests.cc generates an automatic test harness executable,
158 # that will test each instruction Rule. Each test generates all
159 # possible matches the the corresponding Pattern of the table rule,
160 # and calls the corresponding tester associated with the class decoder
161 # of that row. By default, the tester is presumed to be named.
162 #
163 # InstClassTester
164 #
165 # If the row defines a Constraints identifier, then the tester
166 #
167 # InstClassTesterConstraints
168 #
169 # is used instead.
170
171 import dgen_opt
172 import dgen_output
173
174 # Defines the header for decoder_named_classes.h
175 NAMED_CLASSES_H_HEADER="""
176 %(FILE_HEADER)s
177 %(NOT_TCB_MESSAGE)s
178
179 #ifndef %(IFDEF_NAME)s
180 #define %(IFDEF_NAME)s
181
182 #include "native_client/src/trusted/validator_arm/named_class_decoder.h"
183
184 """
185
186 RULE_CLASSES_HEADER="""
187 /*
188 * Define rule decoder classes.
189 */
190 namespace nacl_arm_dec {
191 """
192
193 RULE_CLASS="""
194 class %(rule)s%(decoder)s
195 : public %(decoder)s {
196 public:
197 virtual ~%(rule)s%(decoder)s() {}
198 };
199
200 """
201
202 RULE_CLASSES_FOOTER="""
203 } // nacl_arm_dec
204 """
205
206 NAMED_H_NAMESPACE="""
207 namespace nacl_arm_test {
208 """
209
210 NAMED_DECODERS_HEADER="""
211 /*
212 * Define named class decoders for each class decoder.
213 * The main purpose of these classes is to introduce
214 * instances that are named specifically to the class decoder
215 * and/or rule that was used to parse them. This makes testing
216 * much easier in that error messages use these named classes
217 * to clarify what row in the corresponding table was used
218 * to select this decoder. Without these names, debugging the
219 * output of the test code would be nearly impossible
220 */
221
222 """
223
224 NAMED_DECODER_DECLARE="""
225 class Named%(decoder)s : public NamedClassDecoder {
226 public:
227 inline Named%(decoder)s()
228 : NamedClassDecoder(decoder_, "%(decoder)s")
229 {}
230 virtual ~Named%(decoder)s() {}
231 protected:
232 explicit inline Named%(decoder)s(const char* name)
233 : NamedClassDecoder(decoder_, name) {}
234 private:
235 nacl_arm_dec::%(decoder)s decoder_;
236 };
237
238 """
239
240 NAMED_RULE_DECLARE="""
241 class Named%(rule)s%(decoder)s
242 : public Named%(decoder)s {
243 public:
244 inline Named%(rule)s%(decoder)s()
245 : Named%(decoder)s("%(rule)s%(decoder)s")
246 {}
247 virtual ~Named%(rule)s%(decoder)s() {}
248 };
249
250 """
251
252 NAMED_CLASSES_H_FOOTER="""
253 } // namespace nacl_arm_test
254 #endif // %(IFDEF_NAME)s
255 """
256
257 def generate_named_classes_h(decoder, decoder_name, filename, out):
258 """Defines named classes needed for decoder testing.
259
260 Args:
261 tables: list of Table objects to process.
262 decoder_name: The name of the decoder state to build.
263 filename: The (localized) name for the .h file.
264 out: a COutput object to write to.
265 """
266 if not decoder.primary: raise Exception('No tables provided.')
267
268 values = {
269 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
270 'NOT_TCB_MESSAGE' : dgen_output.NOT_TCB_BOILERPLATE,
271 'IFDEF_NAME' : dgen_output.ifdef_name(filename),
272 'decoder_name': decoder_name,
273 }
274 out.write(NAMED_CLASSES_H_HEADER % values)
275 _generate_rule_classes(decoder, values, out)
276 out.write(NAMED_H_NAMESPACE)
277 _generate_named_decoder_classes(decoder, values, out)
278 out.write(NAMED_CLASSES_H_FOOTER % values)
279
280 def _generate_named_decoder_classes(decoder, values, out):
281 out.write(NAMED_DECODERS_HEADER)
282 # Generate one for each type of decoder in the decoder.
283 for d in decoder.action_filter(['name']).decoders():
284 values['decoder'] = d.name
285 values['rule'] = ''
286 out.write(NAMED_DECODER_DECLARE % values)
287 # Now generate one for each decoder that has a rule associated with it.
288 for d in decoder.action_filter(['name', 'rule']).rules():
289 values['decoder'] = d.name
290 values['rule'] = d.rule
291 out.write(NAMED_RULE_DECLARE % values)
292
293 def _generate_rule_classes(decoder, values, out):
294 # Note: we generate these classes in nacl_arm_dec, so that
295 # all decoder classes generated by the pareser are in the
296 # same namesapce.
297 out.write(RULE_CLASSES_HEADER)
298 for action in decoder.action_filter(['name', 'rule']).rules():
299 values['decoder'] = action.name
300 values['rule'] = action.rule
301 out.write(RULE_CLASS % values)
302 out.write(RULE_CLASSES_FOOTER)
303
304 NAMED_DECODER_H_HEADER="""
305 %(FILE_HEADER)s
306 %(NOT_TCB_MESSAGE)s
307
308 #ifndef %(IFDEF_NAME)s
309 #define %(IFDEF_NAME)s
310
311 #include "native_client/src/trusted/validator_arm/decode.h"
312 #include "%(FILENAME_BASE)s_classes.h"
313 #include "native_client/src/trusted/validator_arm/named_class_decoder.h"
314
315 namespace nacl_arm_test {
316 """
317
318 DECODER_STATE_HEADER="""
319 // Defines a (named) decoder class selector for instructions
320 class Named%(decoder_name)s : nacl_arm_dec::DecoderState {
321 public:
322 explicit Named%(decoder_name)s();
323 virtual ~Named%(decoder_name)s();
324
325 // Parses the given instruction, returning the named class
326 // decoder to use.
327 const NamedClassDecoder& decode_named(
328 const nacl_arm_dec::Instruction) const;
329
330 // Parses the given instruction, returning the class decoder
331 // to use.
332 virtual const nacl_arm_dec::ClassDecoder& decode(
333 const nacl_arm_dec::Instruction) const;
334 """
335
336 DECODER_STATE_FIELD_COMMENTS="""
337 // The following fields define the set of class decoders
338 // that can be returned by the API function "decode_named". They
339 // are created once as instance fields, and then returned
340 // by the table methods above. This speeds up the code since
341 // the class decoders need to only be bulit once (and reused
342 // for each call to "decode_named").
343 """
344
345 DECODER_STATE_FIELD="""
346 const Named%(rule)s%(decoder)s %(rule)s%(decoder)s_instance_;
347 """
348
349 DECODER_STATE_PRIVATE="""
350 private:
351 """
352
353 DECODER_STATE_DECODER_COMMENTS="""
354 // The following list of methods correspond to each decoder table,
355 // and implements the pattern matching of the corresponding bit
356 // patterns. After matching the corresponding bit patterns, they
357 // either call other methods in this list (corresponding to another
358 // decoder table), or they return the instance field that implements
359 // the class decoder that should be used to decode the particular
360 // instruction.
361 """
362
363 DECODER_STATE_DECODER="""
364 inline const NamedClassDecoder& decode_%(table)s(
365 const nacl_arm_dec::Instruction insn) const;
366 """
367
368 DECODER_STATE_FOOTER="""
369 };
370 """
371
372 NAMED_DECODER_H_FOOTER="""
373 } // namespace nacl_arm_test
374 #endif // %(IFDEF_NAME)s
375 """
376
377 def generate_named_decoder_h(decoder, decoder_name, filename, out):
378 """Generates the named decoder for testing.
379
380 Args:
381 tables: list of Table objects to process.
382 decoder_name: The name of the decoder state to build.
383 filename: The (localized) name for the .h file.
384 out: a COutput object to write to.
385 """
386 if not decoder.primary: raise Exception('No tables provided.')
387 assert filename.endswith('_decoder.h')
388
389 values = {
390 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
391 'NOT_TCB_MESSAGE' : dgen_output.NOT_TCB_BOILERPLATE,
392 'IFDEF_NAME' : dgen_output.ifdef_name(filename),
393 'FILENAME_BASE': filename[:-len('_decoder.h')],
394 'decoder_name': decoder_name,
395 }
396 out.write(NAMED_DECODER_H_HEADER % values)
397 _generate_decoder_state_class(decoder, values, out)
398 out.write(NAMED_DECODER_H_FOOTER % values)
399
400 def _generate_decoder_state_class(decoder, values, out):
401 # Generate a field for each type of decoder in the decoder.
402 out.write(DECODER_STATE_HEADER % values)
403 out.write(DECODER_STATE_FIELD_COMMENTS);
404 for d in decoder.action_filter(['name']).decoders():
405 values['decoder'] = d.name
406 values['rule'] = ''
407 out.write(DECODER_STATE_FIELD % values)
408 # Now generate one for each decoder that has a rule associated with it.
409 for d in decoder.action_filter(['name', 'rule']).rules():
410 values['decoder'] = d.name
411 values['rule'] = d.rule
412 out.write(DECODER_STATE_FIELD % values)
413 out.write(DECODER_STATE_PRIVATE);
414 out.write(DECODER_STATE_DECODER_COMMENTS)
415 for table in decoder.tables():
416 values['table'] = table.name
417 out.write(DECODER_STATE_DECODER % values)
418 out.write(DECODER_STATE_FOOTER % values)
419
420 # Defines the source for DECODER_named.cc
421 NAMED_CC_HEADER="""
422 %(FILE_HEADER)s
423 %(NOT_TCB_MESSAGE)s
424 #include "%(FILENAME_BASE)s_decoder.h"
425
426 #include <stdio.h>
427
428 using nacl_arm_dec::ClassDecoder;
429 using nacl_arm_dec::Instruction;
430
431 namespace nacl_arm_test {
432 """
433
434 PARSE_CONSTRUCT_HEADER="""
435 Named%(decoder_name)s::Named%(decoder_name)s()
436 : nacl_arm_dec::DecoderState()
437 """
438
439 PARSE_CONSTRUCT_FIELDS="""
440 , %(rule)s%(decoder)s_instance_()
441 """
442
443 PARSE_CONSTRUCT_FOOTER="""
444 {}
445
446 Named%(decoder_name)s::~Named%(decoder_name)s() {}
447 """
448
449 PARSE_TABLE_METHOD_HEADER="""
450 /*
451 * Implementation of table %(table_name)s.
452 * Specified by: %(citation)s
453 */
454 const NamedClassDecoder& Named%(decoder_name)s::decode_%(table_name)s(
455 const nacl_arm_dec::Instruction insn) const {
456 """
457
458 PARSE_TABLE_METHOD_ROW="""
459 if (%(tests)s) {
460 return %(action)s;
461 }
462 """
463
464 PARSE_TABLE_METHOD_FOOTER="""
465 // Catch any attempt to fall through...
466 fprintf(stderr, "TABLE IS INCOMPLETE: %(table_name)s could not parse %%08X",
467 insn.bits(31,0));
468 return Forbidden_instance_;
469 }
470
471 """
472
473 NAMED_CC_FOOTER="""
474 const NamedClassDecoder& Named%(decoder_name)s::
475 decode_named(const nacl_arm_dec::Instruction insn) const {
476 return decode_%(entry_table_name)s(insn);
477 }
478
479 const nacl_arm_dec::ClassDecoder& Named%(decoder_name)s::
480 decode(const nacl_arm_dec::Instruction insn) const {
481 return decode_named(insn).named_decoder();
482 }
483
484 } // namespace nacl_arm_test
485 """
486
487 def generate_named_cc(decoder, decoder_name, filename, out):
488 """Implementation of the test decoder in .cc file
489
490 Args:
491 tables: list of Table objects to process.
492 decoder_name: The name of the decoder state to build.
493 filename: The (localized) name for the .h file.
494 out: a COutput object to write to.
495 """
496 if not decoder.primary: raise Exception('No tables provided.')
497 assert filename.endswith('.cc')
498
499 values = {
500 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
501 'NOT_TCB_MESSAGE' : dgen_output.NOT_TCB_BOILERPLATE,
502 'FILENAME_BASE' : filename[:-len('.cc')],
503 'decoder_name': decoder_name,
504 'entry_table_name': decoder.primary.name,
505 }
506 out.write(NAMED_CC_HEADER % values)
507 _generate_decoder_constructors(decoder, values, out)
508 _generate_decoder_method_bodies(decoder, values, out)
509 out.write(NAMED_CC_FOOTER % values)
510
511 def _generate_decoder_constructors(decoder, values, out):
512 out.write(PARSE_CONSTRUCT_HEADER % values)
513 # Initialize each type of decoder in the decoder.
514 for d in decoder.action_filter(['name']).decoders():
515 values['decoder'] = d.name
516 values['rule'] = ''
517 out.write(PARSE_CONSTRUCT_FIELDS % values)
518 # Now initialize fields for each decoder with a rule.
519 for d in decoder.action_filter(['name', 'rule']).rules():
520 values['decoder'] = d.name
521 values['rule'] = d.rule
522 out.write(PARSE_CONSTRUCT_FIELDS % values)
523 out.write(PARSE_CONSTRUCT_FOOTER % values)
524
525 def _generate_decoder_method_bodies(decoder, values, out):
526 for table in decoder.tables():
527 opt_rows = dgen_opt.optimize_rows(
528 table.action_filter(['name', 'rule']).rows)
529 print ("Table %s: %d rows minimized to %d"
530 % (table.name, len(table.rows), len(opt_rows)))
531
532 values['table_name'] = table.name
533 values['citation'] = table.citation,
534 out.write(PARSE_TABLE_METHOD_HEADER % values)
535
536 # Add message to stop compilation warnings if this table
537 # doesn't require subtables to select a class decoder.
538 if not [r for r in opt_rows
539 if r.action.__class__.__name__ == 'DecoderMethod']:
540 out.write(" UNREFERENCED_PARAMETER(insn);")
541
542 for row in opt_rows:
543 if row.action.__class__.__name__ == 'DecoderAction':
544 values['decoder'] = row.action.name
545 values['rule'] = row.action.rule if row.action.rule else ''
546 action = '%(rule)s%(decoder)s_instance_' % values
547 elif row.action.__class__.__name__ == 'DecoderMethod':
548 action = 'decode_%s(insn)' % row.action.name
549 else:
550 raise Exception('Bad table action: %s' % row.action)
551 # Each row consists of a set of bit patterns defining if the row
552 # is applicable. Convert this into a sequence of anded C test
553 # expressions. For example, convert the following pair of bit
554 # patterns:
555 #
556 # xxxx1010xxxxxxxxxxxxxxxxxxxxxxxx
557 # xxxxxxxxxxxxxxxxxxxxxxxxxxxx0101
558 #
559 # Each instruction is masked to get the the bits, and then
560 # tested against the corresponding expected bits. Hence, the
561 # above example is converted to:
562 #
563 # ((insn & 0x0F000000) != 0x0C000000) &&
564 # ((insn & 0x0000000F) != 0x00000005)
565 values['tests'] = ' && '.join(['(%s)' % p.to_c_expr('insn')
566 for p in row.patterns])
567 values['action'] = action
568 out.write(PARSE_TABLE_METHOD_ROW % values)
569 out.write(PARSE_TABLE_METHOD_FOOTER % values)
570
571 # Define the source for DECODER_tests.cc
572 TEST_CC_HEADER="""
573 %(FILE_HEADER)s
574 %(NOT_TCB_MESSAGE)s
575
576 #include "gtest/gtest.h"
577 #include "native_client/src/trusted/validator_arm/inst_classes_testers.h"
578
579 namespace nacl_arm_test {
580
581 """
582
583 TESTER_CLASS="""
584 class %(rule)s%(decoder)sTester%(constraints)s
585 : public %(decoder)sTester%(constraints)s {
586 public:
587 %(rule)s%(decoder)sTester%(constraints)s()
588 : %(decoder)sTester%(constraints)s(
589 state_.%(rule)s%(decoder)s_instance_)
590 {}
591 };
592 """
593
594 TEST_HARNESS="""
595 // Defines a gtest testing harness for tests.
596 class %(decoder_name)sTests : public ::testing::Test {
597 protected:
598 %(decoder_name)sTests() {}
599 };
600 """
601
602 TEST_FUNCTION="""
603 TEST_F(%(decoder_name)sTests,
604 %(rule)s%(decoder)s%(constraints)s_%(pattern)s_Test) {
605 %(rule)s%(decoder)sTester%(constraints)s tester;
606 tester.Test("%(pattern)s");
607 }
608 """
609
610
611 TEST_CC_FOOTER="""
612 } // namespace nacl_arm_test
613
614 int main(int argc, char* argv[]) {
615 testing::InitGoogleTest(&argc, argv);
616 return RUN_ALL_TESTS();
617 }
618 """
619
620 def generate_tests_cc(decoder, decoder_name, out):
621 if not decoder.primary: raise Exception('No tables provided.')
622 values = {
623 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
624 'NOT_TCB_MESSAGE' : dgen_output.NOT_TCB_BOILERPLATE,
625 'decoder_name': decoder_name,
626 }
627 out.write(TEST_CC_HEADER % values)
628 _generate_rule_testers(decoder, values, out)
629 out.write(TEST_HARNESS % values)
630 _generate_test_patterns(decoder, values, out)
631 out.write(TEST_CC_FOOTER % values)
632
633 def _generate_rule_testers(decoder, values, out):
634 for d in decoder.action_filter(['name', 'rule', 'constraints']).rules():
635 values['decoder'] = d.name
636 values['rule'] = d.rule
637 values['constraints'] = d.constraints if d.constraints else ''
638 out.write(TESTER_CLASS % values)
639
640 def _generate_test_patterns(decoder, values, out):
641 for d in decoder.decoders():
642 if d.pattern:
643 values['decoder'] = d.name
644 values['rule'] = d.rule if d.rule else ''
645 values['constraints'] = d.constraints if d.constraints else ''
646 values['pattern'] = d.pattern
647 out.write(TEST_FUNCTION % values)
OLDNEW
« no previous file with comments | « src/trusted/validator_arm/dgen_output.py ('k') | src/trusted/validator_arm/generate_decoder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698