Skip to content

Commit

Permalink
[feature] Replace en/rdy with val/rdy for ctrl mem and provide test
Browse files Browse the repository at this point in the history
  • Loading branch information
tancheng committed Dec 23, 2024
1 parent 2ea2ecd commit 037d434
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 35 deletions.
2 changes: 2 additions & 0 deletions lib/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ def mk_ring_across_tiles_pkt(nrouters = 4,
CtrlFuInType = mk_bits(clog2(ctrl_fu_inports + 1))
CtrlFuOutType = mk_bits(clog2(ctrl_fu_outports + 1))
CtrlPredicateType = mk_bits(1)
VcIdType = mk_bits(1)

new_name = f"{prefix}_{nrouters}_{opaque_nbits}_{ctrl_actions}_" \
f"{ctrl_mem_size}_{ctrl_operations}_{ctrl_fu_inports}_"\
Expand Down Expand Up @@ -363,6 +364,7 @@ def str_func(s):
field_dict['src'] = IdType
field_dict['dst'] = IdType
field_dict['opaque'] = OpqType
field_dict['vc_id'] = VcIdType
field_dict['ctrl_action'] = CtrlActionType
field_dict['ctrl_addr'] = CtrlAddrType
field_dict['ctrl_operation'] = CtrlOperationType
Expand Down
65 changes: 36 additions & 29 deletions mem/ctrl/CtrlMemDynamicRTL.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
"""

from pymtl3 import *
from pymtl3.stdlib.dstruct.queues import NormalQueue
# from pymtl3.stdlib.dstruct.queues import NormalQueue
from pymtl3.stdlib.primitive import RegisterFile
from ...lib.basic.en_rdy.ifcs import SendIfcRTL, RecvIfcRTL
from ...lib.basic.en_rdy.ifcs import SendIfcRTL
from ...lib.basic.val_rdy.ifcs import ValRdyRecvIfcRTL
from ...lib.basic.val_rdy.queues import NormalQueueRTL
from ...lib.cmd_type import *
from ...lib.opt_type import *

Expand All @@ -37,47 +39,52 @@ def construct(s, CtrlPktType, CtrlSignalType, ctrl_mem_size,

# Interface
s.send_ctrl = SendIfcRTL(CtrlSignalType)
s.recv_pkt = RecvIfcRTL(CtrlPktType)
s.recv_pkt = ValRdyRecvIfcRTL(CtrlPktType)

# Component
s.reg_file = RegisterFile(CtrlSignalType, ctrl_mem_size, 1, 1)
s.recv_pkt_queue = NormalQueue(CtrlPktType)
# FIXME: valrdy normal queue RTL?
s.recv_pkt_queue = NormalQueueRTL(CtrlPktType)
s.times = Wire(TimeType)
s.start_iterate_ctrl = Wire(b1)

# Connections
s.send_ctrl.msg //= s.reg_file.rdata[0]
s.recv_pkt.rdy //= s.recv_pkt_queue.enq_rdy
# s.recv_pkt.rdy //= s.recv_pkt_queue.enq_rdy
s.recv_pkt //= s.recv_pkt_queue.recv

@update
def update_msg():

s.recv_pkt_queue.enq_en @= s.recv_pkt.en & s.recv_pkt_queue.enq_rdy
s.recv_pkt_queue.enq_msg @= CtrlPktType()
# s.recv_pkt_queue.enq_en @= s.recv_pkt.en & s.recv_pkt_queue.enq_rdy
# s.recv_pkt_queue.enq_msg @= CtrlPktType()
s.reg_file.wen[0] @= 0
s.reg_file.wdata[0] @= CtrlSignalType()
if s.recv_pkt.en:
s.recv_pkt_queue.enq_msg @= s.recv_pkt.msg
s.reg_file.waddr[0] @= s.recv_pkt_queue.send.msg.ctrl_addr

if s.recv_pkt_queue.deq_msg.ctrl_action == CMD_CONFIG:
# if s.recv_pkt.en:
# s.recv_pkt_queue.enq_msg @= s.recv_pkt.msg

if s.recv_pkt_queue.send.val & (s.recv_pkt_queue.send.msg.ctrl_action == CMD_CONFIG):
s.reg_file.wen[0] @= 1 # s.recv_pkt_queue.deq_en
s.reg_file.waddr[0] @= s.recv_pkt_queue.deq_msg.ctrl_addr
s.reg_file.waddr[0] @= s.recv_pkt_queue.send.msg.ctrl_addr
# Fills the fields of the control signal.
s.reg_file.wdata[0].ctrl @= s.recv_pkt_queue.deq_msg.ctrl_operation
s.reg_file.wdata[0].predicate @= s.recv_pkt_queue.deq_msg.ctrl_predicate
s.reg_file.wdata[0].ctrl @= s.recv_pkt_queue.send.msg.ctrl_operation
s.reg_file.wdata[0].predicate @= s.recv_pkt_queue.send.msg.ctrl_predicate
for i in range(num_fu_inports):
s.reg_file.wdata[0].fu_in[i] @= s.recv_pkt_queue.deq_msg.ctrl_fu_in[i]
s.reg_file.wdata[0].fu_in[i] @= s.recv_pkt_queue.send.msg.ctrl_fu_in[i]
for i in range(num_routing_outports):
s.reg_file.wdata[0].routing_xbar_outport[i] @= s.recv_pkt_queue.deq_msg.ctrl_routing_xbar_outport[i]
s.reg_file.wdata[0].fu_xbar_outport[i] @= s.recv_pkt_queue.deq_msg.ctrl_fu_xbar_outport[i]
s.reg_file.wdata[0].routing_xbar_outport[i] @= s.recv_pkt_queue.send.msg.ctrl_routing_xbar_outport[i]
s.reg_file.wdata[0].fu_xbar_outport[i] @= s.recv_pkt_queue.send.msg.ctrl_fu_xbar_outport[i]
for i in range(num_tile_inports):
s.reg_file.wdata[0].routing_predicate_in[i] @= s.recv_pkt_queue.deq_msg.ctrl_routing_predicate_in[i]
s.reg_file.wdata[0].routing_predicate_in[i] @= s.recv_pkt_queue.send.msg.ctrl_routing_predicate_in[i]

# @yo96? depending on data, causing combinational loop or not?
if (s.recv_pkt_queue.deq_msg.ctrl_action == CMD_CONFIG) | \
(s.recv_pkt_queue.deq_msg.ctrl_action == CMD_LAUNCH) | \
(s.recv_pkt_queue.deq_msg.ctrl_action == CMD_TERMINATE) | \
(s.recv_pkt_queue.deq_msg.ctrl_action == CMD_PAUSE):
s.recv_pkt_queue.deq_en @= 1
if (s.recv_pkt_queue.send.msg.ctrl_action == CMD_CONFIG) | \
(s.recv_pkt_queue.send.msg.ctrl_action == CMD_LAUNCH) | \
(s.recv_pkt_queue.send.msg.ctrl_action == CMD_TERMINATE) | \
(s.recv_pkt_queue.send.msg.ctrl_action == CMD_PAUSE):
s.recv_pkt_queue.send.rdy @= 1
# TODO: Extend for the other commands. Maybe another queue to
# handle complicated actions.
# else:
Expand All @@ -93,20 +100,20 @@ def update_send_out_signal():
else:
s.send_ctrl.en @= s.send_ctrl.rdy
# @yo96? What would happen if we overwrite? ok?
if s.recv_pkt_queue.deq_rdy & \
((s.recv_pkt_queue.deq_msg.ctrl_action == CMD_PAUSE) | \
(s.recv_pkt_queue.deq_msg.ctrl_action == CMD_TERMINATE)):
if s.recv_pkt_queue.send.val & \
((s.recv_pkt_queue.send.msg.ctrl_action == CMD_PAUSE) | \
(s.recv_pkt_queue.send.msg.ctrl_action == CMD_TERMINATE)):
s.send_ctrl.en @= b1(0)

@update_ff
def update_whether_we_can_iterate_ctrl():
if s.recv_pkt_queue.deq_rdy:
if s.recv_pkt_queue.send.val:
# @yo96? data is still there, not released yet?
if s.recv_pkt_queue.deq_msg.ctrl_action == CMD_LAUNCH:
if s.recv_pkt_queue.send.msg.ctrl_action == CMD_LAUNCH:
s.start_iterate_ctrl <<= 1
elif s.recv_pkt_queue.deq_msg.ctrl_action == CMD_TERMINATE:
elif s.recv_pkt_queue.send.msg.ctrl_action == CMD_TERMINATE:
s.start_iterate_ctrl <<= 0
elif s.recv_pkt_queue.deq_msg.ctrl_action == CMD_PAUSE:
elif s.recv_pkt_queue.send.msg.ctrl_action == CMD_PAUSE:
s.start_iterate_ctrl <<= 0
# else:
# s.start_iterate_ctrl <<= 1
Expand Down
78 changes: 78 additions & 0 deletions mem/ctrl/RingMultiCtrlMemDynamicRTL.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
==========================================================================
RingMultiCtrlMemDynamicRTL.py
==========================================================================
Ring connecting multiple control memories.
Author : Cheng Tan
Date : Dec 22, 2024
"""

from pymtl3 import *
from pymtl3.stdlib.primitive import RegisterFile
from .CtrlMemDynamicRTL import CtrlMemDynamicRTL
from ...lib.basic.en_rdy.ifcs import SendIfcRTL
from ...lib.basic.val_rdy.ifcs import ValRdyRecvIfcRTL
from ...lib.opt_type import *
from ...noc.PyOCN.pymtl3_net.ringnet.RingNetworkRTL import RingNetworkRTL
from ...cgra.CGRAWithCrossbarDataMemRTL import CGRAWithCrossbarDataMemRTL
from ...noc.PyOCN.pymtl3_net.ocnlib.ifcs.positions import mk_ring_pos

class RingMultiCtrlMemDynamicRTL(Component):

def construct(s, CtrlPktType, CtrlSignalType, width, height,
ctrl_mem_size, num_fu_inports, num_fu_outports,
num_tile_inports, num_tile_outports,
ctrl_count_per_iter = 4, total_ctrl_steps = 4):

# Constant
num_terminals = width * height
CtrlRingPos = mk_ring_pos(num_terminals)
s.num_terminals = width * height
# CtrlAddrType = mk_bits(clog2(ctrl_mem_size))
# ControllerIdType = mk_bits(clog2(num_terminals))

# Interface
# # Request from/to CPU.
# s.recv_from_cpu = RecvIfcRTL(CGRADataType)
# s.send_to_cpu = SendIfcRTL(CGRADataType)
# s.recv_waddr = [[RecvIfcRTL(CtrlAddrType) for _ in range(s.num_tiles)]
# for _ in range(s.num_terminals)]
# s.recv_wopt = [[RecvIfcRTL(CtrlType) for _ in range(s.num_tiles)]
# for _ in range(s.num_terminals)]
s.send_ctrl = [SendIfcRTL(CtrlSignalType) for _ in range(s.num_terminals)]
s.recv_pkt_from_controller = ValRdyRecvIfcRTL(CtrlPktType)

# Components
# s.cgra = [CGRAWithCrossbarDataMemRTL(
# CGRADataType, PredicateType, CtrlType, NocPktType, CmdType,
# ControllerIdType, terminal_id, width, height, ctrl_mem_size,
# data_mem_size_global, data_mem_size_per_bank, num_banks_per_cgra,
# num_ctrl, total_steps, FunctionUnit, FuList, controller2addr_map,
# preload_data = None, preload_const = None)
# for terminal_id in range(s.num_terminals)]
s.ctrl_memories = [
CtrlMemDynamicRTL(CtrlPktType, CtrlSignalType, ctrl_mem_size,
num_fu_inports, num_fu_outports, num_tile_inports,
num_tile_outports, ctrl_count_per_iter,
total_ctrl_steps) for terminal_id in range(s.num_terminals)]
s.ctrl_ring = RingNetworkRTL(CtrlPktType, CtrlRingPos, num_terminals, 0)

# Connections
for i in range(s.num_terminals):
s.ctrl_ring.send[i] //= s.ctrl_memories[i].recv_pkt

s.ctrl_ring.recv[0] //= s.recv_pkt_from_controller
for i in range(1, s.num_terminals):
s.ctrl_ring.recv[i].val //= 0
s.ctrl_ring.recv[i].msg //= CtrlPktType()

for i in range(s.num_terminals):
s.ctrl_memories[i].send_ctrl //= s.send_ctrl[i]

def line_trace(s):
res = "||\n".join([(("[ctrl_memory["+str(i)+"]: ") + x.line_trace())
for (i,x) in enumerate(s.ctrl_memories)])
res += " ## ctrl_ring: " + s.ctrl_ring.line_trace()
return res

13 changes: 7 additions & 6 deletions mem/ctrl/test/CtrlMemDynamicRTL_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ....fu.single.AdderRTL import AdderRTL
from ....lib.basic.en_rdy.test_sinks import TestSinkRTL
from ....lib.basic.en_rdy.test_srcs import TestSrcRTL
from ....lib.basic.val_rdy.SourceRTL import SourceRTL as ValRdyTestSrcRTL
from ....lib.messages import *
from ....lib.cmd_type import *
from ....lib.opt_type import *
Expand All @@ -35,7 +36,7 @@ def construct( s, MemUnit, DataType, PredicateType, CtrlPktType,
s.src_data1 = TestSrcRTL(DataType, src1_msgs)
# s.src_waddr = TestSrcRTL(AddrType, ctrl_waddr )
# s.src_wdata = TestSrcRTL(ConfigType, ctrl_msgs )
s.src_pkt = TestSrcRTL(CtrlPktType, ctrl_pkts)
s.src_pkt = ValRdyTestSrcRTL(CtrlPktType, ctrl_pkts)
s.sink_out = TestSinkRTL(DataType, sink_msgs)

s.alu = AdderRTL(DataType, PredicateType, CtrlSignalType, 2, 2,
Expand Down Expand Up @@ -121,11 +122,11 @@ def test_Ctrl():
src_data0 = [DataType(1, 1), DataType(5, 1), DataType(7, 1), DataType(6, 1)]
src_data1 = [DataType(6, 1), DataType(1, 1), DataType(2, 1), DataType(3, 1)]

src_ctrl_pkt = [CtrlPktType(0, 1, 0, CMD_CONFIG, 0, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 1, 0, CMD_CONFIG, 1, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 1, 0, CMD_CONFIG, 2, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 1, 0, CMD_CONFIG, 3, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 1, 0, CMD_LAUNCH, 0, OPT_ADD, b1(0), pickRegister)]
src_ctrl_pkt = [CtrlPktType(0, 1, 0, 0, CMD_CONFIG, 0, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_CONFIG, 1, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_CONFIG, 2, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_CONFIG, 3, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_LAUNCH, 0, OPT_ADD, b1(0), pickRegister)]

sink_out = [DataType(7, 1), DataType(4, 1), DataType(5, 1), DataType(9, 1)]
th = TestHarness(MemUnit, DataType, PredicateType, CtrlPktType, CtrlSignalType,
Expand Down
147 changes: 147 additions & 0 deletions mem/ctrl/test/RingCtrlMemDynamicRTL_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
"""
==========================================================================
CtrlMemDynamicRTL_test.py
==========================================================================
Test cases for control memory with command-based action handling.
Author : Cheng Tan
Date : Dec 21, 2024
"""

from pymtl3 import *
from ..RingMultiCtrlMemDynamicRTL import RingMultiCtrlMemDynamicRTL
from ....fu.single.AdderRTL import AdderRTL
from ....lib.basic.en_rdy.test_sinks import TestSinkRTL
from ....lib.basic.en_rdy.test_srcs import TestSrcRTL
from ....lib.basic.val_rdy.SourceRTL import SourceRTL as ValRdyTestSrcRTL
from ....lib.messages import *
from ....lib.cmd_type import *
from ....lib.opt_type import *

#-------------------------------------------------------------------------
# Test harness
#-------------------------------------------------------------------------

class TestHarness( Component ):

def construct( s, DUT, DataType, PredicateType, CtrlPktType,
CtrlSignalType, ctrl_mem_size, width, height,
data_mem_size, num_fu_inports, num_fu_outports,
num_tile_inports, num_tile_outports, ctrl_pkts,
sink_msgs):

s.width = width
s.height = height
s.src_pkt = ValRdyTestSrcRTL(CtrlPktType, ctrl_pkts)
s.sink_out = [TestSinkRTL(CtrlSignalType, sink_msgs[i])
for i in range(width * height)]

s.dut = \
DUT(CtrlPktType, CtrlSignalType, width, height,
ctrl_mem_size, num_fu_inports, num_fu_outports,
num_tile_inports, num_tile_outports,
len(ctrl_pkts), len(ctrl_pkts))

connect(s.src_pkt.send, s.dut.recv_pkt_from_controller)
for i in range(width * height):
connect(s.dut.send_ctrl[i], s.sink_out[i].recv)

def done(s):
if not s.src_pkt.done():
return False
for i in range(s.width * s.height):
if not s.sink_out[i].done():
return False
return True

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

def run_sim(test_harness, max_cycles = 40):
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()

def test_Ctrl():
MemUnit = RingMultiCtrlMemDynamicRTL
DataType = mk_data(16, 1)
PredicateType = mk_predicate(1, 1)
ctrl_mem_size = 16
ctrl_addr_nbits = clog2(ctrl_mem_size)
data_mem_size = 8
num_fu_inports = 2
num_fu_outports = 2
num_tile_inports = 4
num_tile_outports = 4
width = 2
height = 2
num_terminals = width * height
num_ctrl_actions = 6
ctrl_action_nbits = clog2(num_ctrl_actions)
num_ctrl_operations = 64
CtrlPktType = mk_ring_across_tiles_pkt(num_terminals,
num_ctrl_actions,
ctrl_mem_size,
num_ctrl_operations,
num_fu_inports,
num_fu_outports,
num_tile_inports,
num_tile_outports)
CtrlSignalType = mk_separate_ctrl(num_ctrl_operations,
num_fu_inports,
num_fu_outports,
num_tile_inports,
num_tile_outports)
FuInType = mk_bits(clog2(num_fu_inports + 1))
pickRegister = [FuInType(x + 1) for x in range(num_fu_inports)]

src_ctrl_pkt = [ # src dst vc_id opq cmd_type addr operation predicate
CtrlPktType(0, 0, 0, 0, CMD_CONFIG, 0, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_CONFIG, 1, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 2, 0, 0, CMD_CONFIG, 0, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 3, 0, 0, CMD_CONFIG, 1, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 3, 0, 0, CMD_CONFIG, 0, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 0, 0, 0, CMD_CONFIG, 1, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 0, 0, 0, CMD_LAUNCH, 0, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_CONFIG, 0, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 1, 0, 0, CMD_LAUNCH, 0, OPT_SUB, b1(0), pickRegister),
CtrlPktType(0, 2, 0, 0, CMD_CONFIG, 1, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 2, 0, 0, CMD_LAUNCH, 0, OPT_ADD, b1(0), pickRegister),
CtrlPktType(0, 3, 0, 0, CMD_LAUNCH, 0, OPT_ADD, b1(0), pickRegister)]

sink_out = [
[CtrlSignalType(OPT_ADD, 0, pickRegister),
CtrlSignalType(OPT_SUB, 0, pickRegister)],
# Ctrl memory 1 first write into address 1, then address 0.
[CtrlSignalType(OPT_ADD, 0, pickRegister),
CtrlSignalType(OPT_SUB, 0, pickRegister)],

[CtrlSignalType(OPT_SUB, 0, pickRegister),
CtrlSignalType(OPT_ADD, 0, pickRegister)],

[CtrlSignalType(OPT_SUB, 0, pickRegister),
CtrlSignalType(OPT_ADD, 0, pickRegister)]]
th = TestHarness(MemUnit, DataType, PredicateType, CtrlPktType, CtrlSignalType,
ctrl_mem_size, width, height, data_mem_size, num_fu_inports,
num_fu_outports, num_tile_inports, num_tile_outports,
src_ctrl_pkt, sink_out)
run_sim(th)

0 comments on commit 037d434

Please sign in to comment.