Skip to content

Commit

Permalink
[feature] Test ring with CGRA data type
Browse files Browse the repository at this point in the history
  • Loading branch information
tancheng committed Dec 2, 2024
1 parent ff94b25 commit 9406bf7
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 30 deletions.
122 changes: 92 additions & 30 deletions lib/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def str_func( s ):
# Generic config message
#=========================================================================

def mk_ctrl( num_fu_in=2, num_inports=5, num_outports=5, prefix="CGRAConfig" ):
def mk_ctrl(num_fu_in = 2, num_inports = 5, num_outports = 5,
prefix = "CGRAConfig"):

ctrl_nbits = 6
CtrlType = mk_bits( ctrl_nbits )
Expand All @@ -72,7 +73,8 @@ def mk_ctrl( num_fu_in=2, num_inports=5, num_outports=5, prefix="CGRAConfig" ):
FuInType = mk_bits( clog2( num_fu_in + 1 ) )
PredicateType = mk_bits( 1 )

new_name = f"{prefix}_{ctrl_nbits}_{num_fu_in}_{num_inports}_{num_outports}"
new_name = f"{prefix}_{ctrl_nbits}_{num_fu_in}_{num_inports}_" \
f"{num_outports}"

def str_func( s ):
out_str = '(in)'
Expand Down Expand Up @@ -100,27 +102,31 @@ def str_func( s ):
return f"(opt){s.ctrl}|{out_str}"

field_dict = {}
field_dict[ 'ctrl' ] = CtrlType
# The 'predicate' indicates whether the current operation is based on the partial
# predication or not. Note that 'predicate' is different from the following
# 'predicate_in', which contributes to the 'predicate' at the next cycle.
field_dict[ 'predicate' ] = PredicateType
# The fu_in indicates the input register ID (i.e., operands) for the operation.
field_dict[ 'fu_in' ] = [ FuInType for _ in range( num_fu_in ) ]

field_dict[ 'outport' ] = [ InportsType for _ in range( num_outports ) ]
# I assume one tile supports single predicate during the entire execution time, as
# it is hard to distinguish predication for different operations (we automatically
# update, i.e., 'or', the predicate stored in the predicate register). This should
# be guaranteed by the compiler.
field_dict[ 'predicate_in' ] = [ PredicateType for _ in range( num_inports ) ]
field_dict['ctrl'] = CtrlType
# The 'predicate' indicates whether the current operation is based on
# the partial predication or not. Note that 'predicate' is different
# from the following 'predicate_in', which contributes to the
# 'predicate' at the next cycle.
field_dict['predicate'] = PredicateType
# The fu_in indicates the input register ID (i.e., operands) for the
# operation.
field_dict['fu_in'] = [FuInType for _ in range(num_fu_in)]

field_dict['outport'] = [InportsType for _ in range(num_outports)]
# I assume one tile supports single predicate during the entire
# execution time, as it is hard to distinguish predication for
# different operations (we automatically update, i.e., 'or', the
# predicate stored in the predicate register). This should be
# guaranteed by the compiler.
field_dict['predicate_in'] = [PredicateType for _ in range(
num_inports)]

# TODO: to support multiple predicate
# field_dict[ 'predicate_in0' ] = ...
# field_dict[ 'predicate_in1' ] = ...

