Exemple #1
0
    def construct(s):

        # If translated into Verilog, we use the explicit name

        s.set_metadata(VerilogTranslationPass.explicit_module_name,
                       'SramMinionRTL')

        # Default memory message has 8 bits opaque field and 32 bits address

        MemReqType, MemRespType = mk_mem_msg(8, 32, 32)

        # Interface

        s.minion = stream.ifcs.MinionIfcRTL(MemReqType, MemRespType)
Exemple #2
0
    def construct(s, ProcClass, XcelClass):

        req_class, resp_class = mk_mem_msg(8, 32, 32)

        s.commit_inst = OutPort(Bits1)

        # Instruction Memory Request/Response Interface

        s.proc = ProcClass()
        s.proc.commit_inst //= s.commit_inst

        s.xcel = XcelClass()
        s.xcel.xcel //= s.proc.xcel

        if isinstance(s.proc.imem, MemMasterIfcRTL):  # RTL proc
            s.mngr2proc = RecvIfcRTL(Bits32)
            s.proc2mngr = SendIfcRTL(Bits32)
            s.imem = MemMasterIfcRTL(req_class, resp_class)
            s.dmem = MemMasterIfcRTL(req_class, resp_class)

        elif isinstance(s.proc.imem, MemMasterIfcCL):  # CL proc
            s.mngr2proc = CalleeIfcCL(Type=Bits32)
            s.proc2mngr = CallerIfcCL(Type=Bits32)
            s.imem = MemMasterIfcCL(req_class, resp_class)
            s.dmem = MemMasterIfcCL(req_class, resp_class)

        elif isinstance(s.proc.imem, MemMasterIfcFL):  # FL proc
            s.mngr2proc = GetIfcFL(Type=Bits32)
            s.proc2mngr = SendIfcFL(Type=Bits32)
            s.imem = MemMasterIfcFL()
            s.dmem = MemMasterIfcFL()

        s.mngr2proc //= s.proc.mngr2proc
        s.proc2mngr //= s.proc.proc2mngr
        s.imem //= s.proc.imem
        s.dmem //= s.proc.dmem
