/tests/test_type/test_bit.py

https://github.com/phanrahan/magma · Python · 382 lines · 286 code · 93 blank · 3 comment · 13 complexity · f414bdf0edc153a25fb4d76e5f3b0736 MD5 · raw file

  1. import itertools
  2. import pytest
  3. import magma as m
  4. from magma import In, Out, Flip
  5. from magma.testing import check_files_equal
  6. from magma.bit import Bit, VCC, GND, Digital
  7. from magma.simulator import PythonSimulator
  8. import operator
  9. BitIn = In(Bit)
  10. BitOut = Out(Bit)
  11. def test_bit():
  12. assert m.Bit == m.Bit
  13. assert m.BitIn == m.BitIn
  14. assert m.BitOut == m.BitOut
  15. assert m.Bit == m.BitIn
  16. assert m.Bit == m.BitOut
  17. assert m.BitIn == m.BitOut
  18. assert m.Bit is not m.BitIn
  19. assert m.Bit is not m.BitOut
  20. assert m.BitIn is not m.BitOut
  21. assert str(m.Bit) == 'Bit'
  22. assert str(m.BitIn) == 'In(Bit)'
  23. assert str(m.BitOut) == 'Out(Bit)'
  24. assert issubclass(m.Bit, m.Digital)
  25. assert isinstance(m.Bit(), m.Digital)
  26. assert issubclass(m.BitIn, m.Digital)
  27. assert isinstance(m.BitIn(), m.Digital)
  28. assert issubclass(m.BitIn, In(m.Digital))
  29. assert isinstance(m.BitIn(), In(m.Digital))
  30. assert not issubclass(m.BitIn, Out(m.Digital))
  31. assert not isinstance(m.BitIn(), Out(m.Digital))
  32. assert issubclass(m.BitIn, m.Bit)
  33. assert isinstance(m.BitIn(), m.Bit)
  34. assert not issubclass(m.BitIn, m.BitOut)
  35. assert not isinstance(m.BitIn(), m.BitOut)
  36. assert issubclass(m.BitOut, m.Digital)
  37. assert isinstance(m.BitOut(), m.Digital)
  38. assert issubclass(m.BitOut, Out(m.Digital))
  39. assert isinstance(m.BitOut(), Out(m.Digital))
  40. assert issubclass(m.BitOut, m.Bit)
  41. assert isinstance(m.BitOut(), m.Bit)
  42. assert not issubclass(m.BitOut, m.BitIn)
  43. assert not isinstance(m.BitOut(), m.BitIn)
  44. assert not issubclass(m.BitOut, In(m.Digital))
  45. assert not isinstance(m.BitOut(), In(m.Digital))
  46. assert m.Bit().is_oriented(m.Direction.Undirected)
  47. @pytest.mark.parametrize("T, direction",
  48. itertools.product([m.Digital, m.Bit, m.Clock],
  49. [m.In, m.Out]))
  50. def test_const_bit(T, direction):
  51. T = direction(T)
  52. assert isinstance(T(), T)
  53. assert not T().const()
  54. for val in 0, 1:
  55. expected_name = "VCC" if val else "GND"
  56. bit = T(val)
  57. assert isinstance(bit, T.undirected_t)
  58. assert bit.name.name == expected_name
  59. def test_bit_flip():
  60. bout = Out(Bit)
  61. bin = In(Bit)
  62. assert bout == BitOut
  63. assert bin == BitIn
  64. bin = In(BitIn)
  65. bout = Out(BitOut)
  66. assert bout == BitOut
  67. assert bin == BitIn
  68. bin = In(BitOut)
  69. bout = Out(BitOut)
  70. assert bout == BitOut
  71. assert bin == BitIn
  72. bin = Flip(BitOut)
  73. bout = Flip(BitIn)
  74. assert bout == BitOut
  75. assert bin == BitIn
  76. def test_bit_val():
  77. b = BitIn(name="a")
  78. assert isinstance(b, Bit)
  79. assert isinstance(b, BitIn)
  80. assert b.is_input()
  81. assert str(b) == "a"
  82. assert isinstance(b, BitIn)
  83. assert b.is_input()
  84. b = BitOut(name="a")
  85. assert b.is_output()
  86. assert str(b) == "a"
  87. assert isinstance(b, Bit)
  88. assert isinstance(b, BitOut)
  89. assert b.is_output()
  90. b = Bit(name="a")
  91. assert str(b) == "a"
  92. assert isinstance(b, Bit)
  93. assert isinstance(b, Bit)
  94. assert not b.is_input()
  95. assert not b.is_output()
  96. assert not b.is_inout()
  97. def test_vcc():
  98. assert str(VCC) == "VCC"
  99. assert isinstance(VCC, Digital)
  100. assert str(GND) == "GND"
  101. assert isinstance(GND, Digital)
  102. assert VCC is VCC
  103. assert VCC is not GND
  104. assert GND is GND
  105. def test_wire1():
  106. b0 = BitOut(name='b0')
  107. assert b0.is_output()
  108. b1 = BitIn(name='b1')
  109. assert b1.is_input()
  110. print('wire(b0,b1)')
  111. # b0 is treated as an output connected to b1 (treated as input)
  112. m.wire(b0, b1)
  113. assert b0.wired()
  114. assert b1.wired()
  115. assert b1.driven(), "Should be driven by input"
  116. assert b1.trace() is b0, "Should trace to b0"
  117. assert b1.value() is b0, "Value is b0"
  118. assert b0.driving() == [b1]
  119. assert b0.value() is b1
  120. assert b0 is b1._wire.driver.bit
  121. assert b1 is b0._wire.driving()[0]
  122. def test_wire2():
  123. b0 = BitOut(name='b0')
  124. assert b0.is_output()
  125. b1 = BitIn(name='b1')
  126. assert b1.is_input()
  127. m.wire(b1, b0)
  128. assert b0.wired()
  129. assert b1.wired()
  130. assert b0.wired()
  131. assert b1.wired()
  132. assert b1.driven(), "Should be driven by input"
  133. assert b1.trace() is b0, "Should trace to b0"
  134. assert b1.value() is b0, "Value is b0"
  135. assert b0.value() is b1, "Value is b1"
  136. assert b0.driving() == [b1]
  137. assert b0 is b1._wire.driver.bit
  138. assert b1 is b0._wire.driving()[0]
  139. def test_wire3():
  140. b0 = Bit(name='b0')
  141. b1 = Bit(name='b1')
  142. m.wire(b0, b1)
  143. assert b0.wired()
  144. assert b1.wired()
  145. assert b0.value() is b1
  146. assert b1.value() is b0
  147. assert b0.driving() == [b1]
  148. def test_wire4():
  149. b0 = BitIn(name='b0')
  150. b1 = BitIn(name='b1')
  151. m.wire(b0, b1)
  152. assert not b0.wired()
  153. assert not b1.wired()
  154. assert b0.trace() is None
  155. assert b1.trace() is None
  156. assert b0.value() is None
  157. assert b1.value() is None
  158. assert b1.driving() == []
  159. assert b0.driving() == []
  160. def test_wire5():
  161. b0 = BitOut(name='b0')
  162. b1 = BitOut(name='b1')
  163. m.wire(b0, b1)
  164. assert not b0.wired()
  165. assert not b1.wired()
  166. assert b1.driving() == []
  167. assert b0.driving() == []
  168. assert b1.value() is None
  169. assert b0.value() is None
  170. def test_invert():
  171. class TestInvert(m.Circuit):
  172. io = m.IO(I=m.In(m.Bit), O=m.Out(m.Bit))
  173. io.O <= ~io.I
  174. assert repr(TestInvert) == """\
  175. TestInvert = DefineCircuit("TestInvert", "I", In(Bit), "O", Out(Bit))
  176. magma_Bit_not_inst0 = magma_Bit_not()
  177. wire(TestInvert.I, magma_Bit_not_inst0.in)
  178. wire(magma_Bit_not_inst0.out, TestInvert.O)
  179. EndCircuit()\
  180. """
  181. m.compile("build/TestBitInvert", TestInvert, output="coreir-verilog")
  182. assert check_files_equal(__file__, f"build/TestBitInvert.v",
  183. f"gold/TestBitInvert.v")
  184. sim = PythonSimulator(TestInvert)
  185. for I in [0, 1]:
  186. sim.set_value(TestInvert.I, I)
  187. sim.evaluate()
  188. assert sim.get_value(TestInvert.O) == (0 if I else 1)
  189. @pytest.mark.parametrize("op", ["and_", "or_", "xor"])
  190. def test_binary(op):
  191. class TestBinary(m.Circuit):
  192. io = m.IO(I0=m.In(m.Bit), I1=m.In(m.Bit), O=m.Out(m.Bit))
  193. io.O <= getattr(operator, op)(io.I0, io.I1)
  194. clean_op = op.replace("_", "")
  195. assert repr(TestBinary) == f"""\
  196. TestBinary = DefineCircuit("TestBinary", "I0", In(Bit), "I1", In(Bit), \
  197. "O", Out(Bit))
  198. magma_Bit_{clean_op}_inst0 = magma_Bit_{clean_op}()
  199. wire(TestBinary.I0, magma_Bit_{clean_op}_inst0.in0)
  200. wire(TestBinary.I1, magma_Bit_{clean_op}_inst0.in1)
  201. wire(magma_Bit_{clean_op}_inst0.out, TestBinary.O)
  202. EndCircuit()\
  203. """
  204. m.compile(f"build/TestBit{clean_op}", TestBinary, output="coreir-verilog")
  205. assert check_files_equal(__file__, f"build/TestBit{clean_op}.v",
  206. f"gold/TestBit{clean_op}.v")
  207. sim = PythonSimulator(TestBinary)
  208. for I0, I1 in zip([0, 1], [0, 1]):
  209. sim.set_value(TestBinary.I0, I0)
  210. sim.set_value(TestBinary.I1, I1)
  211. sim.evaluate()
  212. assert sim.get_value(TestBinary.O) == getattr(operator, op)(I0, I1)
  213. def test_eq():
  214. class TestBinary(m.Circuit):
  215. io = m.IO(I0=m.In(m.Bit), I1=m.In(m.Bit), O=m.Out(m.Bit))
  216. # Nasty precidence issue with <= operator means we need parens here
  217. io.O <= (io.I0 == io.I1)
  218. assert repr(TestBinary) == f"""\
  219. TestBinary = DefineCircuit("TestBinary", "I0", In(Bit), "I1", In(Bit), \
  220. "O", Out(Bit))
  221. magma_Bit_not_inst0 = magma_Bit_not()
  222. magma_Bit_xor_inst0 = magma_Bit_xor()
  223. wire(magma_Bit_xor_inst0.out, magma_Bit_not_inst0.in)
  224. wire(TestBinary.I0, magma_Bit_xor_inst0.in0)
  225. wire(TestBinary.I1, magma_Bit_xor_inst0.in1)
  226. wire(magma_Bit_not_inst0.out, TestBinary.O)
  227. EndCircuit()\
  228. """
  229. m.compile(f"build/TestBiteq", TestBinary, output="coreir-verilog")
  230. assert check_files_equal(__file__, f"build/TestBiteq.v",
  231. f"gold/TestBiteq.v")
  232. sim = PythonSimulator(TestBinary)
  233. for I0, I1 in zip([0, 1], [0, 1]):
  234. sim.set_value(TestBinary.I0, I0)
  235. sim.set_value(TestBinary.I1, I1)
  236. sim.evaluate()
  237. assert sim.get_value(TestBinary.O) == (I0 == I1)
  238. def test_ne():
  239. class TestBinary(m.Circuit):
  240. io = m.IO(I0=m.In(m.Bit), I1=m.In(m.Bit), O=m.Out(m.Bit))
  241. # Nasty precidence issue with <= operator means we need parens here
  242. io.O <= (io.I0 != io.I1)
  243. assert repr(TestBinary) == f"""\
  244. TestBinary = DefineCircuit("TestBinary", "I0", In(Bit), "I1", In(Bit), \
  245. "O", Out(Bit))
  246. magma_Bit_xor_inst0 = magma_Bit_xor()
  247. wire(TestBinary.I0, magma_Bit_xor_inst0.in0)
  248. wire(TestBinary.I1, magma_Bit_xor_inst0.in1)
  249. wire(magma_Bit_xor_inst0.out, TestBinary.O)
  250. EndCircuit()\
  251. """
  252. m.compile(f"build/TestBitne", TestBinary, output="coreir-verilog")
  253. assert check_files_equal(__file__, f"build/TestBitne.v",
  254. f"gold/TestBitne.v")
  255. sim = PythonSimulator(TestBinary)
  256. for I0, I1 in zip([0, 1], [0, 1]):
  257. sim.set_value(TestBinary.I0, I0)
  258. sim.set_value(TestBinary.I1, I1)
  259. sim.evaluate()
  260. assert sim.get_value(TestBinary.O) == (I0 != I1)
  261. def test_ite():
  262. class TestITE(m.Circuit):
  263. io = m.IO(I0=m.In(m.Bit), I1=m.In(m.Bit), S=m.In(m.Bit),
  264. O=m.Out(m.Bit))
  265. io.O <= io.S.ite(io.I0, io.I1)
  266. assert repr(TestITE) == """\
  267. TestITE = DefineCircuit("TestITE", "I0", In(Bit), "I1", In(Bit), "S", In(Bit), \
  268. "O", Out(Bit))
  269. Mux2xBit_inst0 = Mux2xBit()
  270. wire(TestITE.I1, Mux2xBit_inst0.I0)
  271. wire(TestITE.I0, Mux2xBit_inst0.I1)
  272. wire(TestITE.S, Mux2xBit_inst0.S)
  273. wire(Mux2xBit_inst0.O, TestITE.O)
  274. EndCircuit()\
  275. """, repr(TestITE)
  276. m.compile(f"build/TestBitite", TestITE, output="coreir-verilog")
  277. assert check_files_equal(__file__, f"build/TestBitite.v",
  278. f"gold/TestBitite.v")
  279. sim = PythonSimulator(TestITE)
  280. for I0, I1, S in zip([0, 1], [0, 1], [0, 1]):
  281. sim.set_value(TestITE.I0, I0)
  282. sim.set_value(TestITE.I1, I1)
  283. sim.set_value(TestITE.S, S)
  284. sim.evaluate()
  285. assert sim.get_value(TestITE.O) == (I1 if S else I0)
  286. @pytest.mark.parametrize("op", [int, bool])
  287. def test_errors(op):
  288. with pytest.raises(NotImplementedError):
  289. op(m.Bit(name="b"))