gen/common: Add Reduction function (To avoid using Python's reduction directly which is messy/confusing).
This commit is contained in:
parent
13448b8260
commit
5106fd43fc
|
@ -23,6 +23,31 @@ def reverse_bytes(s):
|
||||||
return Cat(*[s[i*8:min((i + 1)*8, len(s))]
|
return Cat(*[s[i*8:min((i + 1)*8, len(s))]
|
||||||
for i in reversed(range(n))])
|
for i in reversed(range(n))])
|
||||||
|
|
||||||
|
# Reduction ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
from operator import and_, or_, not_, xor
|
||||||
|
|
||||||
|
def Reduce(operator, value):
|
||||||
|
# List of supported Operators.
|
||||||
|
operators = {
|
||||||
|
"AND" : and_,
|
||||||
|
"OR" : or_,
|
||||||
|
"NOR" : not_,
|
||||||
|
"XOR" : xor,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Switch to upper-case.
|
||||||
|
operator = operator.upper()
|
||||||
|
|
||||||
|
# Check if provided operator is supported.
|
||||||
|
if operator not in operators.keys():
|
||||||
|
supported = ", ".join(operators.keys())
|
||||||
|
raise ValueError(f"Reduce does not support {operator} operator; supported: {supported}.")
|
||||||
|
|
||||||
|
# Return Python's reduction.
|
||||||
|
return reduce(operators[operator], value)
|
||||||
|
|
||||||
# LiteX Module -------------------------------------------------------------------------------------
|
# LiteX Module -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteXModule(Module, AutoCSR, AutoDoc):
|
class LiteXModule(Module, AutoCSR, AutoDoc):
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#
|
||||||
|
# This file is part of LiteX.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import random
|
||||||
|
|
||||||
|
from migen import *
|
||||||
|
|
||||||
|
from litex.gen import *
|
||||||
|
|
||||||
|
class TestReduce(unittest.TestCase):
|
||||||
|
def reduce_test(self, operator, value, reduced):
|
||||||
|
class DUT(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.errors = 0
|
||||||
|
self.reduced = Reduce(operator, value)
|
||||||
|
|
||||||
|
def checker(self):
|
||||||
|
yield
|
||||||
|
if (yield self.reduced) != reduced:
|
||||||
|
self.errors += 1
|
||||||
|
|
||||||
|
dut = DUT()
|
||||||
|
run_simulation(dut, [dut.checker()])
|
||||||
|
self.assertEqual(dut.errors, 0)
|
||||||
|
|
||||||
|
def test_reduced_and(self):
|
||||||
|
self.reduce_test(operator="AND", value=Constant(0b00, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="AND", value=Constant(0b01, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="AND", value=Constant(0b10, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="AND", value=Constant(0b11, 2), reduced=0b1)
|
||||||
|
|
||||||
|
def test_reduced_or(self):
|
||||||
|
self.reduce_test(operator="OR", value=Constant(0b00, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="OR", value=Constant(0b01, 2), reduced=0b1)
|
||||||
|
self.reduce_test(operator="OR", value=Constant(0b10, 2), reduced=0b1)
|
||||||
|
self.reduce_test(operator="OR", value=Constant(0b11, 2), reduced=0b1)
|
||||||
|
|
||||||
|
def test_reduced_nor(self):
|
||||||
|
self.reduce_test(operator="NOR", value=Constant(0b00, 2), reduced=0b1)
|
||||||
|
self.reduce_test(operator="NOR", value=Constant(0b01, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="NOR", value=Constant(0b10, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="NOR", value=Constant(0b11, 2), reduced=0b0)
|
||||||
|
|
||||||
|
def test_reduced_nor(self):
|
||||||
|
self.reduce_test(operator="XOR", value=Constant(0b00, 2), reduced=0b0)
|
||||||
|
self.reduce_test(operator="XOR", value=Constant(0b01, 2), reduced=0b1)
|
||||||
|
self.reduce_test(operator="XOR", value=Constant(0b10, 2), reduced=0b1)
|
||||||
|
self.reduce_test(operator="XOR", value=Constant(0b11, 2), reduced=0b0)
|
Loading…
Reference in New Issue