Exemple #3
0
  def construct( s ):

    req_class, resp_class = mk_mem_msg( 8, 32, 32 )

    # Proc/Mngr Interface

    s.mngr2proc = RecvIfcRTL( Bits32 )
    s.proc2mngr = SendIfcRTL( Bits32 )

    # Instruction Memory Request/Response Interface

    s.imem = MemMasterIfcRTL( req_class, resp_class )

    # Data Memory Request/Response Interface

    s.dmem = MemMasterIfcRTL( req_class, resp_class )

    # Xcel Request/Response Interface

    xreq_class, xresp_class = mk_xcel_msg( 5, 32 )

    s.xcel = XcelMasterIfcRTL( xreq_class, xresp_class )

    # val_W port used for counting commited insts.

    s.commit_inst = OutPort( Bits1 )

    # Bypass queues

    s.imemreq_q   = BypassQueue2RTL( req_class, 2 )

    # We have to turn input receive interface into get interface

    s.imemresp_q  = BypassQueueRTL( resp_class, 1 )
    s.dmemresp_q  = BypassQueueRTL( resp_class, 1 )
    s.mngr2proc_q = BypassQueueRTL( Bits32, 1 )
    s.xcelresp_q  = BypassQueueRTL( xresp_class, 1 )

    # imem drop unit

    s.imemresp_drop = m = DropUnitRTL( Bits32 )
    m.in_.en  //= s.imemresp_q.deq.en
    m.in_.rdy //= s.imemresp_q.deq.rdy
    m.in_.ret //= s.imemresp_q.deq.ret.data

    # connect all the queues

    s.imemreq_q.deq   //= s.imem.req
    s.imemresp_q.enq  //= s.imem.resp
    s.dmemresp_q.enq  //= s.dmem.resp
    s.mngr2proc_q.enq //= s.mngr2proc
    s.xcelresp_q.enq  //= s.xcel.resp

    # Control

    s.ctrl = m = ProcCtrl()

    # imem port
    m.imemresp_drop //= s.imemresp_drop.drop
    m.imemreq_en    //= s.imemreq_q.enq.en
    m.imemreq_rdy   //= s.imemreq_q.enq.rdy
    m.imemresp_en   //= s.imemresp_drop.out.en
    m.imemresp_rdy  //= s.imemresp_drop.out.rdy

    # dmem port
    m.dmemreq_en    //= s.dmem.req.en
    m.dmemreq_rdy   //= s.dmem.req.rdy
    m.dmemreq_type  //= s.dmem.req.msg.type_
    m.dmemresp_en   //= s.dmemresp_q.deq.en
    m.dmemresp_rdy  //= s.dmemresp_q.deq.rdy

    # xcel port
    m.xcelreq_type  //= s.xcel.req.msg.type_

    m.xcelreq_en    //= s.xcel.req.en
    m.xcelreq_rdy   //= s.xcel.req.rdy
    m.xcelresp_en   //= s.xcelresp_q.deq.en
    m.xcelresp_rdy  //= s.xcelresp_q.deq.rdy

    # proc2mngr and mngr2proc
    m.proc2mngr_en  //= s.proc2mngr.en
    m.proc2mngr_rdy //= s.proc2mngr.rdy
    m.mngr2proc_en  //= s.mngr2proc_q.deq.en
    m.mngr2proc_rdy //= s.mngr2proc_q.deq.rdy

    # commit inst for counting
    m.commit_inst //= s.commit_inst

    # Dpath

    s.dpath = m = ProcDpath()

    # imem ports
    m.imemreq_addr  //= s.imemreq_q.enq.msg.addr
    m.imemresp_data //= s.imemresp_drop.out.ret

    # dmem ports
    m.dmemreq_addr  //= s.dmem.req.msg.addr
    m.dmemreq_data  //= s.dmem.req.msg.data
    m.dmemresp_data //= s.dmemresp_q.deq.ret.data

    # xcel ports
    m.xcelreq_addr  //= s.xcel.req.msg.addr
    m.xcelreq_data  //= s.xcel.req.msg.data
    m.xcelresp_data //= s.xcelresp_q.deq.ret.data

    # mngr
    m.mngr2proc_data //= s.mngr2proc_q.deq.ret
    m.proc2mngr_data //= s.proc2mngr.msg

    # Ctrl <-> Dpath

    s.ctrl.reg_en_F        //= s.dpath.reg_en_F
    s.ctrl.pc_sel_F        //= s.dpath.pc_sel_F

    s.ctrl.reg_en_D        //= s.dpath.reg_en_D
    s.ctrl.op1_byp_sel_D   //= s.dpath.op1_byp_sel_D
    s.ctrl.op2_byp_sel_D   //= s.dpath.op2_byp_sel_D
    s.ctrl.op2_sel_D       //= s.dpath.op2_sel_D
    s.ctrl.imm_type_D      //= s.dpath.imm_type_D

    s.ctrl.reg_en_X        //= s.dpath.reg_en_X
    s.ctrl.alu_fn_X        //= s.dpath.alu_fn_X

    s.ctrl.reg_en_M        //= s.dpath.reg_en_M
    s.ctrl.wb_result_sel_M //= s.dpath.wb_result_sel_M

    s.ctrl.reg_en_W        //= s.dpath.reg_en_W
    s.ctrl.rf_waddr_W      //= s.dpath.rf_waddr_W
    s.ctrl.rf_wen_W        //= s.dpath.rf_wen_W

    s.dpath.inst_D         //= s.ctrl.inst_D
    s.dpath.ne_X           //= s.ctrl.ne_X
    def construct(s):
        s.set_metadata(VerilogTranslationPass.explicit_module_name,
                       "SramMinionRTL")

        # size is fixed as 32x128

        num_bits = 32
        num_words = 128
        addr_width = clog2(num_words)
        addr_start = clog2(num_bits / 8)
        addr_end = addr_start + addr_width

        BitsAddr = mk_bits(addr_width)
        BitsData = mk_bits(num_bits)

        # Default memory message has 8 bits opaque field and 32 bits address.

        MemReqType, MemRespType = mk_mem_msg(8, 32, num_bits)

        # Interface

        s.minion = stream.ifcs.MinionIfcRTL(MemReqType, MemRespType)

        #---------------------------------------------------------------------
        # M0 stage
        #---------------------------------------------------------------------

        s.sram_addr_M0 = Wire(BitsAddr)
        s.sram_wen_M0 = Wire(Bits1)
        s.sram_en_M0 = Wire(Bits1)
        s.sram_wdata_M0 = Wire(BitsData)

        # translation work around
        MEM_MSG_TYPE_WRITE = b4(MemMsgType.WRITE)

        @update
        def comb_M0():
            s.sram_addr_M0 @= s.minion.req.msg.addr[addr_start:addr_end]
            s.sram_wen_M0 @= s.minion.req.val & (s.minion.req.msg.type_
                                                 == MEM_MSG_TYPE_WRITE)
            s.sram_en_M0 @= s.minion.req.val & s.minion.req.rdy
            s.sram_wdata_M0 @= s.minion.req.msg.data

        # SRAM

        s.sram = m = SramRTL(num_bits, num_words)
        m.port0_idx //= s.sram_addr_M0
        m.port0_type //= s.sram_wen_M0
        m.port0_val //= s.sram_en_M0
        m.port0_wdata //= s.sram_wdata_M0

        #---------------------------------------------------------------------
        # M1 stage
        #---------------------------------------------------------------------

        # Pipeline registers

        s.memreq_val_reg_M1 = m = RegRst(Bits1)
        m.in_ //= s.sram_en_M0

        s.memreq_msg_reg_M1 = m = Reg(MemReqType)
        m.in_ //= s.minion.req.msg

        # Create the memory response message with data from SRAM if read

        s.memresp_msg_M1 = Wire(MemRespType)

        # translation work around
        MEM_MSG_TYPE_READ = b4(MemMsgType.READ)

        @update
        def comb_M1a():

            s.memresp_msg_M1.type_ @= s.memreq_msg_reg_M1.out.type_
            s.memresp_msg_M1.opaque @= s.memreq_msg_reg_M1.out.opaque
            s.memresp_msg_M1.test @= 0
            s.memresp_msg_M1.len @= s.memreq_msg_reg_M1.out.len

            if s.memreq_msg_reg_M1.out.type_ == MEM_MSG_TYPE_READ:
                s.memresp_msg_M1.data @= s.sram.port0_rdata
            else:
                s.memresp_msg_M1.data @= 0

        # Bypass queue

        s.memresp_q = stream.BypassQueueRTL(MemRespType, num_entries=2)

        @update
        def comb_M1b():

            # enqueue messages into the bypass queue

            s.memresp_q.recv.val @= s.memreq_val_reg_M1.out
            s.memresp_q.recv.msg @= s.memresp_msg_M1

            # dequeue messages from the bypass queue
            s.minion.resp.val @= s.memresp_q.send.val
            s.memresp_q.send.rdy @= s.minion.resp.rdy
            s.minion.resp.msg @= s.memresp_q.send.msg

            # stop the minion interface if not enough skid buffering

            s.minion.req.rdy @= s.memresp_q.count == 0