return mk_bitstruct( new_name, field_dict,
namespace = { '__str__': str_func }
return mk_bitstruct(new_name, field_dict,
namespace = {'__str__': str_func}
)


Expand All @@ -139,7 +145,9 @@ def mk_separate_ctrl(num_fu_inports = 4,
FuOutType = mk_bits(clog2(num_fu_outports + 1))
PredicateType = mk_bits(1)

new_name = f"{prefix}_{operation_nbits}_{num_fu_inports}_{num_fu_outports}_{num_tile_inports}_{num_tile_outports}"
new_name = f"{prefix}_{operation_nbits}_{num_fu_inports}_" \
f"{num_fu_outports}_{num_tile_inports}_" \
f"{num_tile_outports}"

def str_func(s):
out_str = '(fu_in)'
Expand Down Expand Up @@ -180,20 +188,25 @@ def str_func(s):
field_dict = {}
field_dict['ctrl'] = OperationType
# TODO: need fix to pair `predicate` with specific operation.
# The 'predicate' indicates whether the current operation is based on the partial
# predication or not. Note that 'predicate' is different from the following
# 'predicate_in', which contributes to the 'predicate' at the next cycle.
# The 'predicate' indicates whether the current operation is based on
# the partial predication or not. Note that 'predicate' is different
# from the following 'predicate_in', which contributes to the 'predicate'
# at the next cycle.
field_dict['predicate'] = PredicateType
# The fu_in indicates the input register ID (i.e., operands) for the operation.
# The fu_in indicates the input register ID (i.e., operands) for the
# operation.
field_dict['fu_in'] = [FuInType for _ in range(num_fu_inports)]

field_dict['routing_xbar_outport'] = [TileInportsType for _ in range(num_routing_outports)]
field_dict['fu_xbar_outport'] = [FuOutType for _ in range(num_routing_outports)]
# I assume one tile supports single predicate during the entire execution time, as
# it is hard to distinguish predication for different operations (we automatically
# update, i.e., 'or', the predicate stored in the predicate register). This should
# be guaranteed by the compiler.
field_dict['routing_predicate_in'] = [PredicateType for _ in range(num_tile_inports)]
field_dict['routing_xbar_outport'] = [TileInportsType for _ in range(
num_routing_outports)]
field_dict['fu_xbar_outport'] = [FuOutType for _ in range(
num_routing_outports)]
# I assume one tile supports single predicate during the entire execution
# time, as it is hard to distinguish predication for different operations
# (we automatically update, i.e., 'or', the predicate stored in the
# predicate register). This should be guaranteed by the compiler.
field_dict['routing_predicate_in'] = [PredicateType for _ in range(
num_tile_inports)]

# TODO: to support multiple predicate
# field_dict[ 'predicate_in0' ] = ...
Expand All @@ -203,3 +216,52 @@ def str_func(s):
namespace = { '__str__': str_func }
)


#=========================================================================
# Ring multi-CGRA data/config/cmd packet
#=========================================================================

def mk_ring_multi_cgra_pkt(nrouters = 4, opaque_nbits = 8, vc = 2,
payload_nbits = 16, predicate_nbits = 1,
prefix="RingMultiCGRAPacket" ):

IdType = mk_bits(clog2(nrouters))
OpqType = mk_bits(opaque_nbits)
PayloadType = mk_bits(payload_nbits)
PredicateType = mk_bits(predicate_nbits)

new_name = f"{prefix}_{nrouters}_{vc}_{opaque_nbits}_{payload_nbits}_" \
f"{predicate_nbits}"

if vc > 1:
VcIdType = mk_bits( clog2( vc ) )

def str_func( s ):
return f"{s.src}>{s.dst}:{s.opaque}:{s.vc_id}:{s.payload}." \
f"{s.predicate}"

return mk_bitstruct( new_name, {
'src': IdType,
'dst': IdType,
'opaque': OpqType,
'vc_id': VcIdType,
'payload': PayloadType,
'predicate': PredicateType,
},
namespace = { '__str__': str_func }
)

else:
def str_func( s ):
return f"{s.src}>{s.dst}:{s.opaque}:{s.payload}.{s.predicate}"

return mk_bitstruct( new_name, {
'src': IdType,
'dst': IdType,
'opaque': OpqType,
'payload': PayloadType,
'predicate': PredicateType,
},
namespace = { '__str__': str_func }
)

Empty file added multi_cgra/__init__.py
Empty file.
104 changes: 104 additions & 0 deletions multi_cgra/test/RingNetworkRTL_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""
=========================================================================
RingNetworkRTL_test.py
=========================================================================
Test for RingNetworkRTL with CGRA message.
Author : Cheng Tan
Date : Dec 1, 2024
"""


from pymtl3 import *
from ...lib.basic.val_rdy.SourceRTL import SourceRTL as TestSrcRTL
from ...lib.messages import *
from ...lib.opt_type import *
# from ...noc.PyOCN.pymtl3_net.ocnlib.ifcs.packets import mk_ring_pkt
from ...noc.PyOCN.pymtl3_net.ocnlib.ifcs.positions import mk_ring_pos
from ...noc.PyOCN.pymtl3_net.ocnlib.utils import run_sim
from ...noc.PyOCN.pymtl3_net.ocnlib.test.stream_sinks import NetSinkRTL as TestNetSinkRTL
from ...noc.PyOCN.pymtl3_net.ringnet.RingNetworkFL import ringnet_fl
from ...noc.PyOCN.pymtl3_net.ringnet.RingNetworkRTL import RingNetworkRTL


#-------------------------------------------------------------------------
# TestHarness
#-------------------------------------------------------------------------

class TestHarness(Component):

def construct(s, MsgType, num_routers, src_msgs, sink_msgs):

s.num_routers = num_routers
RingPos = mk_ring_pos(num_routers)
cmp_fn = lambda a, b : a.payload == b.payload

s.srcs = [TestSrcRTL(MsgType, src_msgs[i])
for i in range(num_routers)]
s.dut = RingNetworkRTL(MsgType, RingPos, num_routers, 0)
s.sinks = [TestNetSinkRTL(MsgType, sink_msgs[i], cmp_fn = cmp_fn)
for i in range( num_routers)]

# Connections
for i in range (s.dut.num_routers):
s.srcs[i].send //= s.dut.recv[i]
s.dut.send[i] //= s.sinks[i].recv

def done(s):
srcs_done = True
sinks_done = True
for i in range(s.num_routers):
srcs_done = srcs_done and s.srcs[i].done()
sinks_done = sinks_done and s.sinks[i].done()
return srcs_done and sinks_done

def line_trace(s):
return s.dut.line_trace()

#-------------------------------------------------------------------------
# mk_src_pkts
#-------------------------------------------------------------------------

def mk_src_pkts( nterminals, lst ):
src_pkts = [ [] for _ in range( nterminals ) ]
src = 0
for pkt in lst:
if hasattr(pkt, 'fl_type'):
if pkt.fl_type == 0:
src = pkt.src
else:
src = pkt.src
src_pkts[ src ].append( pkt )
return src_pkts

#=========================================================================
# Test cases
#=========================================================================

class RingNetwork_Tests:

@classmethod
def setup_class(cls):
cls.DutType = RingNetworkRTL

def _test_cgra_data(s, translation = ''):
DataType = mk_data(16, 1)
nterminals = 4
Pkt = mk_ring_multi_cgra_pkt(nterminals, payload_nbits = 32,
predicate_nbits = 1)
src_pkts = mk_src_pkts(nterminals, [
# src dst opq vc payload predicate
Pkt(0, 1, 0, 0, 0xfaceb00c, 1),
Pkt(1, 2, 1, 0, 0xdeadbeef, 0),
Pkt(2, 3, 2, 0, 0xbaadface, 1),
Pkt(3, 0, 0, 0, 0xfaceb00c, 0),
])
dst_pkts = ringnet_fl(src_pkts)
th = TestHarness(Pkt, nterminals, src_pkts, dst_pkts)
cmdline_opts={'dump_vcd': False, 'test_verilog': translation,
'dump_vtb': False}
run_sim(th, cmdline_opts)

def test_cgra_data(self):
self._test_cgra_data('zeros')

0 comments on commit 9406bf7

Please sign in to comment.