From 1621ceb65a72d9b599834be307376014caf8ea5c Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 28 Sep 2019 19:33:24 +0000 Subject: [PATCH] hdl.ast: actually implement the // operator. --- nmigen/back/pysim.py | 4 ++++ nmigen/back/rtlil.py | 2 +- nmigen/hdl/ast.py | 11 +++++++---- nmigen/test/test_hdl_ast.py | 11 +++++++++++ nmigen/test/test_sim.py | 6 ++++++ 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/nmigen/back/pysim.py b/nmigen/back/pysim.py index 0f7e8c0..472cc57 100644 --- a/nmigen/back/pysim.py +++ b/nmigen/back/pysim.py @@ -146,6 +146,10 @@ class _RHSValueCompiler(_ValueCompiler): return lambda state: normalize(lhs(state) - rhs(state), shape) if value.op == "*": return lambda state: normalize(lhs(state) * rhs(state), shape) + if value.op == "//": + def floordiv(lhs, rhs): + return 0 if rhs == 0 else lhs // rhs + return lambda state: normalize(floordiv(lhs(state), rhs(state)), shape) if value.op == "&": return lambda state: normalize(lhs(state) & rhs(state), shape) if value.op == "|": diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 11823d4..e7ec34c 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -388,7 +388,7 @@ class _RHSValueCompiler(_ValueCompiler): (2, "+"): "$add", (2, "-"): "$sub", (2, "*"): "$mul", - (2, "/"): "$div", + (2, "//"): "$div", (2, "%"): "$mod", (2, "**"): "$pow", (2, "<<"): "$sshl", diff --git a/nmigen/hdl/ast.py b/nmigen/hdl/ast.py index 2dee3ff..6a68a67 100644 --- a/nmigen/hdl/ast.py +++ b/nmigen/hdl/ast.py @@ -87,10 +87,10 @@ class Value(metaclass=ABCMeta): return Operator("%", [self, other]) def __rmod__(self, other): return Operator("%", [other, self]) - def __div__(self, other): - return Operator("/", [self, other]) - def __rdiv__(self, other): - return Operator("/", [other, self]) + def __floordiv__(self, other): + return Operator("//", [self, other]) + def __rfloordiv__(self, other): + return Operator("//", [other, self]) def __lshift__(self, other): return Operator("<<", [self, other]) def __rlshift__(self, other): @@ -475,6 +475,9 @@ class Operator(Value): return width + 1, signed if self.op == "*": return a_width + b_width, a_signed or b_signed + if self.op == "//": + # division by -1 can overflow + return a_width + b_signed, a_signed or b_signed if self.op == "%": return a_width, a_signed if self.op in ("<", "<=", "==", "!=", ">", ">="): diff --git a/nmigen/test/test_hdl_ast.py b/nmigen/test/test_hdl_ast.py index 143de35..0c4914b 100644 --- a/nmigen/test/test_hdl_ast.py +++ b/nmigen/test/test_hdl_ast.py @@ -181,6 +181,17 @@ class OperatorTestCase(FHDLTestCase): v5 = 10 * Const(0, 4) self.assertEqual(v5.shape(), (8, False)) + def test_floordiv(self): + v1 = Const(0, (4, False)) // Const(0, (6, False)) + self.assertEqual(repr(v1), "(// (const 4'd0) (const 6'd0))") + self.assertEqual(v1.shape(), (4, False)) + v2 = Const(0, (4, True)) // Const(0, (6, True)) + self.assertEqual(v2.shape(), (5, True)) + v3 = Const(0, (4, True)) // Const(0, (4, False)) + self.assertEqual(v3.shape(), (4, True)) + v5 = 10 // Const(0, 4) + self.assertEqual(v5.shape(), (4, False)) + def test_and(self): v1 = Const(0, (4, False)) & Const(0, (6, False)) self.assertEqual(repr(v1), "(& (const 4'd0) (const 6'd0))") diff --git a/nmigen/test/test_sim.py b/nmigen/test/test_sim.py index adfad0e..8126f1b 100644 --- a/nmigen/test/test_sim.py +++ b/nmigen/test/test_sim.py @@ -95,6 +95,12 @@ class SimulatorUnitTestCase(FHDLTestCase): self.assertStatement(stmt, [C(2, 4), C(2, 4)], C(4, 8)) self.assertStatement(stmt, [C(7, 4), C(7, 4)], C(49, 8)) + def test_floordiv(self): + stmt = lambda y, a, b: y.eq(a // b) + self.assertStatement(stmt, [C(2, 4), C(1, 4)], C(2, 8)) + self.assertStatement(stmt, [C(2, 4), C(2, 4)], C(1, 8)) + self.assertStatement(stmt, [C(7, 4), C(2, 4)], C(3, 8)) + def test_and(self): stmt = lambda y, a, b: y.eq(a & b) self.assertStatement(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b1000, 4)) -- 2.30.2