Exemple #5
0
  Date : Apr 20, 2020
'''
import pytest
from pymtl3 import *
from pymtl3.stdlib.mem import mk_mem_msg, MemMsgType, MagicMemoryCL as MemoryCL
from pymtl3.stdlib.test_utils.test_srcs import TestSrcCL as TestSource
from pymtl3.stdlib.test_utils.test_sinks import TestSinkCL as TestSink
from pymtl3.stdlib.test_utils import run_sim, mk_test_case_table

from ..MasterMinionXbarGeneric import MasterMinionXbarGeneric as Xbar

#-------------------------------------------------------------------------
# constants
#-------------------------------------------------------------------------

Req, Resp = mk_mem_msg(8, 32, 32)
rd = MemMsgType.READ
wr = MemMsgType.WRITE

hexwords = [
    0x8badf00d,
    0xdeadbeef,
    0xfeedbabe,
    0xdeadc0de,
    0xc001d00d,
    0xdeadfa11,
    0xfaceb00c,
    0xc001cafe,
    0xdeafbabe,
    0x8badcafe,
]
#=========================================================================

from __future__ import print_function

import pytest
import random

from pymtl3 import *
from pymtl3.stdlib import stream
from pymtl3.stdlib.test_utils import mk_test_case_table, run_sim, config_model_with_cmdline_opts
from pymtl3.stdlib.test_utils import TestSrcCL, TestSinkCL
from pymtl3.stdlib.mem import mk_mem_msg, MemMsgType

from tut8_sram.SramMinionRTL import SramMinionRTL

MemReqType, MemRespType = mk_mem_msg(8, 32, 32)

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


class TestHarness(Component):
    def construct(s, dut):

        # Instantiate models

        s.src = stream.SourceRTL(MemReqType)
        s.sram = dut
        s.sink = stream.SinkRTL(MemRespType)
Exemple #7
0
  def construct( s ):

    memreq_cls, memresp_cls = mk_mem_msg( 8,32,32 )
    xreq_class, xresp_class = mk_xcel_msg(5,32)

    # Interface

    s.commit_inst = OutPort( Bits1 )

    s.imem = MemMasterIfcCL( memreq_cls, memresp_cls )
    s.dmem = MemMasterIfcCL( memreq_cls, memresp_cls )

    s.xcel = XcelMasterIfcCL( xreq_class, xresp_class )

    s.proc2mngr = CallerIfcCL()
    s.mngr2proc = CalleeIfcCL()

    # Buffers to hold input messages

    s.imemresp_q  = DelayPipeDeqCL(0)
    s.imemresp_q.enq //= s.imem.resp

    s.dmemresp_q  = DelayPipeDeqCL(1)
    s.dmemresp_q.enq //= s.dmem.resp

    s.mngr2proc_q = DelayPipeDeqCL(1)
    s.mngr2proc_q.enq //= s.mngr2proc

    s.xcelresp_q  = DelayPipeDeqCL(0)
    s.xcelresp_q.enq //= s.xcel.resp

    s.pc = b32( 0x200 )
    s.R  = RegisterFile( 32 )

    s.F_DXM_queue = PipeQueueCL(1)
    s.DXM_W_queue = PipeQueueCL(1)

    s.F_status   = PipelineStatus.idle
    s.DXM_status = PipelineStatus.idle
    s.W_status   = PipelineStatus.idle

    @update_once
    def F():
      s.F_status = PipelineStatus.idle

      if s.reset:
        s.pc = b32( 0x200 )
        return

      if s.imem.req.rdy() and s.F_DXM_queue.enq.rdy():
        if s.redirected_pc_DXM >= 0:
          s.imem.req( memreq_cls( MemMsgType.READ, 0, s.redirected_pc_DXM ) )
          s.pc = s.redirected_pc_DXM
        else:
          s.imem.req( memreq_cls( MemMsgType.READ, 0, s.pc ) )

        s.F_DXM_queue.enq( s.pc )
        s.F_status = PipelineStatus.work
        s.pc += 4
      else:
        s.F_status = PipelineStatus.stall

    s.redirected_pc_DXM = -1

    s.raw_inst = b32(0)

    @update_once
    def DXM():
      s.redirected_pc_DXM = -1
      s.DXM_status = PipelineStatus.idle

      if s.F_DXM_queue.deq.rdy() and s.imemresp_q.deq.rdy():

        if not s.DXM_W_queue.enq.rdy():
          s.DXM_status = PipelineStatus.stall
        else:
          pc = s.F_DXM_queue.peek()

          s.raw_inst = s.imemresp_q.peek().data
          inst       = TinyRV0Inst( s.raw_inst )
          inst_name  = inst.name

          s.DXM_status = PipelineStatus.work

          if inst_name == "nop":
            pass
          elif inst_name == "add":
            s.DXM_W_queue.enq( (inst.rd, s.R[ inst.rs1 ] + s.R[ inst.rs2 ], DXM_W.arith) )
          elif inst_name == "sll":
            s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] << (s.R[inst.rs2] & 0x1F), DXM_W.arith) )
          elif inst_name == "srl":
            s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] >> (s.R[inst.rs2].uint() & 0x1F), DXM_W.arith) )

          # ''' TUTORIAL TASK ''''''''''''''''''''''''''''''''''''''''''''
          # Implement instruction AND in CL processor
          # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\/
          #; Make an "elif" statement here to implement instruction AND
          #; that applies bit-wise "and" operator to rs1 and rs2 and
          #; pass the result to the pipeline.

          elif inst_name == "and":
            s.DXM_W_queue.enq( (inst.rd, s.R[inst.rs1] & s.R[inst.rs2], DXM_W.arith) )

          # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''/\

          elif inst_name == "addi":
            s.DXM_W_queue.enq( (inst.rd, s.R[ inst.rs1 ] + sext(inst.i_imm, 32), DXM_W.arith) )
          elif inst_name == "sw":
            if s.dmem.req.rdy():
              s.dmem.req( memreq_cls( MemMsgType.WRITE, 0,
                                      s.R[ inst.rs1 ] + sext(inst.s_imm, 32),
                                      0,
                                      s.R[ inst.rs2 ] ) )
              s.DXM_W_queue.enq( (0, 0, DXM_W.mem) )
            else:
              s.DXM_status = PipelineStatus.stall

          elif inst_name == "lw":
            if s.dmem.req.rdy():
              s.dmem.req( memreq_cls( MemMsgType.READ, 0,
                                      s.R[ inst.rs1 ] + sext(inst.i_imm, 32),
                                      0 ) )
              s.DXM_W_queue.enq( (inst.rd, 0, DXM_W.mem) )
            else:
              s.DXM_status = PipelineStatus.stall

          elif inst_name == "bne":
            if s.R[ inst.rs1 ] != s.R[ inst.rs2 ]:
              s.redirected_pc_DXM = pc + sext(inst.b_imm, 32)
            s.DXM_W_queue.enq( None )

          elif inst_name == "csrw":
            if inst.csrnum == 0x7C0: # CSR: proc2mngr
              # We execute csrw in W stage
              s.DXM_W_queue.enq( (0, s.R[ inst.rs1 ], DXM_W.mngr) )

            elif 0x7E0 <= inst.csrnum <= 0x7FF:
              if s.xcel.req.rdy():
                s.xcel.req( xreq_class( XcelMsgType.WRITE, inst.csrnum[0:5], s.R[inst.rs1]) )
                s.DXM_W_queue.enq( (0, 0, DXM_W.xcel) )
              else:
                s.DXM_status = PipelineStatus.stall
          elif inst_name == "csrr":
            if inst.csrnum == 0xFC0: # CSR: mngr2proc
              if s.mngr2proc_q.deq.rdy():
                s.DXM_W_queue.enq( (inst.rd, s.mngr2proc_q.deq(), DXM_W.arith) )
              else:
                s.DXM_status = PipelineStatus.stall
            elif 0x7E0 <= inst.csrnum <= 0x7FF:
              if s.xcel.req.rdy():
                s.xcel.req( xreq_class( XcelMsgType.READ, inst.csrnum[0:5], s.R[inst.rs1]) )
                s.DXM_W_queue.enq( (inst.rd, 0, DXM_W.xcel) )
              else:
                s.DXM_status = PipelineStatus.stall

          # If we execute any instruction, we pop from queues
          if s.DXM_status == PipelineStatus.work:
            s.F_DXM_queue.deq()
            s.imemresp_q.deq()

    s.rd = b5(0)

    @update_once
    def W():
      s.commit_inst @= 0
      s.W_status = PipelineStatus.idle

      if s.DXM_W_queue.deq.rdy():
        entry = s.DXM_W_queue.peek()
        if entry is not None:
          rd, data, entry_type = entry
          s.rd = rd

          if entry_type == DXM_W.mem:
            if s.dmemresp_q.deq.rdy():
              if rd > 0: # load
                s.R[ rd ] = Bits32( s.dmemresp_q.deq().data )
              else: # store
                s.dmemresp_q.deq()

              s.W_status = PipelineStatus.work

            else:
              s.W_status = PipelineStatus.stall

          elif entry_type == DXM_W.xcel:
            if s.xcelresp_q.deq.rdy():
              if rd > 0: # csrr
                s.R[ rd ] = Bits32( s.xcelresp_q.deq().data )
              else: # csrw
                s.xcelresp_q.deq()

              s.W_status = PipelineStatus.work
            else:
              s.W_status = PipelineStatus.stall

          elif entry_type == DXM_W.mngr:
            if s.proc2mngr.rdy():
              s.proc2mngr( data )
              s.W_status = PipelineStatus.work
            else:
              s.W_status = PipelineStatus.stall

          else: # other WB insts
            assert entry_type == DXM_W.arith
            if rd > 0: s.R[ rd ] = Bits32( data )
            s.W_status = PipelineStatus.work

        else: # non-WB insts
          s.W_status = PipelineStatus.work

      if s.W_status == PipelineStatus.work:
        s.DXM_W_queue.deq()
        s.commit_inst @= 1