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_sign_convert_array_value(self): t = ArrayType(BitsType(signed=True, size=8), 3) self.assertEqual( sample_runner.sign_convert_value( t, Value.make_array((Value.make_ubits(8, 0x42), Value.make_ubits(8, 0x43), Value.make_ubits(8, 0x44)))), Value.make_array((Value.make_sbits(8, 0x42), Value.make_sbits(8, 0x43), Value.make_sbits(8, 0x44))))
def test_bits_value_hex(self): self.assertEqual(value_from_string('bits[3]:0x7'), Value.make_ubits(bit_count=3, value=7)) self.assertEqual(value_from_string('bits[1]:0x1'), Value.make_ubits(bit_count=1, value=1)) self.assertEqual(value_from_string('bits[1]:0x0'), Value.make_ubits(bit_count=1, value=0)) self.assertEqual(value_from_string('bits[8]:0xff'), Value.make_ubits(bit_count=8, value=0xff)) self.assertEqual(value_from_string('u8:0xff'), Value.make_ubits(bit_count=8, value=0xff))
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_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_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_array_values(self): self.assertEqual( value_from_string('[(u8:0xff, u2:0x1), (u8:0, u2:3)]'), Value.make_array(( Value.make_tuple(( Value.make_ubits(bit_count=8, value=0xff), Value.make_ubits(bit_count=2, value=1), )), Value.make_tuple(( Value.make_ubits(bit_count=8, value=0x0), Value.make_ubits(bit_count=2, value=3), )), )))
def test_sign_convert_tuple_value(self): # type is (u8, (u16, s8) t = TupleType( (BitsType(signed=False, size=8), TupleType( (BitsType(signed=False, size=16), BitsType(signed=True, size=8))))) self.assertEqual( sample_runner.sign_convert_value( t, Value.make_tuple((Value.make_ubits(8, 0x42), Value.make_tuple((Value.make_ubits(16, 0x33), Value.make_ubits(8, 0x44)))))), Value.make_tuple( (Value.make_ubits(8, 0x42), Value.make_tuple( (Value.make_ubits(16, 0x33), Value.make_sbits(8, 0x44))))))
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_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 test_tuple_values(self): self.assertEqual( value_from_string('(bits[8]:0xff, bits[2]:0x1)'), Value.make_tuple(( Value.make_ubits(bit_count=8, value=0xff), Value.make_ubits(bit_count=2, value=1), ))) self.assertEqual(value_from_string('()'), Value.make_tuple(())) # Tuple of single element. want = Value.make_tuple((Value.make_ubits(bit_count=2, value=1),)) got = value_from_string('(bits[2]:0x1,)') self.assertEqual(want, got) with self.assertRaises(ValueParseError) as cm: value_from_string('(,)') self.assertIn('Unexpected token in value', str(cm.exception))
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_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_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_ubits(100, 10**30), Value.make_ubits(100, 10**30)], [Value.make_ubits(100, 2**80), Value.make_ubits(100, 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_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_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_parse_args(self): self.assertEqual(sample.parse_args(''), tuple()) self.assertEqual(sample.parse_args('bits[8]:42'), (Value.make_ubits(8, 42), )) self.assertEqual(sample.parse_args('bits[8]:42; bits[16]:1234'), (Value.make_ubits(8, 42), Value.make_ubits(16, 1234))) self.assertEqual( sample.parse_args( 'bits[8]:42; (bits[8]:0x42, (bits[16]:0x33, bits[8]:0x44))'), (Value.make_ubits(8, 42), Value.make_tuple((Value.make_ubits(8, 0x42), Value.make_tuple((Value.make_ubits( 16, 0x33), Value.make_ubits(8, 0x44))))))) self.assertEqual( sample.parse_args('[bits[8]:0x42, bits[8]:0x43, bits[8]:0x44]'), (Value.make_array( tuple(Value.make_ubits(8, v) for v in (0x42, 0x43, 0x44))), ))
def ir_value_to_interpreter_value(value: ir_value_mod.Value) -> Value: """Converts an IR Value to an interpreter Value.""" if value.is_bits(): if value.get_bits().bit_count() <= 64: return Value.make_ubits(value.get_bits().bit_count(), value.get_bits().to_uint()) else: # For wide values which do not fit in 64 bits, parse value as as string. return value_from_string(value.to_str(FormatPreference.HEX)) elif value.is_array(): return Value.make_array( tuple(ir_value_to_interpreter_value(e) for e in value.get_elements())) else: assert value.is_tuple() return Value.make_tuple( tuple(ir_value_to_interpreter_value(e) for e in value.get_elements()))
def test_sign_convert_args_batch(self): dslx_text = 'fn main(y: s8) -> s8 { y }' filename = '/fake/test_module.x' with fakefs_util.scoped_fakefs(filename, dslx_text): m = parser_helpers.parse_text( dslx_text, 'test_module', print_on_error=True, filename=filename) f = m.get_function('main') self.assertEqual( sample_runner.sign_convert_args_batch(f, m, ((Value.make_ubits(8, 2),),)), ((Value.make_sbits(8, 2),),)) # Converting a value which is already signed is no problem. self.assertEqual( sample_runner.sign_convert_args_batch(f, m, ((Value.make_sbits(8, 2),),)), ((Value.make_sbits(8, 2),),))