示例#1
0
class UARTCommReader(BusDriver):

    _signals = ["rd_data", "rd_stb"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.read_data_busy = Lock("%s_wbusy" % name)
        self.data = Array('B')

    @cocotb.coroutine
    def read(self, size):
        yield self.read_data_busy.acquire()
        self.data = Array('B')
        count = 0
        while count < size:
            yield ReadOnly()
            yield RisingEdge(self.clock)
            if self.bus.rd_stb.value == 1:
                self.data.append(self.bus.rd_data.value)
                count += 1

        yield RisingEdge(self.clock)
        self.read_data_busy.release()

    def get_data(self):
        return self.data
示例#2
0
class UARTCommWriter(BusDriver):

    _signals = ["wr_stb", "wr_data", "wr_busy"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.wr_stb     <=  0
        self.bus.wr_data    <=  0
        self.write_data_busy = Lock("%s_wbusy" % name)


    @cocotb.coroutine
    def write(self, data):
        yield self.write_data_busy.acquire()
        i = 0
        while i < len(data):
            yield ReadOnly()
            yield RisingEdge(self.clock)
            if not (self.bus.wr_busy.value):
                if i == len(data):
                    break
                self.bus.wr_data    <=  data[i]
                self.bus.wr_stb     <=  1
                i = i + 1

            yield RisingEdge(self.clock)
            self.bus.wr_stb     <=  0

        self.write_data_busy.release()
示例#3
0
class semaphore():
    def __init__(self, count=1):
        self.max_count = count
        self.count = count
        self.lock = Lock("sem_lock")
        self.locked = False

    async def get(self, count=1):
        if self.count > count:
            self.count -= count
            await Timer(0, "NS")
        elif count > self.max_count:
            raise Exception("Tried to get {} > max count {}".format(
                count, self.max_count))
        else:
            await self.lock.acquire()
            self.locked = True
            self.count -= count

    def put(self, count=1):
        if self.count < self.max_count:
            self.count += count
            if self.locked is True:
                self.locked = False
                self.lock.release()

    def try_get(self, count=1):
        if self.count >= count:
            self.count -= count
            return True
        return False
示例#4
0
class VideoOutBus(BusDriver):
    """
    Generate RGB Video Signals
    """

    _signals = ["RGB", "HSYNC", "VSYNC", "DATA_EN", "HBLANK", "VBLANK"]

    def __init__(self, entity, name, clock, width, height, hblank, vblank):
        BusDriver.__init__(self, entity, name, clock)

        #Drive some sensible defaults
        self.bus.RGB.setimmediatevalue(0)
        self.bus.HSYNC.setimmediatevalue(0)
        self.bus.VSYNC.setimmediatevalue(0)
        self.bus.DATA_EN.setimmediatevalue(0)

        self.bus.HBLANK.setimmediatevalue(1)
        self.bus.VBLANK.setimmediatevalue(1)

        self.width = width
        self.height = height
        self.hblank = hblank
        self.vblank = vblank

        self.write_lock = Lock("%s_busy" % name)

    @cocotb.coroutine
    def write(self, video):
        #print "Video: %s" % video
        yield self.write_lock.acquire()
        yield RisingEdge(self.clock)
        self.bus.DATA_EN <= 1
        for frame in video:
            for line in frame:
                for pixel in line:
                    self.bus.HBLANK <= 0
                    self.bus.VBLANK <= 0
                    self.bus.HSYNC <= 1
                    self.bus.VSYNC <= 1

                    self.bus.RGB <= pixel
                    yield RisingEdge(self.clock)

                #Horizontal Blank
                self.bus.HSYNC <= 0
                self.bus.HBLANK <= 1
                for i in range(self.hblank):
                    yield RisingEdge(self.clock)

                self.bus.VSYNC <= 0
                self.bus.VBLANK <= 1

            #Vertical Blank
            for i in range(self.vblank):
                yield RisingEdge(self.clock)

        self.bus.DATA_EN <= 0
        self.write_lock.release()
示例#5
0
class GlobalBuffer(BusDriver):
    _signals = ["rd_addr", "rd_data", "rd_en", "wr_addr", "wr_data", "wr_strb"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)

        # Drive some sensible defaults (setimmediatevalue to avoid x asserts)
        self.bus.rd_en.setimmediatevalue(0)
        self.bus.wr_strb.setimmediatevalue(0)

        # Mutex for each channel that we master to prevent contention
        self.write_busy = Lock("%s_wbusy" % name)
        self.read_busy = Lock("%s_rbusy" % name)

    @cocotb.coroutine
    def write(self, address, data, byte_enable=0b11111111, sync=True):
        """Write a value to an address.
        """
        if sync:
            yield RisingEdge(self.clock)

        yield self.write_busy.acquire()

        self.bus.wr_addr <= address
        self.bus.wr_data <= data
        self.bus.wr_strb <= byte_enable

        yield RisingEdge(self.clock)

        self.bus.wr_strb <= 0
        self.write_busy.release()

    @cocotb.coroutine
    def read(self, address, sync=True):
        """Read from an address.
        Returns:
            BinaryValue: The read data value.
        """
        if sync:
            yield RisingEdge(self.clock)

        yield self.read_busy.acquire()

        self.bus.rd_addr <= address
        self.bus.rd_en <= 1

        yield RisingEdge(self.clock)

        self.bus.rd_en <= 0
        self.read_busy.release()

        # 2 cycle read latency
        yield RisingEdge(self.clock)

        yield ReadOnly()
        data = self.bus.rd_data

        raise ReturnValue(data)
class BlockFIFOReadPath(BusDriver):
    _signals = ["RDY", "ACT", "STB", "SIZE", "DATA"]
    _optional_signals = ["INACTIVE"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.ACT.setimmediatevalue(0)
        self.bus.STB.setimmediatevalue(0)
        self.busy = Lock("%s_busy" % name)

    @cocotb.coroutine
    def read(self, size=None):
        """
        If set to None just keep reading
        """
        fifo_size = 0
        data = []
        yield self.busy.acquire()
        pos = 0
        while (size is None) or (pos < size):
            print "Within read loop: Pos: %d" % pos
            yield ReadOnly()
            #while True:
            while self.bus.ACT == 0:
                if self.bus.RDY == 1:
                    yield RisingEdge(self.clock)
                    self.bus.ACT    <=  1
                yield RisingEdge(self.clock)
                yield ReadOnly()

            print "Got act!"
            yield RisingEdge(self.clock)
            count = 0
            yield ReadOnly()
            fifo_size = int(self.bus.SIZE)
            #print "FIFO Size: %d" % fifo_size
            while count < fifo_size:
                #print "Count: %d" % count
                yield RisingEdge(self.clock)
                self.bus.STB    <=  1
                yield ReadOnly()
                if size is not None:
                    d = int(self.bus.DATA)
                    #print "Data: %08X" % d
                    data.append(d)
                count   += 1
                pos     += 1
            yield RisingEdge(self.clock)
            self.bus.STB    <=  0
            self.bus.ACT    <=  0
            yield RisingEdge(self.clock)

        self.busy.release()

        raise ReturnValue(data)
class BlockFIFOReadPath(BusDriver):
    _signals = ["RDY", "ACT", "STB", "SIZE", "DATA"]
    _optional_signals = ["INACTIVE"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.ACT.setimmediatevalue(0)
        self.bus.STB.setimmediatevalue(0)
        self.busy = Lock("%s_busy" % name)

    @cocotb.coroutine
    def read(self, size=None):
        """
        If set to None just keep reading
        """
        fifo_size = 0
        data = []
        yield self.busy.acquire()
        pos = 0
        while (size is None) or (pos < size):
            print "Within read loop: Pos: %d" % pos
            yield ReadOnly()
            #while True:
            while self.bus.ACT == 0:
                if self.bus.RDY == 1:
                    yield RisingEdge(self.clock)
                    self.bus.ACT <= 1
                yield RisingEdge(self.clock)
                yield ReadOnly()

            print "Got act!"
            yield RisingEdge(self.clock)
            count = 0
            yield ReadOnly()
            fifo_size = int(self.bus.SIZE)
            #print "FIFO Size: %d" % fifo_size
            while count < fifo_size:
                #print "Count: %d" % count
                yield RisingEdge(self.clock)
                self.bus.STB <= 1
                yield ReadOnly()
                if size is not None:
                    d = int(self.bus.DATA)
                    #print "Data: %08X" % d
                    data.append(d)
                count += 1
                pos += 1
            yield RisingEdge(self.clock)
            self.bus.STB <= 0
            self.bus.ACT <= 0
            yield RisingEdge(self.clock)

        self.busy.release()

        raise ReturnValue(data)
示例#8
0
class AXI4StreamSlave(BusDriver):

    _signals = ["tvalid", "tready", "tdata"]
    _optional_signals = ["tlast", "tkeep", "tstrb", "tid", "tdest", "tuser"]

    def __init__(self, entity, name, clock, width = 32):
        BusDriver.__init__(self, entity, name, clock)
        self.width = width
        self.bus.tready <= 0;
        self.read_data_busy = Lock("%s_wbusy" % name)
        self.data = []

    @cocotb.coroutine
    def read(self, wait_for_valid=True):
        """Read a packe of data from the Axi Ingress stream"""
        yield self.read_data_busy.acquire()
        try:
            # clear the data register and signal we're ready to receive some data
            self.data = []
            self.bus.tready <=  1

            if wait_for_valid:
                while not self.bus.tvalid.value:
                    yield RisingEdge(self.clock)

                # while self.bus.tvalid.value and self.bus.tready.value:
                while True:

                    if self.bus.tvalid.value and self.bus.tready.value:
                        self.data.append(self.bus.tdata.value.integer)

                        if self.bus.tlast.value:
                            self.bus.tready <= 0
                            break
                    
                    yield RisingEdge(self.clock)
                
                
            else:
                self.bus.tready <= 1

                while not self.bus.tlast.value:
                    
                    if self.bus.tvalid.value and self.bus.tready.value:
                        self.data.append(self.bus.tdata.value.integer)
                    
                    yield RisingEdge(self.clock)

                self.bus.tready <= 0
        
        finally:
            self.read_data_busy.release()
                
示例#9
0
class PPFIFOWritePath(BusDriver):
    _signals = ["RDY", "ACT", "STB", "SIZE", "DATA"]
    _optional_signals = ["STARVED"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.ACT.setimmediatevalue(0)
        self.bus.DATA.setimmediatevalue(0)
        self.bus.STB.setimmediatevalue(0)
        self.busy = Lock("%s_busy" % name)

    @cocotb.coroutine
    def write(self, data):
        yield self.busy.acquire()
        pos = 0
        count = 0
        total_length = len(data)
        rdy = 0

        while pos < total_length:
            while True:
                yield ReadOnly()
                rdy = int(self.bus.RDY)
                if rdy != 0:
                    yield RisingEdge(self.clock)
                    break
                yield RisingEdge(self.clock)

            if (rdy & 0x01) > 0:
                self.bus.ACT <= 0x01
            else:
                self.bus.ACT <= 0x02

            yield RisingEdge(self.clock)
            length = total_length
            if length > int(self.bus.SIZE):
                length = self.bus.SIZE

            print "Length: %d" % length

            for d in data[pos:length]:
                self.bus.STB <= 1
                self.bus.DATA <= d
                yield RisingEdge(self.clock)

            self.bus.STB <= 0
            pos += length
            yield RisingEdge(self.clock)
            self.bus.ACT <= 0
            yield RisingEdge(self.clock)

        self.busy.release()
示例#10
0
class PSBus(BusDriver):
    """
    Small subset of Zynq registers, used to access SAXI_HP* registers
    """
    _signals=[ # i/o from the DUT side
        "clk",    # output    
        "addr",   # input [31:0]
        "wr",     # input
        "rd",     # input
        "din",    # input [31:0]
        "dout"]   #output [31:0]
    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.busy_channel = Lock("%s_busy"%(name))
        self.bus.wr.setimmediatevalue(0)
        self.bus.rd.setimmediatevalue(0)
        _float_signals((self.bus.addr, self.bus.din))
        self.name = name

    @cocotb.coroutine
    def write_reg(self,addr,data):
        yield self.busy_channel.acquire()
        #Only wait if it is too late (<1/2 cycle)
        if not int(self.clock):
            yield RisingEdge(self.clock)
        self.bus.addr <= addr
        self.bus.din <= data
        self.bus.wr <= 1
        yield RisingEdge(self.clock)
        self.bus.wr <= 0
        _float_signals((self.bus.addr, self.bus.din))
        self.busy_channel.release()

    @cocotb.coroutine
    def read_reg(self,addr):
        yield self.busy_channel.acquire()
        #Only wait if it is too late (<1/2 cycle)
        if not int(self.clock):
            yield RisingEdge(self.clock)
        self.bus.addr <= addr
        self.bus.rd <= 1
        yield RisingEdge(self.clock)
        try:
            data = self.bus.dout.value.integer
        except:
            bv = self.bus.dout.value
            bv.binstr = re.sub("[^1]","0",bv.binstr)
            data = bv.integer
        self.bus.rd <= 0
        _float_signals((self.bus.addr, ))
        self.busy_channel.release()
        raise ReturnValue(data)
示例#11
0
class PPFIFOWritePath(BusDriver):
    _signals = ["RDY", "ACT", "STB", "SIZE", "DATA"]
    _optional_signals = ["STARVED"]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.ACT.setimmediatevalue(0)
        self.bus.DATA.setimmediatevalue(0)
        self.bus.STB.setimmediatevalue(0)
        self.busy = Lock("%s_busy" % name)

    @cocotb.coroutine
    def write(self, data):
        yield self.busy.acquire()
        pos = 0
        count = 0
        total_length = len(data)
        rdy = 0

        while pos < total_length:
            while True:
                yield ReadOnly()
                rdy = int(self.bus.RDY)
                if rdy != 0:
                    yield RisingEdge(self.clock)
                    break
                yield RisingEdge(self.clock)

            if (rdy & 0x01) > 0:
                self.bus.ACT <= 0x01
            else:
                self.bus.ACT <= 0x02

            yield RisingEdge(self.clock)
            length  = total_length
            if length > int(self.bus.SIZE):
                length = self.bus.SIZE

            print "Length: %d" % length

            for d in data[pos:length]:
                self.bus.STB    <=  1
                self.bus.DATA   <=  d
                yield RisingEdge(self.clock)

            self.bus.STB        <=  0
            pos += length
            yield RisingEdge(self.clock)
            self.bus.ACT        <=  0
            yield RisingEdge(self.clock)

        self.busy.release()
示例#12
0
class NESPPU(BusDriver):
    _signals = [
        "X_OUT", "Y_OUT", "Y_NEXT_OUT", "PULSE_OUT", "VBLANK", "SYS_PALETTE"
    ]

    def __init__(self, entity, name, clock, width, height):
        BusDriver.__init__(self, entity, name, clock)
        self.width = width
        self.height = height
        self.bus.SYS_PALETTE.setimmediatevalue(0)
        self.busy = Lock("%s_busy" % name)

    @cocotb.coroutine
    def run(self, data=None):

        if data is None:
            #Generate a test image
            data = [[0] * self.width] * self.height
            for y in range(self.height):
                for x in range(self.width):
                    #data[y][x] = x % 0x03F
                    data[y][x] = 0x00

        yield self.busy.acquire()

        print "Wait for pulse out to go high"
        while True:
            yield ReadOnly()
            if not self.bus.PULSE_OUT:
                print "Pulse out went high"
                yield RisingEdge(self.clock)
                continue
            yield RisingEdge(self.clock)

            ypos = int(self.bus.Y_OUT)
            xpos = int(self.bus.X_OUT)
            self.bus.SYS_PALETTE <= data[ypos][xpos]

        print "Exiting run..."
        self.busy.release()
示例#13
0
文件: amba.py 项目: zpan007/cocotb
class AXI4LiteMaster(BusDriver):
    """
    AXI4-Lite Master

    TODO: Kill all pending transactions if reset is asserted...
    """
    _signals = ["AWVALID", "AWADDR", "AWREADY",        # Write address channel
                "WVALID", "WREADY", "WDATA", "WSTRB",  # Write data channel
                "BVALID", "BREADY", "BRESP",           # Write response channel
                "ARVALID", "ARADDR", "ARREADY",        # Read address channel
                "RVALID", "RREADY", "RRESP", "RDATA"]  # Read data channel

    _default_config = {
        "address_latency" : 0,
        "data_latency" : 0,
    }

    def __init__(self, entity, name, clock, **kwargs):
        BusDriver.__init__(self, entity, name, clock)

        # Drive some sensible defaults (setimmediatevalue to avoid x asserts)
        self.bus.AWVALID.setimmediatevalue(0)
        self.bus.WVALID.setimmediatevalue(0)
        self.bus.ARVALID.setimmediatevalue(0)
        self.bus.BREADY.setimmediatevalue(1)
        self.bus.RREADY.setimmediatevalue(1)

        # Mutex for each channel that we master to prevent contention
        self.write_address_busy = Lock("%s_wabusy" % name)
        self.read_address_busy = Lock("%s_rabusy" % name)
        self.write_data_busy = Lock("%s_wbusy" % name)

        config = kwargs.pop('config', {})
        self.config = AXI4LiteMaster._default_config.copy()

        for configoption, value in config.items():
            self.config[configoption] = value
            self.log.debug("Setting config option %s to %s" %
                           (configoption, str(value)))
    @cocotb.coroutine
    def _send_write_address(self, address, delay=0):
        """
        Send the write address, with optional delay (in clocks)
        """
        yield self.write_address_busy.acquire()
        for cycle in range(max(self.config["address_latency"], delay)):
            yield RisingEdge(self.clock)

        self.bus.AWADDR <= address
        self.bus.AWVALID <= 1

        while True:
            yield ReadOnly()
            if self.bus.AWREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.AWVALID <= 0
        self.write_address_busy.release()

    @cocotb.coroutine
    def _send_write_data(self, data, delay=0, byte_enable=0xF):
        """
        Send the write address, with optional delay (in clocks)
        """
        yield self.write_data_busy.acquire()
        for cycle in range(max(self.config["data_latency"], delay)):
            yield RisingEdge(self.clock)

        self.bus.WDATA <= data
        self.bus.WVALID <= 1
        self.bus.WSTRB <= byte_enable

        while True:
            yield ReadOnly()
            if self.bus.WREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.WVALID <= 0
        self.write_data_busy.release()

    @cocotb.coroutine
    def write(self, address, value, byte_enable=0xf, address_latency=0,
              data_latency=0, sync=True):
        """
        Write a value to an address.

        Args:
            address (int): The address to write to
            value (int): The data value to write
            byte_enable (int, optional): Which bytes in value to actually write.
                Default is to write all bytes.
            address_latency (int, optional): Delay before setting the address (in clock cycles).
                Default is no delay.
            data_latency (int, optional): Delay before setting the data value (in clock cycles).
                Default is no delay.
            sync (bool, optional): Wait for rising edge on clock initially.
                Defaults to True.
            
        Returns:
            BinaryValue: The write response value
            
        Raises:
            AXIProtocolError: If write response from AXI is not ``OKAY``
        """
        if sync:
            yield RisingEdge(self.clock)

        c_addr = cocotb.fork(self._send_write_address(address,
                                                      delay=address_latency))
        c_data = cocotb.fork(self._send_write_data(value,
                                                   byte_enable=byte_enable,
                                                   delay=data_latency))

        if c_addr:
            yield c_addr.join()
        if c_data:
            yield c_data.join()

        # Wait for the response
        while True:
            yield ReadOnly()
            if self.bus.BVALID.value and self.bus.BREADY.value:
                result = self.bus.BRESP.value
                self.log.debug("Writing to address 0x%08x with 0x%08x" %
                               (address, value))
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)

        if int(result):
            raise AXIProtocolError("Write to address 0x%08x failed with BRESP: %d"
                               % (address, int(result)))

        raise ReturnValue(result)

    @cocotb.coroutine
    def read(self, address, sync=True):
        """
        Read from an address.
        
        Args:
            address (int): The address to read from
            sync (bool, optional): Wait for rising edge on clock initially.
                Defaults to True.
            
        Returns:
            BinaryValue: The read data value
            
        Raises:
            AXIProtocolError: If read response from AXI is not ``OKAY``
        """
        if sync:
            yield RisingEdge(self.clock)

        self.bus.ARADDR <= address
        self.bus.ARVALID <= 1

        while True:
            yield ReadOnly()
            if self.bus.ARREADY.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        self.bus.ARVALID <= 0

        while True:
            yield ReadOnly()
            if self.bus.RVALID.value and self.bus.RREADY.value:
                data = self.bus.RDATA.value
                result = self.bus.RRESP.value
                self.log.debug("Data at address 0x%08x is 0x%08x" %
                               (address, data))
                break
            yield RisingEdge(self.clock)

        if int(result):
            raise AXIProtocolError("Read address 0x%08x failed with RRESP: %d" %
                               (address, int(result)))

        raise ReturnValue(data)

    def __len__(self):
        return 2**len(self.bus.ARADDR)
示例#14
0
文件: amba.py 项目: zpan007/cocotb
class AXI4StreamMaster(BusDriver):

    _signals = ["TVALID", "TREADY", "TDATA"]  # Write data channel
    _optional_signals = ["TLAST", "TKEEP", "TSTRB", "TID", "TDEST", "TUSER"]

    def __init__(self, entity, name, clock, width=32):
        BusDriver.__init__(self, entity, name, clock)
        #Drive default values onto bus
        self.width = width
        self.strobe_width = width / 8
        self.bus.TVALID.setimmediatevalue(0)
        self.bus.TLAST.setimmediatevalue(0)
        self.bus.TDATA.setimmediatevalue(0)
        self.bus.TKEEP.setimmediatevalue(0)
        self.bus.TID.setimmediatevalue(0)
        self.bus.TDEST.setimmediatevalue(0)
        self.bus.TUSER.setimmediatevalue(0)

        self.write_data_busy = Lock("%s_wbusy" % name)

    @cocotb.coroutine
    def write(self, data, byte_enable=-1, keep=1, tid=0, dest=0, user=0):
        """
        Send the write data, with optional delay
        """
        yield self.write_data_busy.acquire()
        self.bus.TVALID <=  0
        self.bus.TLAST  <=  0
        self.bus.TID    <=  tid
        self.bus.TDEST  <=  dest
        self.bus.TUSER  <=  user
        self.bus.TSTRB  <=  (1 << self.strobe_width) - 1
        if byte_enable == -1:
            byte_enable = (self.width >> 3) - 1

        #Wait for the slave to assert tready
        while True:
            yield ReadOnly()
            if self.bus.TREADY.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        #every clock cycle update the data
        for i in range (len(data)):
            self.bus.TVALID <=  1
            self.bus.TDATA  <= data[i]
            if i >= len(data) - 1:
                self.bus.TLAST  <=  1;
            yield ReadOnly()
            if not self.bus.TREADY.value:
                while True:
                    yield RisingEdge(self.clock)
                    yield ReadOnly()
                    if self.bus.TREADY.value:
                        yield RisingEdge(self.clock)
                        break
                continue
            yield RisingEdge(self.clock)

        self.bus.TLAST  <=  0;
        self.bus.TVALID <=  0;
        yield RisingEdge(self.clock)
        self.write_data_busy.release()
        self.bus.TSTRB  <=  0
示例#15
0
class FwriscTracerSignalBfm():
    '''
    Implements a signal-level BFM for the FWRISC tracer
    '''
    
    def __init__(self, scope):
        self.listener_l = []
        self.lock = Lock()
        self.ev = Event()
        self.scope = scope
        cocotb.fork(self.run())
        pass

    @cocotb.coroutine
    def run(self):
        while True:
            yield RisingEdge(self.scope.clock)
            
            if self.scope.rd_write and self.scope.rd_waddr != 0:
#                print("reg_write")
                self.reg_write(int(self.scope.rd_waddr), int(self.scope.rd_wdata))
            
            if self.scope.ivalid:
#                print("instr_exec")
                self.instr_exec(int(self.scope.pc), int(self.scope.instr))
                
            if self.scope.mvalid and self.scope.mwrite:
                self.mem_write(
                    int(self.scope.maddr), 
                    int(self.scope.mstrb),
                    int(self.scope.mdata))
        pass
    
    def add_addr_region(self, base, limit):
        # NOP
        pass
    
    def set_trace_all_memwrite(self, t):
        pass
    
    def set_trace_instr(self, all_instr, jump_instr, call_instr):
        pass
    
    def set_trace_reg_writes(self, t):
        pass    
    
    def add_listener(self, l):
        self.listener_l.append(l)
    
    def instr_exec(self, pc, instr):
        for l in self.listener_l:
            l.instr_exec(pc, instr)
    
    def reg_write(self, waddr, wdata):
        for l in self.listener_l:
            l.reg_write(waddr, wdata)
    
    def mem_write(self, maddr, mstrb, mdata):
        for l in self.listener_l:
            l.mem_write(maddr, mstrb, mdata)
            
    @cocotb.coroutine
    def get_reg_info(self, raddr):
        yield self.lock.acquire()
        self.get_reg_info_req(raddr)
        yield self.ev.wait()
        ret = self.ev.data
        self.ev.clear()
        self.lock.release()
        return ret
示例#16
0
class CommandMaster (BusDriver):
    _signals = ["EN", "ERROR", "ACK", "STATUS", "INTERRUPT",
                "ADR", "WR_RD", "BYTE_EN",
                "WR_DATA", "RD_DATA"]

    def __init__(self,
                 entity,
                 name,
                 clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.EN.setimmediatevalue(0)
        self.bus.ADR.setimmediatevalue(0)
        self.bus.WR_RD.setimmediatevalue(0)
        self.bus.BYTE_EN.setimmediatevalue(0)
        self.bus.WR_DATA.setimmediatevalue(0)

        # Mutex for each channel that we master to prevent contention
        self.rd_busy = Lock("%s_wbusy" % name)
        self.wr_busy = Lock("%s_rbusy" % name)

    @cocotb.coroutine
    def write(self, address, data, byte_en = 0xF):
        yield self.wr_busy.acquire()
        yield RisingEdge(self.clock)
        self.bus.ADR        <= address
        self.bus.WR_RD      <=  1
        self.bus.EN         <=  1
        self.bus.ADR        <=  address
        self.bus.WR_DATA    <=  data
        self.bus.BYTE_EN    <=  byte_en

        yield RisingEdge(self.clock)

        yield ReadOnly()
        rdy = int(self.bus.ACK)

        while (rdy == 0):
            yield RisingEdge(self.clock)
            yield ReadOnly()
            rdy = int(self.bus.ACK)

        yield RisingEdge(self.clock)
        self.bus.EN         <=  0
        self.wr_busy.release()

    @cocotb.coroutine
    def read(self, address):
        data = []
        yield self.rd_busy.acquire()
        self.bus.ADR        <= address
        self.bus.EN         <= 1
        self.bus.WR_RD      <= 0
        self.bus.BYTE_EN    <= 0
        yield RisingEdge(self.clock)

        yield ReadOnly()
        rdy = int(self.bus.ACK)

        while (rdy == 0):
            yield RisingEdge(self.clock)
            yield ReadOnly()
            rdy = int(self.bus.ACK)

        yield RisingEdge(self.clock)
        self.bus.EN         <=  0
示例#17
0
class FwriscTracerBfm():
    def __init__(self):
        self.listener_l = []
        self.lock = Lock()
        self.ev = Event()
        self.addr_region_idx = 0
        pass

    def add_listener(self, l):
        self.listener_l.append(l)

    def add_addr_region(self, base, limit):
        self.set_addr_region(self.addr_region_idx, base, limit, 1)
        self.addr_region_idx += 1

    @cocotb.bfm_export(cocotb.bfm_uint32_t, cocotb.bfm_uint32_t)
    def instr_exec(self, pc, instr):
        #        print("instr_exec: " + hex(pc))
        for l in self.listener_l:
            l.instr_exec(pc, instr)

    @cocotb.bfm_export(cocotb.bfm_uint32_t, cocotb.bfm_uint32_t)
    def reg_write(self, waddr, wdata):
        #        print("reg_write: " + hex(waddr))
        for l in self.listener_l:
            l.reg_write(waddr, wdata)

    @cocotb.bfm_export(cocotb.bfm_uint32_t, cocotb.bfm_uint32_t,
                       cocotb.bfm_uint32_t)
    def mem_write(self, maddr, mstrb, mdata):
        #        print("mem_write: " + hex(maddr))
        for l in self.listener_l:
            l.mem_write(maddr, mstrb, mdata)

    @cocotb.coroutine
    def get_reg_info(self, raddr):
        yield self.lock.acquire()
        self.get_reg_info_req(raddr)
        yield self.ev.wait()
        ret = self.ev.data
        self.ev.clear()
        self.lock.release()
        return ret

    @cocotb.bfm_import(cocotb.bfm_uint32_t)
    def get_reg_info_req(self, raddr):
        pass

    @cocotb.bfm_import(cocotb.bfm_uint32_t, cocotb.bfm_uint32_t,
                       cocotb.bfm_uint32_t, cocotb.bfm_uint32_t)
    def set_addr_region(self, i, base, limit, valid):
        pass

    @cocotb.bfm_export(cocotb.bfm_uint32_t, cocotb.bfm_uint32_t)
    def get_reg_info_ack(self, rdata, accessed):
        self.ev.set((rdata, accessed))

    @cocotb.bfm_import(cocotb.bfm_uint32_t)
    def set_trace_all_memwrite(self, t):
        pass

    @cocotb.bfm_import(cocotb.bfm_uint32_t, cocotb.bfm_uint32_t,
                       cocotb.bfm_uint32_t)
    def set_trace_instr(self, all_instr, jump_instr, call_instr):
        pass

    @cocotb.bfm_import(cocotb.bfm_uint32_t)
    def set_trace_reg_writes(self, t):
        pass
示例#18
0
class CommandMaster(BusDriver):
    _signals = [
        "EN", "ERROR", "ACK", "STATUS", "INTERRUPT", "ADR", "WR_RD", "BYTE_EN",
        "WR_DATA", "RD_DATA"
    ]

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)
        self.bus.EN.setimmediatevalue(0)
        self.bus.ADR.setimmediatevalue(0)
        self.bus.WR_RD.setimmediatevalue(0)
        self.bus.BYTE_EN.setimmediatevalue(0)
        self.bus.WR_DATA.setimmediatevalue(0)

        # Mutex for each channel that we master to prevent contention
        self.rd_busy = Lock("%s_wbusy" % name)
        self.wr_busy = Lock("%s_rbusy" % name)

    @cocotb.coroutine
    def write(self, address, data, byte_en=0xF):
        yield self.wr_busy.acquire()
        yield RisingEdge(self.clock)
        self.bus.ADR <= address
        self.bus.WR_RD <= 1
        self.bus.EN <= 1
        self.bus.ADR <= address
        self.bus.WR_DATA <= data
        self.bus.BYTE_EN <= byte_en

        yield RisingEdge(self.clock)

        yield ReadOnly()
        rdy = int(self.bus.ACK)

        while (rdy == 0):
            yield RisingEdge(self.clock)
            yield ReadOnly()
            rdy = int(self.bus.ACK)

        yield RisingEdge(self.clock)
        self.bus.EN <= 0
        self.wr_busy.release()

    @cocotb.coroutine
    def read(self, address):
        data = []
        yield self.rd_busy.acquire()
        self.bus.ADR <= address
        self.bus.EN <= 1
        self.bus.WR_RD <= 0
        self.bus.BYTE_EN <= 0
        yield RisingEdge(self.clock)

        yield ReadOnly()
        rdy = int(self.bus.ACK)

        while (rdy == 0):
            yield RisingEdge(self.clock)
            yield ReadOnly()
            rdy = int(self.bus.ACK)

        yield RisingEdge(self.clock)
        self.bus.EN <= 0
示例#19
0
文件: amba.py 项目: cnshijin/cocotb
class AXI4StreamMaster(BusDriver):

    _signals = ["TVALID", "TREADY", "TDATA"]  # Write data channel
    _optional_signals = ["TLAST", "TKEEP", "TSTRB", "TID", "TDEST", "TUSER"]

    def __init__(self, entity, name, clock, width=32):
        BusDriver.__init__(self, entity, name, clock)
        #Drive default values onto bus
        self.width = width
        self.strobe_width = width / 8
        self.bus.TVALID.setimmediatevalue(0)
        self.bus.TLAST.setimmediatevalue(0)
        self.bus.TDATA.setimmediatevalue(0)
        self.bus.TKEEP.setimmediatevalue(0)
        self.bus.TID.setimmediatevalue(0)
        self.bus.TDEST.setimmediatevalue(0)
        self.bus.TUSER.setimmediatevalue(0)

        self.write_data_busy = Lock("%s_wbusy" % name)

    @cocotb.coroutine
    def write(self, data, byte_enable=-1, keep=1, tid=0, dest=0, user=0):
        """
        Send the write data, with optional delay
        """
        yield self.write_data_busy.acquire()
        self.bus.TVALID <=  0
        self.bus.TLAST  <=  0
        self.bus.TID    <=  tid
        self.bus.TDEST  <=  dest
        self.bus.TUSER  <=  user
        self.bus.TSTRB  <=  (1 << self.strobe_width) - 1
        if byte_enable == -1:
            byte_enable = (self.width >> 3) - 1

        #Wait for the slave to assert tready
        while True:
            yield ReadOnly()
            if self.bus.TREADY.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        #every clock cycle update the data
        for i in range (len(data)):
            self.bus.TVALID <=  1
            self.bus.TDATA  <= data[i]
            if i >= len(data) - 1:
                self.bus.TLAST  <=  1;
            yield ReadOnly()
            if not self.bus.TREADY.value:
                while True:
                    yield RisingEdge(self.clock)
                    yield ReadOnly()
                    if self.bus.TREADY.value:
                        yield RisingEdge(self.clock)
                        break
                continue
            yield RisingEdge(self.clock)

        self.bus.TLAST  <=  0;
        self.bus.TVALID <=  0;
        yield RisingEdge(self.clock)
        self.write_data_busy.release()
        self.bus.TSTRB  <=  0
示例#20
0
class CommandMaster (BusDriver):
    _signals = ["EN", "ERROR", "ACK", "STATUS", "INTERRUPT",
                "ADR", "ADR_FIXED", "ADR_WRAP",
                "WR_RD", "COUNT"]

    def __init__(self,
                 entity,
                 name,
                 clock,
                 wr_fifo_name = "WR",
                 wr_fifo_clk = None,
                 wr_fifo_clk_period = 10,
                 rd_fifo_name = "RD",
                 rd_fifo_clk = None,
                 rd_fifo_clk_period = 10):
        BusDriver.__init__(self, entity, name, clock)
        if wr_fifo_clk is None:
            wr_fifo_clk = entity.WR_CLK
        if rd_fifo_clk is None:
            rd_fifo_clk = entity.RD_CLK

        self.bus.EN.setimmediatevalue(0)
        self.bus.ADR.setimmediatevalue(0)
        self.bus.ADR_FIXED.setimmediatevalue(0)
        self.bus.ADR_WRAP.setimmediatevalue(0)
        self.bus.WR_RD.setimmediatevalue(0)
        self.bus.COUNT.setimmediatevalue(0)

        # Mutex for each channel that we master to prevent contention
        self.command_busy = Lock("%s_wabusy" % name)
        cocotb.fork(Clock(wr_fifo_clk, wr_fifo_clk_period).start())
        cocotb.fork(Clock(rd_fifo_clk, rd_fifo_clk_period).start())

        self.write_fifo = PPFIFOWritePath(entity, wr_fifo_name, wr_fifo_clk)
        self.read_fifo = PPFIFOReadPath(entity, rd_fifo_name, rd_fifo_clk)

    @cocotb.coroutine
    def write(self, address, data):
        count = 0
        yield self.command_busy.acquire()
        yield RisingEdge(self.clock)
        self.bus.ADR    <= address
        self.bus.COUNT  <=  len(data)
        self.bus.WR_RD  <=  1
        self.bus.EN     <=  1
        yield RisingEdge(self.clock)
        print "Length of data: %d" % len(data)

        yield self.write_fifo.write(data)

        yield RisingEdge(self.clock)
        self.bus.EN     <=  0
        self.command_busy.release()

    @cocotb.coroutine
    def read(self, address, size, sync=True):
        count = 0
        data = []
        yield self.command_busy.acquire()
        self.bus.ADR <= address
        self.bus.COUNT  <=  size
        self.bus.EN <= 1
        yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        self.bus.EN <=  0

        yield ReadOnly()
        self.command_busy.release()
示例#21
0
class AXI4LiteMaster(BusDriver):
    """AXI4-Lite Master.

    TODO: Kill all pending transactions if reset is asserted.
    """

    _signals = [
        "AWVALID",
        "AWADDR",
        "AWREADY",  # Write address channel
        "WVALID",
        "WREADY",
        "WDATA",
        "WSTRB",  # Write data channel
        "BVALID",
        "BREADY",
        "BRESP",  # Write response channel
        "ARVALID",
        "ARADDR",
        "ARREADY",  # Read address channel
        "RVALID",
        "RREADY",
        "RRESP",
        "RDATA"
    ]  # Read data channel

    def __init__(self, entity, name, clock, **kwargs):
        BusDriver.__init__(self, entity, name, clock, **kwargs)

        # Drive some sensible defaults (setimmediatevalue to avoid x asserts)
        self.bus.AWVALID.setimmediatevalue(0)
        self.bus.WVALID.setimmediatevalue(0)
        self.bus.ARVALID.setimmediatevalue(0)
        self.bus.BREADY.setimmediatevalue(1)
        self.bus.RREADY.setimmediatevalue(1)

        # Mutex for each channel that we master to prevent contention
        self.write_address_busy = Lock("%s_wabusy" % name)
        self.read_address_busy = Lock("%s_rabusy" % name)
        self.write_data_busy = Lock("%s_wbusy" % name)

    @cocotb.coroutine
    def _send_write_address(self, address, delay=0):
        """
        Send the write address, with optional delay (in clocks)
        """
        yield self.write_address_busy.acquire()
        for cycle in range(delay):
            yield RisingEdge(self.clock)

        self.bus.AWADDR <= address
        self.bus.AWVALID <= 1

        while True:
            yield ReadOnly()
            if self.bus.AWREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.AWVALID <= 0
        self.write_address_busy.release()

    @cocotb.coroutine
    def _send_write_data(self, data, delay=0, byte_enable=0xF):
        """Send the write address, with optional delay (in clocks)."""
        yield self.write_data_busy.acquire()
        for cycle in range(delay):
            yield RisingEdge(self.clock)

        self.bus.WDATA <= data
        self.bus.WVALID <= 1
        self.bus.WSTRB <= byte_enable

        while True:
            yield ReadOnly()
            if self.bus.WREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.WVALID <= 0
        self.write_data_busy.release()

    @cocotb.coroutine
    def write(self,
              address,
              value,
              byte_enable=0xf,
              address_latency=0,
              data_latency=0,
              sync=True):
        """Write a value to an address.

        Args:
            address (int): The address to write to.
            value (int): The data value to write.
            byte_enable (int, optional): Which bytes in value to actually write.
                Default is to write all bytes.
            address_latency (int, optional): Delay before setting the address (in clock cycles).
                Default is no delay.
            data_latency (int, optional): Delay before setting the data value (in clock cycles).
                Default is no delay.
            sync (bool, optional): Wait for rising edge on clock initially.
                Defaults to True.

        Returns:
            BinaryValue: The write response value.

        Raises:
            AXIProtocolError: If write response from AXI is not ``OKAY``.
        """
        if sync:
            yield RisingEdge(self.clock)

        c_addr = cocotb.fork(
            self._send_write_address(address, delay=address_latency))
        c_data = cocotb.fork(
            self._send_write_data(value,
                                  byte_enable=byte_enable,
                                  delay=data_latency))

        if c_addr:
            yield c_addr.join()
        if c_data:
            yield c_data.join()

        # Wait for the response
        while True:
            yield ReadOnly()
            if self.bus.BVALID.value and self.bus.BREADY.value:
                result = self.bus.BRESP.value
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)

        if int(result):
            raise AXIProtocolError(
                "Write to address 0x%08x failed with BRESP: %d" %
                (address, int(result)))

        return result

    @cocotb.coroutine
    def read(self, address, sync=True):
        """Read from an address.

        Args:
            address (int): The address to read from.
            sync (bool, optional): Wait for rising edge on clock initially.
                Defaults to True.

        Returns:
            BinaryValue: The read data value.

        Raises:
            AXIProtocolError: If read response from AXI is not ``OKAY``.
        """
        if sync:
            yield RisingEdge(self.clock)

        self.bus.ARADDR <= address
        self.bus.ARVALID <= 1

        while True:
            yield ReadOnly()
            if self.bus.ARREADY.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        self.bus.ARVALID <= 0

        while True:
            yield ReadOnly()
            if self.bus.RVALID.value and self.bus.RREADY.value:
                data = self.bus.RDATA.value
                result = self.bus.RRESP.value
                break
            yield RisingEdge(self.clock)

        if int(result):
            raise AXIProtocolError(
                "Read address 0x%08x failed with RRESP: %d" %
                (address, int(result)))

        return data

    def __len__(self):
        return 2**len(self.bus.ARADDR)
示例#22
0
文件: amba.py 项目: enchanter/cocotb
class AXI4LiteMaster(BusDriver):
    """
    AXI4-Lite Master

    TODO: Kill all pending transactions if reset is asserted...
    """
    _signals = ["AWVALID", "AWADDR", "AWREADY",         # Write address channel
                "WVALID", "WREADY", "WDATA", "WSTRB",   # Write data channel
                "BVALID", "BREADY", "BRESP",            # Write response channel
                "ARVALID", "ARADDR", "ARREADY",         # Read address channel
                "RVALID", "RREADY", "RRESP", "RDATA"]   # Read data channel

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)

        # Drive some sensible defaults (setimmediatevalue to avoid x asserts)
        self.bus.AWVALID.setimmediatevalue(0)
        self.bus.WVALID.setimmediatevalue(0)
        self.bus.ARVALID.setimmediatevalue(0)
        self.bus.BREADY.setimmediatevalue(1)
        self.bus.RREADY.setimmediatevalue(1)

        # Mutex for each channel that we master to prevent contention
        self.write_address_busy = Lock("%s_wabusy" % name)
        self.read_address_busy = Lock("%s_rabusy" % name)
        self.write_data_busy = Lock("%s_wbusy" % name)


    @cocotb.coroutine
    def _send_write_address(self, address, delay=0):
        """
        Send the write address, with optional delay
        """
        yield self.write_address_busy.acquire()
        for cycle in range(delay):
            yield RisingEdge(self.clock)

        self.bus.AWADDR         <= address
        self.bus.AWVALID        <= 1

        while True:
            yield ReadOnly()
            if self.bus.AWREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.AWVALID        <= 0
        self.write_address_busy.release()

    @cocotb.coroutine
    def _send_write_data(self, data, delay=0, byte_enable=0xF):
        """
        Send the write address, with optional delay
        """
        yield self.write_data_busy.acquire()
        for cycle in range(delay):
            yield RisingEdge(self.clock)

        self.bus.WDATA          <= data
        self.bus.WVALID         <= 1
        self.bus.WSTRB          <= byte_enable

        while True:
            yield ReadOnly()
            if self.bus.WREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.WVALID        <= 0
        self.write_data_busy.release()


    @cocotb.coroutine
    def write(self, address, value, byte_enable=0xf, address_latency=0, data_latency=0):
        """
        Write a value to an address.

        The *_latency KWargs allow control over the delta 
        """
        

        c_addr = cocotb.fork(self._send_write_address(address, delay=address_latency))
        c_data = cocotb.fork(self._send_write_data(value, byte_enable=byte_enable, delay=data_latency))



        if c_addr:
            yield c_addr.join()
        if c_data:
            yield c_data.join()

        # Wait for the response
        while True:
            yield ReadOnly()
            if self.bus.BVALID.value and self.bus.BREADY.value:
                result = self.bus.BRESP.value
                break
            yield RisingEdge(self.clock)
        
        yield RisingEdge(self.clock)  
        
        if int(result):
            raise AXIReadError("Write to address 0x%08x failed with BRESP: %d" %(
                address, int(result)))

        raise ReturnValue(result)


    @cocotb.coroutine
    def read(self, address, sync=True):
        """
        Read from an address.
        """
        if sync:
            yield RisingEdge(self.clock)

        self.bus.ARADDR         <= address
        self.bus.ARVALID        <= 1

        while True:
            yield ReadOnly()
            if self.bus.ARREADY.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        self.bus.ARVALID        <= 0

        while True:
            yield ReadOnly()
            if self.bus.RVALID.value and self.bus.RREADY.value:
                data = self.bus.RDATA.value
                result = self.bus.RRESP.value
                break
            yield RisingEdge(self.clock)

        if int(result):
            raise AXIReadError("Read address 0x%08x failed with RRESP: %d" %(
                address, int(result)))

        raise ReturnValue(data)
示例#23
0
class AXI4StreamMaster(BusDriver):

    _signals = ["tvalid", "tready", "tdata"]  # Write data channel
    _optional_signals = ["tlast", "tkeep", "tstrb", "tid", "tdest", "tuser"]

    def __init__(self, entity, name, clock, width=32):
        BusDriver.__init__(self, entity, name, clock)
        #drive default values onto bus
        self.width = width
        self.strobe_width = width / 8
        self.bus.tvalid.setimmediatevalue(0)
        self.bus.tlast.setimmediatevalue(0)
        self.bus.tdata.setimmediatevalue(0)

        if hasattr(self.bus, 'tkeep'):
            self.bus.tkeep.setimmediatevalue(0)

        if hasattr(self.bus, 'tid'):
            self.bus.tid.setimmediatevalue(0)

        if hasattr(self.bus, 'tdest'):
            self.bus.tdest.setimmediatevalue(0)

        if hasattr(self.bus, 'tuser'):
            self.bus.tuser.setimmediatevalue(0)

        self.write_data_busy = Lock("%s_wbusy" % name)

    @cocotb.coroutine
    def write(self, data, byte_enable=-1, keep=1, tid=0, dest=0, user=0):
        """
        Send the write data, with optional delay
        """
        yield self.write_data_busy.acquire()
        self.bus.tvalid <=  0
        self.bus.tlast  <=  0

        if hasattr(self.bus, 'tid'):
            self.bus.tid    <=  tid

        if hasattr(self.bus, 'tdest'):
            self.bus.tdest  <=  dest

        if hasattr(self.bus, 'tuser'):
            self.bus.tuser  <=  user

        if hasattr(self.bus, 'tstrb'):
            self.bus.tstrb  <=  (1 << self.strobe_width) - 1

        if byte_enable == -1:
            byte_enable = (self.width >> 3) - 1

        #Wait for the slave to assert tready
        while True:
            yield ReadOnly()
            if self.bus.tready.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        #every clock cycle update the data
        for i in range (len(data)):
            self.bus.tvalid <=  1
            self.bus.tdata  <= data[i]
            if i >= len(data) - 1:
                self.bus.tlast  <=  1;
            yield ReadOnly()
            if not self.bus.tready.value:
                while True:
                    yield RisingEdge(self.clock)
                    yield ReadOnly()
                    if self.bus.tready.value:
                        yield RisingEdge(self.clock)
                        break
                continue
            yield RisingEdge(self.clock)

        self.bus.tlast  <= 0;
        self.bus.tvalid <= 0;
        yield RisingEdge(self.clock)
        self.write_data_busy.release()
示例#24
0
文件: amba.py 项目: cnshijin/cocotb
class AXI4LiteMaster(BusDriver):
    """
    AXI4-Lite Master

    TODO: Kill all pending transactions if reset is asserted...
    """
    _signals = ["AWVALID", "AWADDR", "AWREADY",        # Write address channel
                "WVALID", "WREADY", "WDATA", "WSTRB",  # Write data channel
                "BVALID", "BREADY", "BRESP",           # Write response channel
                "ARVALID", "ARADDR", "ARREADY",        # Read address channel
                "RVALID", "RREADY", "RRESP", "RDATA"]  # Read data channel

    def __init__(self, entity, name, clock):
        BusDriver.__init__(self, entity, name, clock)

        # Drive some sensible defaults (setimmediatevalue to avoid x asserts)
        self.bus.AWVALID.setimmediatevalue(0)
        self.bus.WVALID.setimmediatevalue(0)
        self.bus.ARVALID.setimmediatevalue(0)
        self.bus.BREADY.setimmediatevalue(1)
        self.bus.RREADY.setimmediatevalue(1)

        # Mutex for each channel that we master to prevent contention
        self.write_address_busy = Lock("%s_wabusy" % name)
        self.read_address_busy = Lock("%s_rabusy" % name)
        self.write_data_busy = Lock("%s_wbusy" % name)

    @cocotb.coroutine
    def _send_write_address(self, address, delay=0):
        """
        Send the write address, with optional delay
        """
        yield self.write_address_busy.acquire()
        for cycle in range(delay):
            yield RisingEdge(self.clock)

        self.bus.AWADDR <= address
        self.bus.AWVALID <= 1

        while True:
            yield ReadOnly()
            if self.bus.AWREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.AWVALID <= 0
        self.write_address_busy.release()

    @cocotb.coroutine
    def _send_write_data(self, data, delay=0, byte_enable=0xF):
        """
        Send the write address, with optional delay
        """
        yield self.write_data_busy.acquire()
        for cycle in range(delay):
            yield RisingEdge(self.clock)

        self.bus.WDATA <= data
        self.bus.WVALID <= 1
        self.bus.WSTRB <= byte_enable

        while True:
            yield ReadOnly()
            if self.bus.WREADY.value:
                break
            yield RisingEdge(self.clock)
        yield RisingEdge(self.clock)
        self.bus.WVALID <= 0
        self.write_data_busy.release()

    @cocotb.coroutine
    def write(self, address, value, byte_enable=0xf, address_latency=0,
              data_latency=0):
        """
        Write a value to an address.

        The *_latency KWargs allow control over the delta
        """

        c_addr = cocotb.fork(self._send_write_address(address,
                                                      delay=address_latency))
        c_data = cocotb.fork(self._send_write_data(value,
                                                   byte_enable=byte_enable,
                                                   delay=data_latency))

        if c_addr:
            yield c_addr.join()
        if c_data:
            yield c_data.join()

        # Wait for the response
        while True:
            yield ReadOnly()
            if self.bus.BVALID.value and self.bus.BREADY.value:
                result = self.bus.BRESP.value
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)

        if int(result):
            raise AXIProtocolError("Write to address 0x%08x failed with BRESP: %d"
                               % (address, int(result)))

        raise ReturnValue(result)

    @cocotb.coroutine
    def read(self, address, sync=True):
        """
        Read from an address.
        """
        if sync:
            yield RisingEdge(self.clock)

        self.bus.ARADDR <= address
        self.bus.ARVALID <= 1

        while True:
            yield ReadOnly()
            if self.bus.ARREADY.value:
                break
            yield RisingEdge(self.clock)

        yield RisingEdge(self.clock)
        self.bus.ARVALID <= 0

        while True:
            yield ReadOnly()
            if self.bus.RVALID.value and self.bus.RREADY.value:
                data = self.bus.RDATA.value
                result = self.bus.RRESP.value
                break
            yield RisingEdge(self.clock)

        if int(result):
            raise AXIProtocolError("Read address 0x%08x failed with RRESP: %d" %
                               (address, int(result)))

        raise ReturnValue(data)
示例#25
0
class VideoOutBus(BusDriver):
    """
    Generate RGB Video Signals
    """

    _signals = [
        "RGB",
        "HSYNC",
        "VSYNC",
        "DATA_EN",
        "HBLANK",
        "VBLANK"
    ]

    def __init__(self, entity, name, clock, width, height, hblank, vblank):
        BusDriver.__init__(self, entity, name, clock)

        #Drive some sensible defaults
        self.bus.RGB.setimmediatevalue(0)
        self.bus.HSYNC.setimmediatevalue(0)
        self.bus.VSYNC.setimmediatevalue(0)
        self.bus.DATA_EN.setimmediatevalue(0)

        self.bus.HBLANK.setimmediatevalue(1)
        self.bus.VBLANK.setimmediatevalue(1)

        self.width = width
        self.height = height
        self.hblank = hblank
        self.vblank = vblank

        self.write_lock = Lock("%s_busy" % name)

    @cocotb.coroutine
    def write(self, video):
        #print "Video: %s" % video
        yield self.write_lock.acquire()
        yield RisingEdge(self.clock)
        self.bus.DATA_EN               <=  1
        for frame in video:
            for line in frame:
                for pixel in line:
                    self.bus.HBLANK    <=  0
                    self.bus.VBLANK    <=  0
                    self.bus.HSYNC     <=  1
                    self.bus.VSYNC     <=  1

                    self.bus.RGB        <= pixel
                    yield RisingEdge(self.clock)

                #Horizontal Blank
                self.bus.HSYNC         <=  0
                self.bus.HBLANK        <=  1
                for i in range(self.hblank):
                    yield RisingEdge(self.clock)

                self.bus.VSYNC         <=  0
                self.bus.VBLANK        <=  1

            #Vertical Blank
            for i in range(self.vblank):
                yield RisingEdge(self.clock)

        self.bus.DATA_EN                <=  0
        self.write_lock.release()