diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index c393708..33e4921 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -66,4 +66,6 @@ jobs: pytest ../cgra/translate/CGRAMemRightAndBottomRTL_matmul_2x2_test.py -xvs --tb=short pytest ../cgra/translate/CGRAMemRightAndBottomRTL_matmul_2x2_test.py -xvs --tb=short --test-verilog --dump-vtb --dump-vcd pytest ../noc/PyOCN/pymtl3_net/ringnet/test/RingNetworkRTL_test.py --tb=short -sv + pytest --tb=short -sv ../cgra/translate/CGRAWithControllerRTL_test.py --test-verilog --dump-vtb --dump-vcd + pytest --tb=short -sv ../scale_out/translate/RingMultiCGRARTL_test.py --test-verilog --dump-vtb --dump-vcd diff --git a/cgra/CGRAWithControllerRTL.py b/cgra/CGRAWithControllerRTL.py index 53103b6..1695993 100644 --- a/cgra/CGRAWithControllerRTL.py +++ b/cgra/CGRAWithControllerRTL.py @@ -13,8 +13,8 @@ from ..fu.single.AdderRTL import AdderRTL from ..lib.util.common import * from ..lib.basic.en_rdy.ifcs import SendIfcRTL, RecvIfcRTL -from ..lib.basic.val_rdy.ifcs import SendIfcRTL as ValRdySendIfcRTL -from ..lib.basic.val_rdy.ifcs import RecvIfcRTL as ValRdyRecvIfcRTL +from ..lib.basic.val_rdy.ifcs import ValRdySendIfcRTL +from ..lib.basic.val_rdy.ifcs import ValRdyRecvIfcRTL from ..lib.opt_type import * from ..mem.data.DataMemScalableRTL import DataMemScalableRTL from ..noc.ChannelNormalRTL import ChannelNormalRTL @@ -35,9 +35,12 @@ def construct(s, DataType, PredicateType, CtrlType, NocPktType, AddrType = mk_bits(clog2(ctrl_mem_size)) # Interfaces - s.recv_waddr = [RecvIfcRTL(AddrType) for _ in range(s.num_tiles)] - s.recv_wopt = [RecvIfcRTL(CtrlType) for _ in range(s.num_tiles)] + s.recv_waddr = [RecvIfcRTL(AddrType) for _ in range(s.num_tiles)] + s.recv_wopt = [RecvIfcRTL(CtrlType) for _ in range(s.num_tiles)] + # Explicitly provides the ValRdyRecvIfcRTL in the library, as the + # translation pass sometimes not able to distinguish the + # EnRdyRecvIfcRTL from it. s.recv_from_other = ValRdyRecvIfcRTL(NocPktType) s.send_to_other = ValRdySendIfcRTL(NocPktType) diff --git a/cgra/translate/CGRAWithControllerRTL_test.py b/cgra/translate/CGRAWithControllerRTL_test.py new file mode 100644 index 0000000..4d50a18 --- /dev/null +++ b/cgra/translate/CGRAWithControllerRTL_test.py @@ -0,0 +1,156 @@ +""" +========================================================================== +CGRAWithControllerRTL_test.py +========================================================================== +Test cases for CGRA with controller. + +Author : Cheng Tan + Date : Dec 4, 2024 +""" + + +from pymtl3 import * +from pymtl3.stdlib.test_utils import (run_sim, + config_model_with_cmdline_opts) +from pymtl3.passes.backends.verilog import (VerilogTranslationPass, + VerilogVerilatorImportPass) +from ..CGRAWithControllerRTL import CGRAWithControllerRTL +from ...fu.flexible.FlexibleFuRTL import FlexibleFuRTL +from ...fu.single.AdderRTL import AdderRTL +from ...fu.single.MemUnitRTL import MemUnitRTL +from ...fu.single.ShifterRTL import ShifterRTL +from ...lib.messages import * +from ...lib.opt_type import * +from ...lib.basic.en_rdy.test_srcs import TestSrcRTL + + +#------------------------------------------------------------------------- +# Test harness +#------------------------------------------------------------------------- + +class TestHarness(Component): + + def construct(s, DUT, FunctionUnit, FuList, DataType, PredicateType, + CtrlType, NocPktType, width, height, ctrl_mem_size, + data_mem_size, src_opt, ctrl_waddr): + + s.num_tiles = width * height + AddrType = mk_bits(clog2(ctrl_mem_size)) + + s.src_opt = [TestSrcRTL(CtrlType, src_opt[i]) + for i in range(s.num_tiles)] + s.ctrl_waddr = [TestSrcRTL(AddrType, ctrl_waddr[i]) + for i in range(s.num_tiles)] + + s.dut = DUT(DataType, PredicateType, CtrlType, NocPktType, + width, height, ctrl_mem_size, data_mem_size, + len(src_opt[0]), len(src_opt[0]), FunctionUnit, FuList) + + # Connections + s.dut.send_to_other.rdy //= 0 + s.dut.recv_from_other.val //= 0 + s.dut.recv_from_other.msg //= NocPktType(0, 0, 0, 0, 0, 0) + + for i in range(s.num_tiles): + connect(s.src_opt[i].send, s.dut.recv_wopt[i]) + connect(s.ctrl_waddr[i].send, s.dut.recv_waddr[i]) + + def done(s): + done = True + for i in range(s.num_tiles): + if not s.src_opt[i].done(): + done = False + break + return done + + def line_trace(s): + return s.dut.line_trace() + +def test_homo_2x2(cmdline_opts): + num_tile_inports = 4 + num_tile_outports = 4 + num_fu_inports = 4 + num_fu_outports = 2 + num_routing_outports = num_tile_outports + num_fu_inports + ctrl_mem_size = 6 + data_mem_size = 8 + width = 2 + height = 2 + TileInType = mk_bits(clog2(num_tile_inports + 1)) + FuInType = mk_bits(clog2(num_fu_inports + 1)) + FuOutType = mk_bits(clog2(num_fu_outports + 1)) + AddrType = mk_bits(clog2(ctrl_mem_size)) + num_tiles = width * height + DUT = CGRAWithControllerRTL + FunctionUnit = FlexibleFuRTL + FuList = [MemUnitRTL, AdderRTL] + DataType = mk_data(32, 1) + PredicateType = mk_predicate(1, 1) + CtrlType = mk_separate_ctrl(num_fu_inports, num_fu_outports, + num_tile_inports, num_tile_outports) + NocPktType = mk_ring_multi_cgra_pkt(nrouters = 4, + payload_nbits = 32, + predicate_nbits = 1) + pickRegister = [FuInType(x + 1) for x in range(num_fu_inports)] + src_opt = [[ + CtrlType(OPT_INC, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + # TODO: make below as TileInType(5) to double check. + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + CtrlType(OPT_INC, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_ADD, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_STR, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_ADD, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_ADD, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]) + + ] for _ in range(num_tiles)] + ctrl_waddr = [[AddrType(0), AddrType(1), AddrType(2), AddrType(3), + AddrType(4), AddrType(5)] for _ in range(num_tiles)] + th = TestHarness(DUT, FunctionUnit, FuList, DataType, PredicateType, + CtrlType, NocPktType, width, height, ctrl_mem_size, + data_mem_size, src_opt, ctrl_waddr) + th.elaborate() + th.dut.set_metadata(VerilogVerilatorImportPass.vl_Wno_list, + ['UNSIGNED', 'UNOPTFLAT', 'WIDTH', 'WIDTHCONCAT', + 'ALWCOMBORDER']) + th = config_model_with_cmdline_opts(th, cmdline_opts, duts=['dut']) + run_sim(th) + diff --git a/lib/basic/val_rdy/ifcs.py b/lib/basic/val_rdy/ifcs.py index 0912b51..644b98f 100644 --- a/lib/basic/val_rdy/ifcs.py +++ b/lib/basic/val_rdy/ifcs.py @@ -29,6 +29,19 @@ def construct( s, Type ): def __str__( s ): return valrdy_to_str( s.msg, s.val, s.rdy, s.trace_len ) +class ValRdyRecvIfcRTL( Interface ): + + def construct( s, Type ): + + s.msg = InPort( Type ) + s.val = InPort() + s.rdy = OutPort() + + s.trace_len = len(str(Type())) + + def __str__( s ): + return valrdy_to_str( s.msg, s.val, s.rdy, s.trace_len ) + class SendIfcRTL( Interface ): def construct( s, Type ): @@ -42,6 +55,19 @@ def construct( s, Type ): def __str__( s ): return valrdy_to_str( s.msg, s.val, s.rdy, s.trace_len ) +class ValRdySendIfcRTL( Interface ): + + def construct( s, Type ): + + s.msg = OutPort( Type ) + s.val = OutPort() + s.rdy = InPort() + + s.trace_len = len(str(Type())) + + def __str__( s ): + return valrdy_to_str( s.msg, s.val, s.rdy, s.trace_len ) + class MasterIfcRTL( Interface ): def construct( s, ReqType, RespType ): s.ReqType = ReqType diff --git a/scale_out/translate/RingMultiCGRARTL_test.py b/scale_out/translate/RingMultiCGRARTL_test.py new file mode 100644 index 0000000..017beec --- /dev/null +++ b/scale_out/translate/RingMultiCGRARTL_test.py @@ -0,0 +1,166 @@ +""" +========================================================================== +CGRAWithControllerRTL_test.py +========================================================================== +Test cases for CGRA with controller. + +Author : Cheng Tan + Date : Dec 4, 2024 +""" + + +from pymtl3 import * +from pymtl3.stdlib.test_utils import (run_sim, + config_model_with_cmdline_opts) +from pymtl3.passes.backends.verilog import (VerilogTranslationPass, + VerilogVerilatorImportPass) +from ..RingMultiCGRARTL import RingMultiCGRARTL +from ...fu.flexible.FlexibleFuRTL import FlexibleFuRTL +from ...fu.single.AdderRTL import AdderRTL +from ...fu.single.MemUnitRTL import MemUnitRTL +from ...fu.single.ShifterRTL import ShifterRTL +from ...lib.messages import * +from ...lib.opt_type import * +from ...lib.basic.en_rdy.test_srcs import TestSrcRTL + + +#------------------------------------------------------------------------- +# Test harness +#------------------------------------------------------------------------- + +class TestHarness(Component): + + def construct(s, DUT, FunctionUnit, FuList, DataType, PredicateType, + CtrlType, NocPktType, num_terminals, width, height, + ctrl_mem_size, data_mem_size, src_opt, ctrl_waddr): + + s.num_terminals = num_terminals + s.num_tiles = width * height + AddrType = mk_bits(clog2(ctrl_mem_size)) + + s.src_opt = [[TestSrcRTL(CtrlType, src_opt[j]) + for j in range(s.num_tiles)] + for i in range(s.num_terminals)] + s.ctrl_waddr = [[TestSrcRTL(AddrType, ctrl_waddr[j]) + for j in range(s.num_tiles)] + for i in range(s.num_terminals)] + + s.dut = DUT(DataType, AddrType, PredicateType, CtrlType, NocPktType, + num_terminals, width, height, ctrl_mem_size, data_mem_size, + len(src_opt[0]), len(src_opt[0]), FunctionUnit, FuList) + + # Connections + # s.dut.data_mem.recv_from_noc.rdy //= 0 + # s.dut.data_mem.send_to_noc.msg //= DataType(0, 0) + # s.dut.data_mem.send_to_noc.en //= 0 + # s.src_val_rdy.send //= s.dut.recv_from_other + # s.dut.send_to_other //= s.sink_val_rdy.recv + + # s.dut.recv_towards_controller.en //= 0 + # s.dut.recv_towards_controller.msg //= DataType(0, 0) + # s.dut.send_from_controller.rdy //= 0 + + for i in range(num_terminals): + for j in range(s.num_tiles): + connect(s.src_opt[i][j].send, s.dut.recv_wopt[i][j]) + connect(s.ctrl_waddr[i][j].send, s.dut.recv_waddr[i][j]) + + def done(s): + for i in range(s.num_terminals): + for j in range(s.num_tiles): + if not s.src_opt[i][j].done(): + return False + return True + + def line_trace(s): + return s.dut.line_trace() + +def test_homo_2x2(cmdline_opts): + num_tile_inports = 4 + num_tile_outports = 4 + num_fu_inports = 4 + num_fu_outports = 2 + num_routing_outports = num_tile_outports + num_fu_inports + ctrl_mem_size = 6 + data_mem_size = 8 + num_terminals = 4 + width = 2 + height = 2 + TileInType = mk_bits(clog2(num_tile_inports + 1)) + FuInType = mk_bits(clog2(num_fu_inports + 1)) + FuOutType = mk_bits(clog2(num_fu_outports + 1)) + AddrType = mk_bits(clog2(ctrl_mem_size)) + num_tiles = width * height + DUT = RingMultiCGRARTL + FunctionUnit = FlexibleFuRTL + FuList = [MemUnitRTL, AdderRTL] + DataType = mk_data(32, 1) + PredicateType = mk_predicate(1, 1) + CtrlType = mk_separate_ctrl(num_fu_inports, num_fu_outports, + num_tile_inports, num_tile_outports) + NocPktType = mk_ring_multi_cgra_pkt(nrouters = num_terminals, + payload_nbits = 32, + predicate_nbits = 1) + pickRegister = [FuInType(x + 1) for x in range(num_fu_inports)] + src_opt = [[ + CtrlType(OPT_INC, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + # TODO: make below as TileInType(5) to double check. + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + CtrlType(OPT_INC, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_ADD, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_STR, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_ADD, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]), + + CtrlType(OPT_ADD, b1(0), + pickRegister, + [TileInType(4), TileInType(3), TileInType(2), TileInType(1), + TileInType(0), TileInType(0), TileInType(0), TileInType(0)], + + [FuOutType(0), FuOutType(0), FuOutType(0), FuOutType(0), + FuOutType(1), FuOutType(1), FuOutType(1), FuOutType(1)]) + + ] for _ in range(num_tiles)] + ctrl_waddr = [[AddrType(0), AddrType(1), AddrType(2), AddrType(3), + AddrType(4), AddrType(5)] for _ in range(num_tiles)] + th = TestHarness(DUT, FunctionUnit, FuList, DataType, PredicateType, + CtrlType, NocPktType, num_terminals, width, height, + ctrl_mem_size, data_mem_size, src_opt, ctrl_waddr) + th.elaborate() + th.dut.set_metadata(VerilogVerilatorImportPass.vl_Wno_list, + ['UNSIGNED', 'UNOPTFLAT', 'WIDTH', 'WIDTHCONCAT', + 'ALWCOMBORDER']) + th = config_model_with_cmdline_opts(th, cmdline_opts, duts=['dut']) + run_sim(th) + diff --git a/scale_out/translate/RingWithControllerRTL_test.py b/scale_out/translate/RingWithControllerRTL_test.py new file mode 100644 index 0000000..d3cf9f5 --- /dev/null +++ b/scale_out/translate/RingWithControllerRTL_test.py @@ -0,0 +1,158 @@ +""" +========================================================================= +RingWithControllerRTL_test.py +========================================================================= +Test for RingControllerRTL with CGRA message. + +Author : Cheng Tan + Date : Dec 3, 2024 +""" + + +from pymtl3 import * +from ...lib.messages import * +from ...lib.opt_type import * +from ...lib.basic.en_rdy.test_sinks import TestSinkRTL +from ...lib.basic.en_rdy.test_srcs import TestSrcRTL +from ..RingWithControllerRTL import RingWithControllerRTL +from pymtl3.stdlib.test_utils import config_model_with_cmdline_opts +from pymtl3.passes.backends.verilog import (VerilogTranslationPass, + VerilogVerilatorImportPass) + + +#------------------------------------------------------------------------- +# TestHarness +#------------------------------------------------------------------------- + +class TestHarness(Component): + + def construct(s, RingPktType, CGRADataType, CGRAAddrType, num_terminals, + src_msgs, sink_msgs): + + s.num_terminals = num_terminals + s.srcs = [TestSrcRTL(CGRADataType, src_msgs[i]) + for i in range(num_terminals)] + s.dut = RingWithControllerRTL(RingPktType, CGRADataType, + CGRAAddrType, num_terminals) + s.sinks = [TestSinkRTL(CGRADataType, sink_msgs[i]) + for i in range(num_terminals)] + + # Connections + for i in range (s.dut.num_terminals): + s.srcs[i].send //= s.dut.recv_from_master[i] + s.dut.send_to_master[i] //= s.sinks[i].recv + + def done(s): + for i in range(s.num_terminals): + if not s.srcs[i].done() or not s.sinks[i].done(): + return False + return True + + def line_trace(s): + return s.dut.line_trace() + +#------------------------------------------------------------------------- +# run_rtl_sim +#------------------------------------------------------------------------- + +def run_sim(test_harness, max_cycles=20): + + # Create a simulator + test_harness.elaborate() + test_harness.apply( DefaultPassGroup() ) + test_harness.sim_reset() + + # Run simulation + ncycles = 0 + print() + print( "{}:{}".format( ncycles, test_harness.line_trace() )) + while not test_harness.done() and ncycles < max_cycles: + test_harness.sim_tick() + ncycles += 1 + print( "{}:{}".format( ncycles, test_harness.line_trace() )) + + # Check timeout + assert ncycles < max_cycles + + test_harness.sim_tick() + test_harness.sim_tick() + test_harness.sim_tick() + + +#========================================================================= +# Test cases +#========================================================================= + +# class RingWithController_Tests: +# +# @classmethod +# def setup_class(cls): +# cls.DutType = RingWithControllerRTL +# +# def _test_ring_data(s, translation = ''): +# DataType = mk_data(32, 1) +# num_terminals = 4 +# RingPktType = mk_ring_multi_cgra_pkt(num_terminals, +# payload_nbits = 32, +# predicate_nbits = 1) +# src_data = [ +# [], +# [], +# [DataType(7, 1, 1), DataType(2, 1), DataType(3, 1)], +# [DataType(7, 1, 1), DataType(2, 1), DataType(3, 1)] +# ] +# +# sink_data = [ +# [], +# [], +# [DataType(7, 1, 1), DataType(2, 1), DataType(3, 1)], +# [DataType(7, 1, 1), DataType(2, 1), DataType(3, 1)] +# ] +# +# ctrl_mem_size = 4 +# AddrType = mk_bits(clog2(ctrl_mem_size)) +# +# th = TestHarness(RingPktType, DataType, AddrType, num_terminals, +# src_data, sink_data) +# cmdline_opts={'dump_vcd': False, 'test_verilog': translation, +# 'dump_vtb': False} +# run_sim(th, cmdline_opts) +# +# def test_ring_data(self): +# self._test_ring_data('zeros') + + +DataType = mk_data(32, 1) +num_terminals = 4 +RingPktType = mk_ring_multi_cgra_pkt(num_terminals, + payload_nbits = 32, + predicate_nbits = 1) +src_data = [ + [], + [DataType(7, 1, 1), DataType(8, 1), DataType(9, 1)], + [DataType(1, 1, 1), DataType(2, 1), DataType(3, 1)], + [] + ] + +sink_data = [ + [], + [], + # The expected data is received in an interleaved way. + [DataType(1, 0, 0), DataType(7, 0, 0), DataType(2, 0, 0), DataType(8, 0, 0), DataType(3, 0, 0), DataType(9, 0, 0)], + [] + ] + +ctrl_mem_size = 4 +AddrType = mk_bits(clog2(ctrl_mem_size)) + +def test_simple(cmdline_opts): + th = TestHarness(RingPktType, DataType, AddrType, num_terminals, + src_data, sink_data) + th.elaborate() + th.dut.set_metadata(VerilogVerilatorImportPass.vl_Wno_list, + ['UNSIGNED', 'UNOPTFLAT', 'WIDTH', 'WIDTHCONCAT', + 'ALWCOMBORDER']) + th = config_model_with_cmdline_opts(th, cmdline_opts, duts=['dut']) + run_sim(th) + + diff --git a/scale_out/translate/__init__.py b/scale_out/translate/__init__.py new file mode 100644 index 0000000..e69de29