def test_evaluate_ir_wide(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: bits[100], y: bits[100]) -> bits[100] { x + y }' runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False), [[ interp_value_from_ir_string( 'bits[100]:{0:#x}'.format(10**30)), interp_value_from_ir_string( 'bits[100]:{0:#x}'.format(10**30)), ], [ interp_value_from_ir_string( 'bits[100]:{0:#x}'.format(2**80)), interp_value_from_ir_string( 'bits[100]:{0:#x}'.format(2**81)), ]])) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.x.results'), [ 'bits[100]:0x9_3e59_39a0_8ce9_dbd4_8000_0000', 'bits[100]:0x3_0000_0000_0000_0000_0000' ]) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.ir.results'), [ 'bits[100]:0x9_3e59_39a0_8ce9_dbd4_8000_0000', 'bits[100]:0x3_0000_0000_0000_0000_0000' ])
def test_dslx_to_ir(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False))) self.assertIn('package sample', _read_file(sample_dir, 'sample.ir'))
def test_evaluate_ir_wide(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: bits[100], y: bits[100]) -> bits[100] { x + y }' runner.run( sample.Sample( dslx_text, sample.SampleOptions(optimize_ir=False), [[ Value.make_bits(Tag.UBITS, ir_bits.from_long(10**30, bit_count=100)), Value.make_bits(Tag.UBITS, ir_bits.from_long(10**30, bit_count=100)) ], [ Value.make_bits(Tag.UBITS, ir_bits.from_long(2**80, bit_count=100)), Value.make_bits(Tag.UBITS, ir_bits.from_long(2**81, bit_count=100)) ]])) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.x.results'), [ 'bits[100]:0x9_3e59_39a0_8ce9_dbd4_8000_0000', 'bits[100]:0x3_0000_0000_0000_0000_0000' ]) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.ir.results'), [ 'bits[100]:0x9_3e59_39a0_8ce9_dbd4_8000_0000', 'bits[100]:0x3_0000_0000_0000_0000_0000' ])
def run_sample(smp: sample.Sample, run_dir: Text, summary_file: Optional[Text] = None, generate_sample_ns: Optional[int] = None): """Runs the given sample in the given directory. Args: smp: Sample to run. run_dir: Directory to run the sample in. The directory should exist and be empty. summary_file: The (optional) file to append sample summary. generate_sample_ns: The (optional) time in nanoseconds to generate the sample. Recorded in the summary file, if given. Raises: sample_runner.SampleError: on any non-zero status from the sample runner. """ start = time.time() _write_to_file(run_dir, 'sample.x', smp.input_text) _write_to_file(run_dir, 'options.json', smp.options.to_json()) if smp.args_batch: _write_to_file(run_dir, 'args.txt', sample.args_batch_to_text(smp.args_batch)) # Create a script named 'run.sh' for rerunning the sample. args = [ SAMPLE_RUNNER_MAIN_PATH, '--logtostderr', '--input_file=sample.x', '--options_file=options.json' ] if smp.args_batch: args.append('--args_file=args.txt') args.append(run_dir) _write_to_file(run_dir, 'run.sh', f'#!/bin/sh\n\n{subprocess.list2cmdline(args)}\n', executable=True) logging.vlog(1, 'Starting to run sample') logging.vlog(2, smp.input_text) runner = sample_runner.SampleRunner(run_dir) runner.run_from_files('sample.x', 'options.json', 'args.txt') timing = runner.timing timing.total_ns = int((time.time() - start) * 1e9) if generate_sample_ns: # The sample generation time, if given, is not part of the measured total # time, so add it in. timing.total_ns += generate_sample_ns timing.generate_sample_ns = generate_sample_ns logging.vlog(1, 'Completed running sample, elapsed: %0.2fs', time.time() - start) if summary_file: _write_ir_summaries(run_dir, timing, summary_file)
def run(run_dir: Text): """Runs the sample in the given run directory.""" runner = sample_runner.SampleRunner(run_dir) input_filename = maybe_copy_file(FLAGS.input_file, run_dir) options_filename = maybe_copy_file(FLAGS.options_file, run_dir) if FLAGS.args_file: args_filename = maybe_copy_file(FLAGS.args_file, run_dir) else: args_filename = None runner.run_from_files(input_filename, options_filename, args_filename)
def test_interpret_mixed_signedness(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: s8) -> s8 { (x as s8) + y }' runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False), [[Value.make_ubits(8, 42), Value.make_sbits(8, 100)]])) self.assertEqual( _read_file(sample_dir, 'sample.x.results').strip(), 'bits[8]:0x8e')
def test_interpret_mixed_signedness_unsigned_inputs(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: s8) -> s8 { (x as s8) + y }' runner.run( sample.Sample( dslx_text, sample.SampleOptions(optimize_ir=False), sample.parse_args_batch('bits[8]:0xb0; bits[8]:0x0a'))) self.assertEqual( _read_file(sample_dir, 'sample.x.results').strip(), 'bits[8]:0xba')
def test_interpret_dslx_single_value(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample(dslx_text, sample.SampleOptions(convert_to_ir=False), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) self.assertEqual( _read_file(sample_dir, 'sample.x.results').strip(), 'bits[8]:0x8e')
def test_bad_ir_input(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) ir_text = """bogus ir string""" with self.assertRaises(sample_runner.SampleError): runner.run( sample.Sample(ir_text, sample.SampleOptions(input_is_dslx=False))) self.assertIn('Expected \'package\' keyword', _read_file(sample_dir, 'opt_main.stderr')) self.assertRegex(_read_file(sample_dir, 'exception.txt'), '.*opt_main.*returned non-zero exit status')
def test_interpret_mixed_signedness(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: s8) -> s8 { (x as s8) + y }' runner.run( sample.Sample( dslx_text, sample.SampleOptions(optimize_ir=False), [[ interp_value_from_ir_string('bits[8]:42'), interp_value_from_ir_string('bits[8]:100').to_signed() ]])) self.assertEqual( _read_file(sample_dir, 'sample.x.results').strip(), 'bits[8]:0x8e')
def test_interpret_opt_ir(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample(dslx_text, sample.SampleOptions(), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) self.assertIn('package sample', _read_file(sample_dir, 'sample.opt.ir')) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.opt.ir.results'), ['bits[8]:0x8e'])
def test_interpret_invalid_dslx(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'syntaxerror!!! fn main(x: u8, y: u8) -> u8 { x + y }' with self.assertRaises(sample_runner.SampleError): runner.run( sample.Sample( dslx_text, sample.SampleOptions(convert_to_ir=False), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) # Verify the exception text is written out to file. self.assertIn('Expected start of top-level construct', _read_file(sample_dir, 'exception.txt'))
def test_interpret_dslx_multiple_values(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample( dslx_text, sample.SampleOptions(convert_to_ir=False), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)], [Value.make_ubits(8, 222), Value.make_ubits(8, 240)]])) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.x.results'), ['bits[8]:0x8e', 'bits[8]:0xce'])
def test_evaluate_ir_miscompare_single_result(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner._evaluate_ir = lambda *args: (Value.make_ubits(8, 1), ) with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample( dslx_text, sample.SampleOptions(optimize_ir=False), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) self.assertIn('Result miscompare for sample 0', str(e.exception)) self.assertIn('Result miscompare for sample 0', _read_file(sample_dir, 'exception.txt'))
def test_evaluate_ir_miscompare_number_of_results(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner._evaluate_ir = lambda *args: (Value.make_ubits(8, 100), ) with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False), [])) self.assertIn( 'Results for interpreted DSLX has 0 values, evaluated unopt IR (interpreter) has 1', str(e.exception)) self.assertIn( 'Results for interpreted DSLX has 0 values, evaluated unopt IR (interpreter) has 1', _read_file(sample_dir, 'exception.txt'))
def test_codegen_combinational_wrong_results(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) runner._simulate = lambda *args: (Value.make_ubits(8, 1), ) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample( dslx_text, sample.SampleOptions( codegen=True, codegen_args=['--generator=combinational'], simulate=True, simulator='iverilog'), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) self.assertIn('Result miscompare for sample 0', str(e.exception))
def test_interpret_dslx_multiple_values(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample(dslx_text, sample.SampleOptions(convert_to_ir=False), [[ interp_value_from_ir_string('bits[8]:42'), interp_value_from_ir_string('bits[8]:100') ], [ interp_value_from_ir_string('bits[8]:222'), interp_value_from_ir_string('bits[8]:240') ]])) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.x.results'), ['bits[8]:0x8e', 'bits[8]:0xce'])
def test_ir_input(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) ir_text = """package foo fn foo(x: bits[8], y: bits[8]) -> bits[8] { ret add.1: bits[8] = add(x, y) } """ runner.run( sample.Sample(ir_text, sample.SampleOptions(input_is_dslx=False), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) self.assertIn('package foo', _read_file(sample_dir, 'sample.ir')) self.assertIn('package foo', _read_file(sample_dir, 'sample.opt.ir')) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.opt.ir.results'), ['bits[8]:0x8e'])
def test_codegen_pipeline(self): sample_dir = self._make_sample_dir() print('sample_dir = ' + sample_dir) runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample( dslx_text, sample.SampleOptions(codegen=True, codegen_args=('--generator=pipeline', '--pipeline_stages=2'), simulate=True), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) # A pipelined block should have a blocking assignment. self.assertIn('<=', _read_file(sample_dir, 'sample.v')) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.v.results'), ['bits[8]:0x8e'])
def run_sample(smp: sample.Sample, run_dir: Text, summary_file: Optional[Text] = None): """Runs the given sample in the given directory. Args: smp: Sample to run. run_dir: Directory to run the sample in. The directory should exist and be empty. summary_file: The (optional) file to append sample summary. Raises: sample_runner.SampleError: on any non-zero status from the sample runner. """ _write_to_file(run_dir, 'sample.x', smp.input_text) _write_to_file(run_dir, 'options.json', smp.options.to_json()) if smp.args_batch: _write_to_file(run_dir, 'args.txt', sample.args_batch_to_text(smp.args_batch)) # Create a script named 'run.sh' for rerunning the sample. args = [ SAMPLE_RUNNER_MAIN_PATH, '--logtostderr', '--input_file=sample.x', '--options_file=options.json' ] if smp.args_batch: args.append('--args_file=args.txt') args.append(run_dir) _write_to_file(run_dir, 'run.sh', f'#!/bin/sh\n\n{subprocess.list2cmdline(args)}\n', executable=True) start = time.time() logging.vlog(1, 'Starting to run sample') logging.vlog(2, smp.input_text) runner = sample_runner.SampleRunner(run_dir) runner.run_from_files('sample.x', 'options.json', 'args.txt') logging.vlog(1, 'Completed running sample, elapsed: %0.2fs', time.time() - start) if summary_file: _write_ir_summaries(run_dir, summary_file)
def test_codegen_combinational(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner.run( sample.Sample( dslx_text, sample.SampleOptions( codegen=True, codegen_args=['--generator=combinational'], simulate=True), [[Value.make_ubits(8, 42), Value.make_ubits(8, 100)]])) self.assertIn('endmodule', _read_file(sample_dir, 'sample.v')) # A combinational block should not have a blocking assignment. self.assertNotIn('<=', _read_file(sample_dir, 'sample.v')) self.assertSequenceEqual( _split_nonempty_lines(sample_dir, 'sample.v.results'), ['bits[8]:0x8e'])
def test_evaluate_ir_miscompare_number_of_results(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' # Give back two results instead of one. def fake_evaluate_ir(*_): return (Value.make_ubits(8, 100), Value.make_ubits(8, 100)) runner._evaluate_ir = fake_evaluate_ir args_batch = [(Value.make_ubits(8, 42), Value.make_ubits(8, 64))] with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False), args_batch)) self.assertIn( 'Results for evaluated unopt IR (JIT) has 2 values, interpreted DSLX has 1', str(e.exception)) self.assertIn( 'Results for evaluated unopt IR (JIT) has 2 values, interpreted DSLX has 1', _read_file(sample_dir, 'exception.txt'))
def test_interpret_opt_ir_miscompare(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' results = [ (Value.make_ubits(8, 100), ), # correct result (Value.make_ubits(8, 100), ), # correct result (Value.make_ubits(8, 0), ), # incorrect result ] def result_gen(*_): return results.pop(0) runner._evaluate_ir = result_gen with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample( dslx_text, sample.SampleOptions(), [[Value.make_ubits(8, 40), Value.make_ubits(8, 60)]])) self.assertIn('Result miscompare for sample 0', str(e.exception)) self.assertIn('evaluated opt IR (JIT)', str(e.exception))
def test_evaluate_ir_miscompare_single_result(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' runner._evaluate_ir = lambda *args: (interp_value_from_ir_string( 'bits[8]:1'), ) with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False), [[ interp_value_from_ir_string('bits[8]:42'), interp_value_from_ir_string('bits[8]:100') ]])) self.assertIn( 'Result miscompare for sample 0:\n' 'args: bits[8]:0x2a; bits[8]:0x64\n' 'evaluated unopt IR (JIT), evaluated unopt IR (interpreter) =\n' ' bits[8]:0x1\n' 'interpreted DSLX =\n' ' bits[8]:0x8e', str(e.exception)) self.assertIn('Result miscompare for sample 0', _read_file(sample_dir, 'exception.txt'))
def test_evaluate_ir_miscompare_multiple_results(self): sample_dir = self._make_sample_dir() runner = sample_runner.SampleRunner(sample_dir) dslx_text = 'fn main(x: u8, y: u8) -> u8 { x + y }' results = (interp_value_from_ir_string('bits[8]:100'), interp_value_from_ir_string('bits[8]:1')) runner._evaluate_ir = lambda *args: results with self.assertRaises(sample_runner.SampleError) as e: runner.run( sample.Sample(dslx_text, sample.SampleOptions(optimize_ir=False), [[ interp_value_from_ir_string('bits[8]:40'), interp_value_from_ir_string('bits[8]:60') ], [ interp_value_from_ir_string('bits[8]:2'), interp_value_from_ir_string('bits[8]:1') ]])) self.assertIn('Result miscompare for sample 1', str(e.exception)) self.assertIn('Result miscompare for sample 1', _read_file(sample_dir, 'exception.txt'))