Skip to content

Commit

Permalink
[feature] Simple controller
Browse files Browse the repository at this point in the history
  • Loading branch information
tancheng committed Dec 3, 2024
1 parent f016a96 commit f0ee5ea
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 0 deletions.
94 changes: 94 additions & 0 deletions controller/ControllerRTL.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
==========================================================================
ControllerRTL.py
==========================================================================
Simple controller for CGRA.
Author : Cheng Tan
Date : Dec 2, 2024
"""


from pymtl3 import *
from pymtl3.stdlib.primitive import RegisterFile
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.opt_type import *


class ControllerRTL(Component):

def construct(s, RingPktType, CGRADataType, CGRAAddrType):

# # Constant

# AddrType = mk_bits( clog2( data_mem_size ) )

# Interface

# # Read/write Data from local CGRA data memory.
# s.recv_raddr_from_local = RecvIfcRTL(AddrType)
# s.send_rdata_from_local = SendIfcRTL(DataType)
# s.recv_waddr_from_local = RecvIfcRTL(AddrType)
# s.recv_wdata_from_local = RecvIfcRTL(DataType)

# # Read/write Data to local CGRA data memory.
# s.recv_raddr_to_local = RecvIfcRTL(CGRAAddrType)
# s.send_rdata_to_local = SendIfcRTL(CGRADataType)
# s.recv_waddr_to_local = RecvIfcRTL(CGRAAddrType)
# s.recv_wdata_to_local = RecvIfcRTL(CGRADataType)

# Request from other CGRA.
s.recv_from_other = ValRdyRecvIfcRTL(RingPktType)
s.send_to_other = ValRdySendIfcRTL(RingPktType)

# Request from master.
s.recv_from_master = RecvIfcRTL(CGRADataType)
s.send_to_master = SendIfcRTL(CGRADataType)


# # TODO: below ifcs should be connected through another NoC within
# # one CGRA, instead of per-tile and performing like a bus.
# # Configuration signals to be written into and read from per-tile
# # control memory.
# s.recv_waddr = [RecvIfcRTL(AddrType) for _ in range(s.num_tiles)]
# s.recv_wopt = [RecvIfcRTL(CtrlType) for _ in range(s.num_tiles)]

# s.send_waddr = [SendIfcRTL(AddrType) for _ in range(s.num_tiles)]
# s.send_wopt = [SendIfcRTL(CtrlType) for _ in range(s.num_tiles)]

# # Cmd to invoke/terminate tiles execution.
# s.recv_cmd = [RecvIfcRTL(b2) for _ in range(s.num_tiles)]
# s.send_cmd = [SendIfcRTL(b2) for _ in range(s.num_tiles)]


s.pkt2data = Wire(CGRADataType)
s.data2pkt = Wire(RingPktType)

@update
def update_data():
s.pkt2data.payload @= s.recv_from_other.msg.payload
s.data2pkt.payload @= s.recv_from_master.msg.payload


# Can also be @update instead of @update_ff
# @update
@update_ff
def update_controller():
s.recv_from_other.rdy <<= s.send_to_master.rdy
s.send_to_master.en <<= s.recv_from_other.val & s.send_to_master.rdy
s.send_to_master.msg <<= s.pkt2data

s.recv_from_master.rdy <<= s.send_to_other.rdy
s.send_to_other.val <<= s.recv_from_master.en
s.send_to_other.msg <<= s.data2pkt


def line_trace(s):
recv_from_master_str = "recv_from_master: " + str(s.recv_from_master.msg)
send_to_master_str = "send_to_master: " + str(s.send_to_master.msg)
recv_from_other_str = "recv_from_other: " + str(s.recv_from_other.msg)
send_to_other_str = "send_to_other: " + str(s.send_to_other.msg)
return f'{recv_from_master_str} || {send_to_master_str} || {recv_from_other_str} || {send_to_other_str}'

Empty file added controller/__init__.py
Empty file.
127 changes: 127 additions & 0 deletions controller/test/ControllerRTL_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
'''
=========================================================================
ChannelRTL_test.py
=========================================================================
Simple test for Channel.
Author : Cheng Tan
Date : Dec 2, 2024
'''


from pymtl3 import *
from pymtl3.stdlib.test_utils import TestVectorSimulator
from ..ControllerRTL import ControllerRTL
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 TestValRdySrcRTL
from ...lib.basic.val_rdy.ifcs import SendIfcRTL as ValRdySendIfcRTL
from ...lib.basic.val_rdy.ifcs import RecvIfcRTL as ValRdyRecvIfcRTL
from ...lib.messages import *
from ...noc.PyOCN.pymtl3_net.ocnlib.test.stream_sinks import NetSinkRTL as TestNetSinkRTL
import pytest


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

class TestHarness(Component):

def construct(s, MsgType, PktType, AddrType, src_msgs, sink_msgs, src_pkts, sink_pkts):

cmp_fn = lambda a, b : a.payload == b.payload
s.src_en_rdy = TestSrcRTL(MsgType, src_msgs)
s.sink_en_rdy = TestSinkRTL(MsgType, sink_msgs)
s.src_val_rdy = TestValRdySrcRTL(PktType, src_pkts)
s.sink_val_rdy = TestNetSinkRTL(PktType, sink_pkts, cmp_fn = cmp_fn)

s.dut = ControllerRTL(PktType, MsgType, AddrType)

# Connections
s.src_en_rdy.send //= s.dut.recv_from_master
s.dut.send_to_master //= s.sink_en_rdy.recv
s.src_val_rdy.send //= s.dut.recv_from_other
s.dut.send_to_other //= s.sink_val_rdy.recv

def done(s):
return s.src_en_rdy.done() and s.sink_en_rdy.done() and \
s.src_val_rdy.done() and s.sink_val_rdy.done()

def line_trace( s ):
return s.dut.line_trace()
# return s.src.line_trace() + "-> | " + s.dut.line_trace()
# return s.src.line_trace() + "-> | " + s.dut.line_trace() + \
# " | -> " + s.sink.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
#-------------------------------------------------------------------------

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

DataType = mk_data(32, 1)
test_msgs = [DataType(7, 1, 1), DataType(2, 1), DataType(3, 1)]
sink_msgs = [DataType(0xdeadbeef, 0), DataType(0xbeefdead, 0), DataType(0xdeedbeed, 0)]

nterminals = 4
Pkt = mk_ring_multi_cgra_pkt(nterminals, payload_nbits = 32,
predicate_nbits = 1)
src_pkts = [
# src dst opq vc payload predicate
Pkt(0, 0, 0, 0, 0xdeadbeef, 0),
Pkt(0, 0, 0, 0, 0xbeefdead, 0),
Pkt(0, 0, 0, 0, 0xdeedbeed, 0),
]

sink_pkts = [
# src dst opq vc payload predicate
Pkt(0, 0, 0, 0, 7, 0),
Pkt(0, 0, 0, 0, 2, 0),
Pkt(0, 0, 0, 0, 3, 0),
]

ctrl_mem_size = 4
AddrType = mk_bits(clog2(ctrl_mem_size))

def test_simple():
th = TestHarness(DataType, Pkt, AddrType, test_msgs, sink_msgs, src_pkts, sink_pkts)
run_sim(th)

Empty file added controller/test/__init__.py
Empty file.

0 comments on commit f0ee5ea

Please sign in to comment.