import operator import re from amaranth.back import rtlil from amaranth.hdl import * from amaranth.hdl._ast import * from amaranth.lib import memory, wiring, data, enum from .utils import * class RTLILTestCase(FHDLTestCase): maxDiff = 10000 def assertRTLIL(self, fragment, ports, rtlil_gold): rtlil_test = rtlil.convert(fragment, ports=ports, emit_src=False) def normalize(s): s = s.strip() s = re.sub(r" +", " ", s) s = re.sub(r"\n ", "\n", s) s = re.sub(r"\n+", "\n", s) return s + "\n" self.assertEqual(normalize(rtlil_test), normalize(rtlil_gold)) class TreeTestCase(RTLILTestCase): def test_tree(self): a = Signal() b = Signal() c = Signal() m = Module() m.submodules.m1 = m1 = Module() m.submodules.m2 = m2 = Module() m.submodules.m3 = m3 = Module() m3.submodules.m4 = m4 = Module() m1.d.comb += a.eq(~b) m2.d.comb += b.eq(~c) self.assertRTLIL(m, [a, c], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 1 \b wire width 1 input 0 \c wire width 1 output 1 \a cell \top.m1 \m1 connect \a \a [0] connect \b \b [0] end cell \top.m2 \m2 connect \c \c [0] connect \b \b [0] end end attribute \generator "Amaranth" module \top.m1 wire width 1 output 0 \a wire width 1 input 1 \b cell $not $1 parameter \A_SIGNED 0 parameter \A_WIDTH 1 parameter \Y_WIDTH 1 connect \A \b [0] connect \Y \a end end attribute \generator "Amaranth" module \top.m2 wire width 1 input 0 \c wire width 1 output 1 \b cell $not $1 parameter \A_SIGNED 0 parameter \A_WIDTH 1 parameter \Y_WIDTH 1 connect \A \c [0] connect \Y \b end end """) class RHSTestCase(RTLILTestCase): def test_operator_unary(self): i8u = Signal(8) i8s = Signal(signed(8)) o1 = Signal(10) o2 = Signal(10) o3 = Signal(10) o4 = Signal(10) o5 = Signal(10) o6 = Signal(10) o7 = Signal(10) o8 = Signal(10) m = Module() m.d.comb += [ o1.eq(-i8u), o2.eq(-i8s), o3.eq(~i8u), o4.eq(~i8s), o5.eq(i8u.bool()), o6.eq(i8u.all()), o7.eq(i8u.any()), o8.eq(i8u.xor()), ] self.assertRTLIL(m, [i8u, i8s, o1, o2, o3, o4, o5, o6, o7, o8], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8u wire width 8 input 1 signed \i8s wire width 10 output 2 \o1 wire width 10 output 3 \o2 wire width 10 output 4 \o3 wire width 10 output 5 \o4 wire width 10 output 6 \o5 wire width 10 output 7 \o6 wire width 10 output 8 \o7 wire width 10 output 9 \o8 wire width 9 $1 wire width 9 $2 wire width 8 $3 wire width 8 $4 wire width 1 $5 wire width 1 $6 wire width 1 $7 wire width 1 $8 cell $neg $9 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 9 connect \A \i8u [7:0] connect \Y $1 end cell $neg $10 parameter \A_SIGNED 1 parameter \A_WIDTH 8 parameter \Y_WIDTH 9 connect \A \i8s [7:0] connect \Y $2 end cell $not $11 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 8 connect \A \i8u [7:0] connect \Y $3 end cell $not $12 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 8 connect \A \i8s [7:0] connect \Y $4 end cell $reduce_bool $13 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8u [7:0] connect \Y $5 end cell $reduce_and $14 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8u [7:0] connect \Y $6 end cell $reduce_or $15 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8u [7:0] connect \Y $7 end cell $reduce_xor $16 parameter \A_SIGNED 0 parameter \A_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8u [7:0] connect \Y $8 end connect \o1 { $1 [8] $1 [8:0] } connect \o2 { $2 [8] $2 [8:0] } connect \o3 { 2'00 $3 [7:0] } connect \o4 { $4 [7] $4 [7] $4 [7:0] } connect \o5 { 9'000000000 $5 [0] } connect \o6 { 9'000000000 $6 [0] } connect \o7 { 9'000000000 $7 [0] } connect \o8 { 9'000000000 $8 [0] } end """) def test_operator_addsub(self): i8ua = Signal(8) i8ub = Signal(8) i8sa = Signal(signed(8)) i8sb = Signal(signed(8)) o1 = Signal(10) o2 = Signal(10) o3 = Signal(10) o4 = Signal(10) o5 = Signal(10) o6 = Signal(10) m = Module() m.d.comb += [ o1.eq(i8ua + i8ub), o2.eq(i8ua + i8sb), o3.eq(i8sa + i8sb), o4.eq(i8ua - i8ub), o5.eq(i8ua - i8sb), o6.eq(i8sa - i8sb), ] self.assertRTLIL(m, [i8ua, i8ub, i8sa, i8sb, o1, o2, o3, o4, o5, o6], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 \i8ub wire width 8 input 2 signed \i8sa wire width 8 input 3 signed \i8sb wire width 10 output 4 \o1 wire width 10 output 5 \o2 wire width 10 output 6 \o3 wire width 10 output 7 \o4 wire width 10 output 8 \o5 wire width 10 output 9 \o6 wire width 9 $1 wire width 9 $2 wire width 9 $3 wire width 9 $4 cell $add $5 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 9 connect \A \i8ua [7:0] connect \B \i8ub [7:0] connect \Y $1 end cell $add $6 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 9 parameter \B_WIDTH 8 parameter \Y_WIDTH 10 connect \A { 1'0 \i8ua [7:0] } connect \B \i8sb [7:0] connect \Y \o2 end cell $add $7 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 9 connect \A \i8sa [7:0] connect \B \i8sb [7:0] connect \Y $2 end cell $sub $8 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 9 connect \A \i8ua [7:0] connect \B \i8ub [7:0] connect \Y $3 end cell $sub $9 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 9 parameter \B_WIDTH 8 parameter \Y_WIDTH 10 connect \A { 1'0 \i8ua [7:0] } connect \B \i8sb [7:0] connect \Y \o5 end cell $sub $10 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 9 connect \A \i8sa [7:0] connect \B \i8sb [7:0] connect \Y $4 end connect \o1 { 1'0 $1 [8:0] } connect \o3 { $2 [8] $2 [8:0] } connect \o4 { $3 [8] $3 [8:0] } connect \o6 { $4 [8] $4 [8:0] } end """) def test_operator_add_imm(self): i8u = Signal(8) i8s = Signal(signed(8)) o1 = Signal(10) o2 = Signal(10) o3 = Signal(10) o4 = Signal(10) m = Module() m.d.comb += [ o1.eq(i8u + 3), o2.eq(i8s + 3), o3.eq(3 + i8u), o4.eq(3 + i8s), ] self.assertRTLIL(m, [i8u, i8s, o1, o2, o3, o4], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8u wire width 8 input 1 signed \i8s wire width 10 output 2 \o1 wire width 10 output 3 \o2 wire width 10 output 4 \o3 wire width 10 output 5 \o4 wire width 9 $1 wire width 9 $2 wire width 9 $3 wire width 9 $4 cell $add $5 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 2 parameter \Y_WIDTH 9 connect \A \i8u [7:0] connect \B 2'11 connect \Y $1 end cell $add $6 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 9 connect \A \i8s [7:0] connect \B 3'011 connect \Y $2 end cell $add $7 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 2 parameter \B_WIDTH 8 parameter \Y_WIDTH 9 connect \A 2'11 connect \B \i8u [7:0] connect \Y $3 end cell $add $8 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 3 parameter \B_WIDTH 8 parameter \Y_WIDTH 9 connect \A 3'011 connect \B \i8s [7:0] connect \Y $4 end connect \o1 { 1'0 $1 [8:0] } connect \o2 { $2 [8] $2 [8:0] } connect \o3 { 1'0 $3 [8:0] } connect \o4 { $4 [8] $4 [8:0] } end """) def test_operator_mul(self): i4ua = Signal(4) i4ub = Signal(4) i4sa = Signal(signed(4)) i4sb = Signal(signed(4)) o1 = Signal(9) o2 = Signal(9) o3 = Signal(9) m = Module() m.d.comb += [ o1.eq(i4ua * i4ub), o2.eq(i4ua * i4sb), o3.eq(i4sa * i4sb), ] self.assertRTLIL(m, [i4ua, i4ub, i4sa, i4sb, o1, o2, o3], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 4 input 0 \i4ua wire width 4 input 1 \i4ub wire width 4 input 2 signed \i4sa wire width 4 input 3 signed \i4sb wire width 9 output 4 \o1 wire width 9 output 5 \o2 wire width 9 output 6 \o3 wire width 8 $1 wire width 8 $2 wire width 8 $3 cell $mul $4 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 4 parameter \B_WIDTH 4 parameter \Y_WIDTH 8 connect \A \i4ua [3:0] connect \B \i4ub [3:0] connect \Y $1 end cell $mul $5 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 5 parameter \B_WIDTH 4 parameter \Y_WIDTH 8 connect \A { 1'0 \i4ua [3:0] } connect \B \i4sb [3:0] connect \Y $2 end cell $mul $6 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 4 parameter \B_WIDTH 4 parameter \Y_WIDTH 8 connect \A \i4sa [3:0] connect \B \i4sb [3:0] connect \Y $3 end connect \o1 { 1'0 $1 [7:0] } connect \o2 { $2 [7] $2 [7:0] } connect \o3 { $3 [7] $3 [7:0] } end """) def test_operator_divmod(self): i4ua = Signal(4) i4ub = Signal(4) i4sa = Signal(signed(4)) i4sb = Signal(signed(4)) o1 = Signal(6) o2 = Signal(6) o3 = Signal(6) o4 = Signal(6) o5 = Signal(6) o6 = Signal(6) o7 = Signal(6) o8 = Signal(6) m = Module() m.d.comb += [ o1.eq(i4ua // i4ub), o2.eq(i4ua // i4sb), o3.eq(i4sa // i4ub), o4.eq(i4sa // i4sb), o5.eq(i4ua % i4ub), o6.eq(i4ua % i4sb), o7.eq(i4sa % i4ub), o8.eq(i4sa % i4sb), ] self.assertRTLIL(m, [i4ua, i4ub, i4sa, i4sb, o1, o2, o3, o4, o5, o6, o7, o8], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 4 input 0 \i4ua wire width 4 input 1 \i4ub wire width 4 input 2 signed \i4sa wire width 4 input 3 signed \i4sb wire width 6 output 4 \o1 wire width 6 output 5 \o2 wire width 6 output 6 \o3 wire width 6 output 7 \o4 wire width 6 output 8 \o5 wire width 6 output 9 \o6 wire width 6 output 10 \o7 wire width 6 output 11 \o8 wire width 4 $1 wire width 5 $2 wire width 5 $3 wire width 5 $4 wire width 4 $5 wire width 5 $6 wire width 5 $7 wire width 4 $8 wire width 4 $9 cell $divfloor $10 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 4 parameter \B_WIDTH 4 parameter \Y_WIDTH 4 connect \A \i4ua [3:0] connect \B \i4ub [3:0] connect \Y $9 end wire width 1 $11 cell $reduce_bool $12 parameter \A_SIGNED 0 parameter \A_WIDTH 4 parameter \Y_WIDTH 1 connect \A \i4ub [3:0] connect \Y $11 end cell $mux $13 parameter \WIDTH 4 connect \S $11 connect \A 4'0000 connect \B $9 connect \Y $1 end wire width 5 $14 cell $divfloor $15 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 5 parameter \B_WIDTH 4 parameter \Y_WIDTH 5 connect \A { 1'0 \i4ua [3:0] } connect \B \i4sb [3:0] connect \Y $14 end wire width 1 $16 cell $reduce_bool $17 parameter \A_SIGNED 0 parameter \A_WIDTH 4 parameter \Y_WIDTH 1 connect \A \i4sb [3:0] connect \Y $16 end cell $mux $18 parameter \WIDTH 5 connect \S $16 connect \A 5'00000 connect \B $14 connect \Y $2 end wire width 5 $19 cell $divfloor $20 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 4 parameter \B_WIDTH 5 parameter \Y_WIDTH 5 connect \A \i4sa [3:0] connect \B { 1'0 \i4ub [3:0] } connect \Y $19 end wire width 1 $21 cell $reduce_bool $22 parameter \A_SIGNED 0 parameter \A_WIDTH 5 parameter \Y_WIDTH 1 connect \A { 1'0 \i4ub [3:0] } connect \Y $21 end cell $mux $23 parameter \WIDTH 5 connect \S $21 connect \A 5'00000 connect \B $19 connect \Y $3 end wire width 5 $24 cell $divfloor $25 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 4 parameter \B_WIDTH 4 parameter \Y_WIDTH 5 connect \A \i4sa [3:0] connect \B \i4sb [3:0] connect \Y $24 end wire width 1 $26 cell $reduce_bool $27 parameter \A_SIGNED 0 parameter \A_WIDTH 4 parameter \Y_WIDTH 1 connect \A \i4sb [3:0] connect \Y $26 end cell $mux $28 parameter \WIDTH 5 connect \S $26 connect \A 5'00000 connect \B $24 connect \Y $4 end wire width 4 $29 cell $modfloor $30 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 4 parameter \B_WIDTH 4 parameter \Y_WIDTH 4 connect \A \i4ua [3:0] connect \B \i4ub [3:0] connect \Y $29 end wire width 1 $31 cell $reduce_bool $32 parameter \A_SIGNED 0 parameter \A_WIDTH 4 parameter \Y_WIDTH 1 connect \A \i4ub [3:0] connect \Y $31 end cell $mux $33 parameter \WIDTH 4 connect \S $31 connect \A 4'0000 connect \B $29 connect \Y $5 end wire width 5 $34 cell $modfloor $35 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 5 parameter \B_WIDTH 4 parameter \Y_WIDTH 5 connect \A { 1'0 \i4ua [3:0] } connect \B \i4sb [3:0] connect \Y $34 end wire width 1 $36 cell $reduce_bool $37 parameter \A_SIGNED 0 parameter \A_WIDTH 4 parameter \Y_WIDTH 1 connect \A \i4sb [3:0] connect \Y $36 end cell $mux $38 parameter \WIDTH 5 connect \S $36 connect \A 5'00000 connect \B $34 connect \Y $6 end wire width 5 $39 cell $modfloor $40 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 4 parameter \B_WIDTH 5 parameter \Y_WIDTH 5 connect \A \i4sa [3:0] connect \B { 1'0 \i4ub [3:0] } connect \Y $39 end wire width 1 $41 cell $reduce_bool $42 parameter \A_SIGNED 0 parameter \A_WIDTH 5 parameter \Y_WIDTH 1 connect \A { 1'0 \i4ub [3:0] } connect \Y $41 end cell $mux $43 parameter \WIDTH 5 connect \S $41 connect \A 5'00000 connect \B $39 connect \Y $7 end wire width 4 $44 cell $modfloor $45 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 4 parameter \B_WIDTH 4 parameter \Y_WIDTH 4 connect \A \i4sa [3:0] connect \B \i4sb [3:0] connect \Y $44 end wire width 1 $46 cell $reduce_bool $47 parameter \A_SIGNED 0 parameter \A_WIDTH 4 parameter \Y_WIDTH 1 connect \A \i4sb [3:0] connect \Y $46 end cell $mux $48 parameter \WIDTH 4 connect \S $46 connect \A 4'0000 connect \B $44 connect \Y $8 end connect \o1 { 2'00 $1 [3:0] } connect \o2 { $2 [4] $2 [4:0] } connect \o3 { $3 [3] $3 [3] $3 [3:0] } connect \o4 { $4 [4] $4 [4:0] } connect \o5 { 2'00 $5 [3:0] } connect \o6 { $6 [3] $6 [3] $6 [3:0] } connect \o7 { 2'00 $7 [3:0] } connect \o8 { $8 [3] $8 [3] $8 [3:0] } end """) def test_operator_shift(self): i8ua = Signal(8) i8sa = Signal(signed(8)) i3 = Signal(3) o1 = Signal(16) o2 = Signal(16) o3 = Signal(16) o4 = Signal(16) m = Module() m.d.comb += [ o1.eq(i8ua << i3), o2.eq(i8sa << i3), o3.eq(i8ua >> i3), o4.eq(i8sa >> i3), ] self.assertRTLIL(m, [i8ua, i8sa, i3, o1, o2, o3, o4], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 signed \i8sa wire width 3 input 2 \i3 wire width 16 output 3 \o1 wire width 16 output 4 \o2 wire width 16 output 5 \o3 wire width 16 output 6 \o4 wire width 15 $1 wire width 15 $2 wire width 8 $3 wire width 8 $4 cell $shl $5 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 15 connect \A \i8ua [7:0] connect \B \i3 [2:0] connect \Y $1 end cell $shl $6 parameter \A_SIGNED 1 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 15 connect \A \i8sa [7:0] connect \B \i3 [2:0] connect \Y $2 end cell $shr $7 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 8 connect \A \i8ua [7:0] connect \B \i3 [2:0] connect \Y $3 end cell $sshr $8 parameter \A_SIGNED 1 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 8 connect \A \i8sa [7:0] connect \B \i3 [2:0] connect \Y $4 end connect \o1 { 1'0 $1 [14:0] } connect \o2 { $2 [14] $2 [14:0] } connect \o3 { 8'00000000 $3 [7:0] } connect \o4 { $4 [7] $4 [7] $4 [7] $4 [7] $4 [7] $4 [7] $4 [7] $4 [7] $4 [7:0] } end """) def test_operator_bitwise(self): for (name, op) in [ ("and", operator.__and__), ("or", operator.__or__), ("xor", operator.__xor__), ]: i8ua = Signal(8) i8ub = Signal(8) i8sa = Signal(signed(8)) i8sb = Signal(signed(8)) o1 = Signal(10) o2 = Signal(10) o3 = Signal(10) m = Module() m.d.comb += [ o1.eq(op(i8ua, i8ub)), o2.eq(op(i8ua, i8sb)), o3.eq(op(i8sa, i8sb)), ] self.assertRTLIL(m, [i8ua, i8ub, i8sa, i8sb, o1, o2, o3], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 \i8ub wire width 8 input 2 signed \i8sa wire width 8 input 3 signed \i8sb wire width 10 output 4 \o1 wire width 10 output 5 \o2 wire width 10 output 6 \o3 wire width 8 $1 wire width 9 $2 wire width 8 $3 cell $bitop $4 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 8 connect \A \i8ua [7:0] connect \B \i8ub [7:0] connect \Y $1 end cell $bitop $5 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 9 parameter \B_WIDTH 9 parameter \Y_WIDTH 9 connect \A { 1'0 \i8ua [7:0] } connect \B { \i8sb [7] \i8sb [7:0] } connect \Y $2 end cell $bitop $6 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 8 connect \A \i8sa [7:0] connect \B \i8sb [7:0] connect \Y $3 end connect \o1 { 2'00 $1 [7:0] } connect \o2 { $2 [8] $2 [8:0] } connect \o3 { $3 [7] $3 [7] $3 [7:0] } end """.replace("bitop", name)) def test_operator_eq(self): for (name, op) in [ ("eq", operator.__eq__), ("ne", operator.__ne__), ]: i8ua = Signal(8) i8ub = Signal(8) i8sa = Signal(signed(8)) i8sb = Signal(signed(8)) o1 = Signal(2) o2 = Signal(2) o3 = Signal(2) m = Module() m.d.comb += [ o1.eq(op(i8ua, i8ub)), o2.eq(op(i8ua, i8sb)), o3.eq(op(i8sa, i8sb)), ] self.assertRTLIL(m, [i8ua, i8ub, i8sa, i8sb, o1, o2, o3], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 \i8ub wire width 8 input 2 signed \i8sa wire width 8 input 3 signed \i8sb wire width 2 output 4 \o1 wire width 2 output 5 \o2 wire width 2 output 6 \o3 wire width 1 $1 wire width 1 $2 wire width 1 $3 cell $eqop $4 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8ua [7:0] connect \B \i8ub [7:0] connect \Y $1 end cell $eqop $5 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 9 parameter \B_WIDTH 8 parameter \Y_WIDTH 1 connect \A { 1'0 \i8ua [7:0] } connect \B \i8sb [7:0] connect \Y $2 end cell $eqop $6 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8sa [7:0] connect \B \i8sb [7:0] connect \Y $3 end connect \o1 { 1'0 $1 [0] } connect \o2 { 1'0 $2 [0] } connect \o3 { 1'0 $3 [0] } end """.replace("eqop", name)) def test_operator_cmp(self): for (name, op) in [ ("lt", operator.__lt__), ("le", operator.__le__), ("gt", operator.__gt__), ("ge", operator.__ge__), ]: i8ua = Signal(8) i8ub = Signal(8) i8sa = Signal(signed(8)) i8sb = Signal(signed(8)) o1 = Signal(2) o2 = Signal(2) o3 = Signal(2) m = Module() m.d.comb += [ o1.eq(op(i8ua, i8ub)), o2.eq(op(i8ua, i8sb)), o3.eq(op(i8sa, i8sb)), ] self.assertRTLIL(m, [i8ua, i8ub, i8sa, i8sb, o1, o2, o3], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 \i8ub wire width 8 input 2 signed \i8sa wire width 8 input 3 signed \i8sb wire width 2 output 4 \o1 wire width 2 output 5 \o2 wire width 2 output 6 \o3 wire width 1 $1 wire width 1 $2 wire width 1 $3 cell $cmpop $4 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8ua [7:0] connect \B \i8ub [7:0] connect \Y $1 end cell $cmpop $5 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 9 parameter \B_WIDTH 8 parameter \Y_WIDTH 1 connect \A { 1'0 \i8ua [7:0] } connect \B \i8sb [7:0] connect \Y $2 end cell $cmpop $6 parameter \A_SIGNED 1 parameter \B_SIGNED 1 parameter \A_WIDTH 8 parameter \B_WIDTH 8 parameter \Y_WIDTH 1 connect \A \i8sa [7:0] connect \B \i8sb [7:0] connect \Y $3 end connect \o1 { 1'0 $1 [0] } connect \o2 { 1'0 $2 [0] } connect \o3 { 1'0 $3 [0] } end """.replace("cmpop", name)) def test_operator_mux(self): i8ua = Signal(8) i8ub = Signal(8) i8sa = Signal(signed(8)) i8sb = Signal(signed(8)) i1 = Signal() o1 = Signal(10) o2 = Signal(10) o3 = Signal(10) m = Module() m.d.comb += [ o1.eq(Mux(i1, i8ua, i8ub)), o2.eq(Mux(i1, i8ua, i8sb)), o3.eq(Mux(i1, i8sa, i8sb)), ] self.assertRTLIL(m, [i8ua, i8ub, i8sa, i8sb, i1, o1, o2, o3], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 \i8ub wire width 8 input 2 signed \i8sa wire width 8 input 3 signed \i8sb wire width 1 input 4 \i1 wire width 10 output 5 \o1 wire width 10 output 6 \o2 wire width 10 output 7 \o3 wire width 8 $1 wire width 9 $2 wire width 8 $3 cell $mux $4 parameter \WIDTH 8 connect \S \i1 [0] connect \A \i8ub [7:0] connect \B \i8ua [7:0] connect \Y $1 end cell $mux $5 parameter \WIDTH 9 connect \S \i1 [0] connect \A { \i8sb [7] \i8sb [7:0] } connect \B { 1'0 \i8ua [7:0] } connect \Y $2 end cell $mux $6 parameter \WIDTH 8 connect \S \i1 [0] connect \A \i8sb [7:0] connect \B \i8sa [7:0] connect \Y $3 end connect \o1 { 2'00 $1 [7:0] } connect \o2 { $2 [8] $2 [8:0] } connect \o3 { $3 [7] $3 [7] $3 [7:0] } end """) def test_part(self): i8ua = Signal(8) i8sa = Signal(signed(8)) i3 = Signal(3) o1 = Signal(4) o2 = Signal(4) o3 = Signal(4) o4 = Signal(4) m = Module() m.d.comb += [ o1.eq(i8ua.bit_select(i3, width=3)), o2.eq(i8sa.bit_select(i3, width=3)), o3.eq(i8ua.word_select(i3, width=3)), o4.eq(i8sa.word_select(i3, width=3)), ] self.assertRTLIL(m, [i8ua, i8sa, i3, o1, o2, o3, o4], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8ua wire width 8 input 1 signed \i8sa wire width 3 input 2 \i3 wire width 4 output 3 \o1 wire width 4 output 4 \o2 wire width 4 output 5 \o3 wire width 4 output 6 \o4 wire width 3 $1 wire width 3 $2 wire width 3 $3 wire width 3 $4 cell $shift $5 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 3 connect \A \i8ua [7:0] connect \B \i3 [2:0] connect \Y $1 end cell $shift $6 parameter \A_SIGNED 1 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 3 parameter \Y_WIDTH 3 connect \A \i8sa [7:0] connect \B \i3 [2:0] connect \Y $2 end wire width 5 $7 cell $mul $8 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 3 parameter \B_WIDTH 2 parameter \Y_WIDTH 5 connect \A \i3 [2:0] connect \B 2'11 connect \Y $7 end cell $shift $9 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 5 parameter \Y_WIDTH 3 connect \A \i8ua [7:0] connect \B $7 connect \Y $3 end wire width 5 $10 cell $mul $11 parameter \A_SIGNED 0 parameter \B_SIGNED 0 parameter \A_WIDTH 3 parameter \B_WIDTH 2 parameter \Y_WIDTH 5 connect \A \i3 [2:0] connect \B 2'11 connect \Y $10 end cell $shift $12 parameter \A_SIGNED 1 parameter \B_SIGNED 0 parameter \A_WIDTH 8 parameter \B_WIDTH 5 parameter \Y_WIDTH 3 connect \A \i8sa [7:0] connect \B $10 connect \Y $4 end connect \o1 { 1'0 $1 [2:0] } connect \o2 { 1'0 $2 [2:0] } connect \o3 { 1'0 $3 [2:0] } connect \o4 { 1'0 $4 [2:0] } end """) def test_initial(self): o = Signal() m = Module() m.d.comb += [ o.eq(Initial()) ] self.assertRTLIL(m, [o], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 1 output 0 \o cell $initstate $1 connect \Y \o end end """) def test_anyvalue(self): o1 = Signal(8) o2 = Signal(8) m = Module() m.d.comb += [ o1.eq(AnyConst(unsigned(4))), o2.eq(AnySeq(signed(4))), ] self.assertRTLIL(m, [o1, o2], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 output 0 \o1 wire width 8 output 1 \o2 wire width 4 $1 wire width 4 $2 cell $anyconst $3 parameter \WIDTH 4 connect \Y $1 end cell $anyseq $4 parameter \WIDTH 4 connect \Y $2 end connect \o1 { 4'0000 $1 [3:0] } connect \o2 { $2 [3] $2 [3] $2 [3] $2 [3] $2 [3:0] } end """) class FlopTestCase(RTLILTestCase): def test_sync(self): o = Signal(8, init=0x55) i = Signal(8) m = Module() m.domains.sync = sync = ClockDomain() m.d.sync += o.eq(i) self.assertRTLIL(m, [i, ClockSignal(), ResetSignal(), o], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i wire width 1 input 1 \clk wire width 1 input 2 \rst attribute \init 8'01010101 wire width 8 output 3 \o wire width 8 $1 process $2 assign $1 [7:0] \o [7:0] assign $1 [7:0] \i [7:0] switch \rst [0] case 1'1 assign $1 [7:0] 8'01010101 end end cell $dff $3 parameter \WIDTH 8 parameter \CLK_POLARITY 1 connect \D $1 [7:0] connect \CLK \clk [0] connect \Q \o end end """) def test_async(self): o = Signal(8, init=0x55) i = Signal(8) m = Module() m.domains.sync = sync = ClockDomain(clk_edge="neg", async_reset=True) m.d.sync += o.eq(i) self.assertRTLIL(m, [i, ClockSignal(), ResetSignal(), o], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i wire width 1 input 1 \clk wire width 1 input 2 \rst attribute \init 8'01010101 wire width 8 output 3 \o cell $adff $1 parameter \WIDTH 8 parameter \CLK_POLARITY 0 parameter \ARST_POLARITY 1 parameter \ARST_VALUE 8'01010101 connect \D \i [7:0] connect \CLK \clk [0] connect \Q \o connect \ARST \rst [0] end end """) class SwitchTestCase(RTLILTestCase): def test_simple(self): sel = Signal(4) out = Signal(4, init=12) m = Module() with m.Switch(sel): with m.Case(0): m.d.comb += out.eq(1) with m.Case(1, 2): m.d.comb += out.eq(2) with m.Case("11--"): m.d.comb += out.eq(3) with m.Case(): m.d.comb += out.eq(4) with m.Default(): m.d.comb += out.eq(5) self.assertRTLIL(m, [sel, out], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 4 input 0 \sel wire width 4 output 1 \out process $1 assign \out [3:0] 4'1100 switch \sel [3:0] case 4'0000 assign \out [3:0] 4'0001 case 4'0001, 4'0010 assign \out [3:0] 4'0010 case 4'11-- assign \out [3:0] 4'0011 case assign \out [3:0] 4'0101 end end end """) def test_aba(self): a = Signal(2) sel = Signal(4) out = Signal(4, init=12) m = Module() with m.Switch(sel): with m.Case(0): m.d.comb += out.eq(1) with m.Case(1, 2): m.d.comb += out.eq(2) with m.Case("11--"): m.d.comb += out.eq(3) with m.Case(): m.d.comb += out.eq(4) with m.Default(): m.d.comb += out.eq(5) m.d.comb += out[1:3].eq(a) self.assertRTLIL(m, [sel, a, out], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 4 input 0 \sel wire width 2 input 1 \a wire width 4 output 2 \out process $1 assign \out [3:0] 4'1100 switch \sel [3:0] case 4'0000 assign \out [3:0] 4'0001 case 4'0001, 4'0010 assign \out [3:0] 4'0010 case 4'11-- assign \out [3:0] 4'0011 case assign \out [3:0] 4'0101 end switch {} case assign \out [2:1] \a [1:0] end end end """) def test_nested(self): sel1 = Signal(4) sel2 = Signal(4) sel3 = Signal(4) out = Signal(4, init=12) m = Module() with m.Switch(sel1): with m.Case(0): m.d.comb += out.eq(1) with m.Case(1): with m.Switch(sel2): with m.Case(0): m.d.comb += out.eq(2) with m.Case(1): with m.Switch(sel3): with m.Case(0): m.d.comb += out.eq(3) with m.Default(): m.d.comb += out.eq(4) with m.Case(2): m.d.comb += out.eq(5) with m.Default(): m.d.comb += out.eq(6) self.assertRTLIL(m, [sel1, sel2, sel3, out], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 4 input 0 \sel1 wire width 4 input 1 \sel2 wire width 4 input 2 \sel3 wire width 4 output 3 \out process $1 assign \out [3:0] 4'1100 switch \sel1 [3:0] case 4'0000 assign \out [3:0] 4'0001 case 4'0001 switch \sel2 [3:0] case 4'0000 assign \out [3:0] 4'0010 case 4'0001 switch \sel3 [3:0] case 4'0000 assign \out [3:0] 4'0011 case assign \out [3:0] 4'0100 end end case 4'0010 assign \out [3:0] 4'0101 case assign \out [3:0] 4'0110 end end end """) def test_trivial(self): sel = Signal(4) out = Signal(4) m = Module() with m.Switch(sel): with m.Default(): m.d.comb += out.eq(1) self.assertRTLIL(m, [sel, out], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 4 input 0 \sel wire width 4 output 1 \out process $1 assign \out [3:0] 4'0000 switch { } case assign \out [3:0] 4'0001 end end end """) class IOBTestCase(RTLILTestCase): def test_iob(self): io_i = IOPort(1) io_o = IOPort(1) io_oe = IOPort(1) io_io = IOPort(1) i = Signal() o = Signal() oe = Signal() m = Module() m.submodules += IOBufferInstance(io_i, o=i) m.submodules += IOBufferInstance(io_o, i=o) m.submodules += IOBufferInstance(io_oe, i=oe) m.submodules += IOBufferInstance(io_io, i=i, o=o, oe=oe) self.assertRTLIL(m, [], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 1 \i wire width 1 \o wire width 1 \oe wire width 1 output 0 \io_i wire width 1 input 1 \io_o wire width 1 input 2 \io_oe wire width 1 inout 3 \io_io cell $tribuf $1 parameter \WIDTH 1 connect \Y \io_io [0] connect \A \o [0] connect \EN \oe [0] end connect \io_i [0] \i [0] connect \o \io_o [0] connect \oe \io_oe [0] connect \i \io_io [0] end """) class InstanceTestCase(RTLILTestCase): def test_instance(self): m = Module() i = Signal(2) o = Signal(3) m.submodules.inst = Instance("t", i_i=i, o_o=o) self.assertRTLIL(m, [i, o], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 2 input 0 \i wire width 3 output 1 \o cell \t \inst connect \i \i [1:0] connect \o \o end end """) def test_attr(self): m = Module() i = Signal(2) o = Signal(3) m.submodules.inst = Instance("t", i_i=i, o_o=o, a_str="abc", a_int=123, a_const=Const(0x55, 8), a_sint=-3, a_sconst=Const(-2, 3)) self.assertRTLIL(m, [i, o], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 2 input 0 \i wire width 3 output 1 \o attribute \str "abc" attribute \int 123 attribute \const 8'01010101 attribute \sint 32'11111111111111111111111111111101 attribute \sconst 3'110 cell \t \inst connect \i \i [1:0] connect \o \o end end """) def test_param(self): m = Module() i = Signal(2) o = Signal(3) m.submodules.inst = Instance("t", i_i=i, o_o=o, p_str="abc", p_int=123, p_float=3.0, p_const=Const(0x55, 8), p_sint=-3, p_sconst=Const(2, signed(3))) self.assertRTLIL(m, [i, o], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 2 input 0 \i wire width 3 output 1 \o cell \t \inst parameter \str "abc" parameter \int 123 parameter real \float "3.0" parameter \const 8'01010101 parameter signed \sint 32'11111111111111111111111111111101 parameter signed \sconst 3'010 connect \i \i [1:0] connect \o \o end end """) def test_ioport(self): io_i = IOPort(2) io_o = IOPort(3) io_io = IOPort(4) m = Module() m.submodules.sm = sm = Module() sm.submodules.inst = Instance("t", i_i=io_i, o_o=io_o, io_io=io_io) self.assertRTLIL(m, [], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 2 input 0 \io_i wire width 3 output 1 \io_o wire width 4 inout 2 \io_io cell \top.sm \sm connect \io_i \io_i [1:0] connect \io_o \io_o [2:0] connect \io_io \io_io [3:0] end end attribute \generator "Amaranth" module \top.sm wire width 2 input 0 \io_i wire width 3 output 1 \io_o wire width 4 inout 2 \io_io cell \t \inst connect \i \io_i [1:0] connect \o \io_o [2:0] connect \io \io_io [3:0] end end """) def test_concat(self): io_a = IOPort(2) io_b = IOPort(2) m = Module() m.submodules.inst = Instance("t", io_io=Cat(io_a, io_b)) self.assertRTLIL(m, [], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 2 inout 0 \io_a wire width 2 inout 1 \io_b cell \t \inst connect \io { \io_b [1:0] \io_a [1:0] } end end """) class MemoryTestCase(RTLILTestCase): def test_async_read(self): m = Module() m.submodules.mem = mem = memory.Memory(shape=8, depth=4, init=[1, 2, 3, 4]) wp = mem.write_port() rp = mem.read_port(domain="comb") self.assertRTLIL(m, [ ("rd", rp.data, None), ("ra", rp.addr, None), ("wd", wp.data, None), ("wa", wp.addr, None), ("we", wp.en, None), ], R""" attribute \generator "Amaranth" attribute \top 1 module \top memory width 8 size 4 \mem wire width 8 \rp__data wire width 2 \rp__addr wire width 8 \wp__data wire width 2 \wp__addr wire width 1 \wp__en wire width 2 input 0 \ra wire width 8 input 1 \wd wire width 2 input 2 \wa wire width 1 input 3 \we wire width 1 input 4 \clk wire width 1 input 5 \rst wire width 8 output 6 \rd cell $meminit_v2 $1 parameter \MEMID "\\mem" parameter \ABITS 0 parameter \WIDTH 8 parameter \WORDS 4 parameter \PRIORITY 0 connect \ADDR { } connect \DATA 32'00000100000000110000001000000001 connect \EN 8'11111111 end cell $memwr_v2 $2 parameter \MEMID "\\mem" parameter \ABITS 2 parameter \WIDTH 8 parameter \CLK_ENABLE 1 parameter \CLK_POLARITY 1 parameter \PORTID 0 parameter \PRIORITY_MASK 0 connect \ADDR \wa [1:0] connect \DATA \wd [7:0] connect \EN { \we [0] \we [0] \we [0] \we [0] \we [0] \we [0] \we [0] \we [0] } connect \CLK \clk [0] end cell $memrd_v2 $3 parameter \MEMID "\\mem" parameter \ABITS 2 parameter \WIDTH 8 parameter \TRANSPARENCY_MASK 1'0 parameter \COLLISION_X_MASK 1'0 parameter \ARST_VALUE 8'00000000 parameter \SRST_VALUE 8'00000000 parameter \INIT_VALUE 8'00000000 parameter \CE_OVER_SRST 0 parameter \CLK_ENABLE 0 parameter \CLK_POLARITY 1 connect \ADDR \ra [1:0] connect \DATA \rp__data connect \ARST 1'0 connect \SRST 1'0 connect \EN 1'1 connect \CLK 1'0 end connect \rp__addr \ra [1:0] connect \wp__data \wd [7:0] connect \wp__addr \wa [1:0] connect \wp__en \we [0] connect \rd \rp__data [7:0] end """) def test_sync_read(self): m = Module() m.submodules.mem = mem = memory.Memory(shape=8, depth=4, init=[1, 2, 3, 4], attrs={"ram_style": "block"}) wp = mem.write_port() rp = mem.read_port(transparent_for=(wp,)) self.assertRTLIL(m, [ ("rd", rp.data, None), ("ra", rp.addr, None), ("re", rp.en, None), ("wd", wp.data, None), ("wa", wp.addr, None), ("we", wp.en, None), ], R""" attribute \generator "Amaranth" attribute \top 1 module \top attribute \ram_style "block" memory width 8 size 4 \mem wire width 8 \rp__data wire width 2 \rp__addr wire width 1 \rp__en wire width 8 \wp__data wire width 2 \wp__addr wire width 1 \wp__en wire width 2 input 0 \ra wire width 1 input 1 \re wire width 8 input 2 \wd wire width 2 input 3 \wa wire width 1 input 4 \we wire width 1 input 5 \clk wire width 1 input 6 \rst wire width 8 output 7 \rd cell $meminit_v2 $1 parameter \MEMID "\\mem" parameter \ABITS 0 parameter \WIDTH 8 parameter \WORDS 4 parameter \PRIORITY 0 connect \ADDR { } connect \DATA 32'00000100000000110000001000000001 connect \EN 8'11111111 end cell $memwr_v2 $2 parameter \MEMID "\\mem" parameter \ABITS 2 parameter \WIDTH 8 parameter \CLK_ENABLE 1 parameter \CLK_POLARITY 1 parameter \PORTID 0 parameter \PRIORITY_MASK 0 connect \ADDR \wa [1:0] connect \DATA \wd [7:0] connect \EN { \we [0] \we [0] \we [0] \we [0] \we [0] \we [0] \we [0] \we [0] } connect \CLK \clk [0] end cell $memrd_v2 $3 parameter \MEMID "\\mem" parameter \ABITS 2 parameter \WIDTH 8 parameter \TRANSPARENCY_MASK 1'1 parameter \COLLISION_X_MASK 1'0 parameter \ARST_VALUE 8'00000000 parameter \SRST_VALUE 8'00000000 parameter \INIT_VALUE 8'00000000 parameter \CE_OVER_SRST 0 parameter \CLK_ENABLE 1 parameter \CLK_POLARITY 1 connect \ADDR \ra [1:0] connect \DATA \rp__data connect \ARST 1'0 connect \SRST 1'0 connect \EN \re [0] connect \CLK \clk [0] end connect \rp__addr \ra [1:0] connect \rp__en \re [0] connect \wp__data \wd [7:0] connect \wp__addr \wa [1:0] connect \wp__en \we [0] connect \rd \rp__data [7:0] end """) class PrintTestCase(RTLILTestCase): def test_print_simple(self): i8u = Signal(8) i8s = Signal(signed(8)) m = Module() m.d.comb += [ Print(i8u, i8s), ] self.assertRTLIL(m, [i8u, i8s], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8u wire width 8 input 1 signed \i8s wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $print $3 parameter \FORMAT "{8:> du} {8:> ds}\n" parameter \ARGS_WIDTH 16 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 0 parameter \TRG_WIDTH 0 parameter \TRG_POLARITY 0 connect \EN $1 [0] connect \ARGS { \i8s [7:0] \i8u [7:0] } connect \TRG { } end end """) def test_print_sync(self): i8u = Signal(8) i8s = Signal(signed(8)) m = Module() m.domains.sync = ClockDomain() m.d.sync += [ Print(i8u, i8s), ] self.assertRTLIL(m, [i8u, i8s, ClockSignal(), ResetSignal()], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i8u wire width 8 input 1 signed \i8s wire width 1 input 2 \clk wire width 1 input 3 \rst wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $print $3 parameter \FORMAT "{8:> du} {8:> ds}\n" parameter \ARGS_WIDTH 16 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 1 parameter \TRG_WIDTH 1 parameter \TRG_POLARITY 1 connect \EN $1 [0] connect \ARGS { \i8s [7:0] \i8u [7:0] } connect \TRG \clk [0] end end """) def test_assert_simple(self): test = Signal() en = Signal() m = Module() with m.If(en): m.d.comb += Assert(test) self.assertRTLIL(m, [test, en], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 1 input 0 \test wire width 1 input 1 \en wire width 1 $1 process $2 assign $1 [0] 1'0 switch \en [0] case 1'1 assign $1 [0] 1'1 end end cell $check $3 parameter \FORMAT "" parameter \ARGS_WIDTH 0 parameter signed \PRIORITY 32'11111111111111111111111111111100 parameter \TRG_ENABLE 0 parameter \TRG_WIDTH 0 parameter \TRG_POLARITY 0 parameter \FLAVOR "assert" connect \EN $1 [0] connect \ARGS { } connect \TRG { } connect \A \test [0] end end """) def test_assume_msg(self): msg = Signal(32) test = Signal() m = Module() m.domains.sync = ClockDomain() m.d.sync += [ Assume(test, Format("{:s}", msg)), ] self.assertRTLIL(m, [msg, test, ClockSignal(), ResetSignal()], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 32 input 0 \msg wire width 1 input 1 \test wire width 1 input 2 \clk wire width 1 input 3 \rst wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $check $3 parameter \FORMAT "{32:< c}" parameter \ARGS_WIDTH 32 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 1 parameter \TRG_WIDTH 1 parameter \TRG_POLARITY 1 parameter \FLAVOR "assume" connect \EN $1 [0] connect \ARGS { \msg [7:0] \msg [15:8] \msg [23:16] \msg [31:24] } connect \TRG \clk [0] connect \A \test [0] end end """) def test_print_char(self): i = Signal(21) m = Module() m.d.comb += [ Print(Format("{:c} {:-<5c} {:->5c}", i, i, i)), ] self.assertRTLIL(m, [i], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 21 input 0 \i wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $print $3 parameter \FORMAT "{21:U} {21:U}---- ----{21:U}\n" parameter \ARGS_WIDTH 63 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 0 parameter \TRG_WIDTH 0 parameter \TRG_POLARITY 0 connect \EN $1 [0] connect \ARGS { \i [20:0] \i [20:0] \i [20:0] } connect \TRG { } end end """) def test_print_base(self): i = Signal(8) m = Module() m.d.comb += [ Print(Format("{:b} {:o} {:d} {:x} {:X} {:#x} {:#d} {:#_x}", i, i, i, i, i, i, i, i)), ] self.assertRTLIL(m, [i], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $print $3 parameter \FORMAT "{8:> bu} {8:> ou} {8:> du} {8:> hu} {8:> Hu} {8:> h#u} {8:> du} {8:> h#_u}\n" parameter \ARGS_WIDTH 64 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 0 parameter \TRG_WIDTH 0 parameter \TRG_POLARITY 0 connect \EN $1 [0] connect \ARGS { \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] } connect \TRG { } end end """) def test_print_sign(self): i = Signal(8) m = Module() m.d.comb += [ Print(Format("{:5x} {:-5x} {:+5x} {: 5x}", i, i, i, i)), ] self.assertRTLIL(m, [i], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $print $3 parameter \FORMAT "{8:> 5hu} {8:> 5h-u} {8:> 5h+u} {8:> 5h u}\n" parameter \ARGS_WIDTH 32 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 0 parameter \TRG_WIDTH 0 parameter \TRG_POLARITY 0 connect \EN $1 [0] connect \ARGS { \i [7:0] \i [7:0] \i [7:0] \i [7:0] } connect \TRG { } end end """) def test_print_align(self): i = Signal(8) m = Module() m.d.comb += [ Print(Format("{:<5x} {:>5x} {:=5x} {:05x} {:-<5x}", i, i, i, i, i)), ] self.assertRTLIL(m, [i], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i wire width 1 $1 process $2 assign $1 [0] 1'0 assign $1 [0] 1'1 end cell $print $3 parameter \FORMAT "{8:< 5hu} {8:> 5hu} {8:= 5hu} {8:=05hu} {8:<-5hu}\n" parameter \ARGS_WIDTH 40 parameter signed \PRIORITY 32'11111111111111111111111111111110 parameter \TRG_ENABLE 0 parameter \TRG_WIDTH 0 parameter \TRG_POLARITY 0 connect \EN $1 [0] connect \ARGS { \i [7:0] \i [7:0] \i [7:0] \i [7:0] \i [7:0] } connect \TRG { } end end """) class DetailTestCase(RTLILTestCase): def test_enum(self): class MyEnum(enum.Enum, shape=unsigned(2)): A = 0 B = 1 C = 2 sig = Signal(MyEnum) m = Module() m.d.comb += sig.eq(MyEnum.A) self.assertRTLIL(m, [sig.as_value()], R""" attribute \generator "Amaranth" attribute \top 1 module \top attribute \enum_base_type "MyEnum" attribute \enum_value_00 "A" attribute \enum_value_01 "B" attribute \enum_value_10 "C" wire width 2 output 0 \sig connect \sig 2'00 end """) def test_struct(self): class MyEnum(enum.Enum, shape=unsigned(2)): A = 0 B = 1 C = 2 class Meow(data.Struct): a: MyEnum b: 3 c: signed(4) d: data.ArrayLayout(2, 2) sig = Signal(Meow) m = Module() self.assertRTLIL(m, [sig.as_value()], R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 13 input 0 \sig attribute \enum_base_type "MyEnum" attribute \enum_value_00 "A" attribute \enum_value_01 "B" attribute \enum_value_10 "C" wire width 2 \sig.a wire width 3 \sig.b wire width 4 signed \sig.c wire width 4 \sig.d wire width 2 \sig.d[0] wire width 2 \sig.d[1] connect \sig.a \sig [1:0] connect \sig.b \sig [4:2] connect \sig.c \sig [8:5] connect \sig.d \sig [12:9] connect \sig.d[0] \sig [10:9] connect \sig.d[1] \sig [12:11] end """) class ComponentTestCase(RTLILTestCase): def test_component(self): class MyComponent(wiring.Component): i: wiring.In(unsigned(8)) o: wiring.Out(unsigned(8)) def elaborate(self, platform): return Module() self.assertRTLIL(MyComponent(), None, R""" attribute \generator "Amaranth" attribute \top 1 module \top wire width 8 input 0 \i wire width 8 output 1 \o connect \o 8'00000000 end """)