Loading tb/interfaces.py 0 → 100644 +101 −0 Original line number Original line Diff line number Diff line """ A driver and monitor to abstract the interface to the JPEG encoder """ import io from PIL import Image import cocotb from cocotb.triggers import RisingEdge, ReadOnly from cocotb.drivers import Driver from cocotb.monitors import Monitor _jpeg_header = open("header.bin", "r").read() class JpegMonitor(Monitor): def __init__(self, dut, **kwargs): self.dut = dut Monitor.__init__(self, **kwargs) @cocotb.coroutine def _monitor_recv(self): """Creates an Image object from the output of the DUT""" data = "" clkedge = RisingEdge(self.dut.clk) ro = ReadOnly() while True: yield clkedge yield ro if self.dut.data_ready.value: data += self.dut.JPEG_bitstream.value.buff if self.dut.eof_data_partial_ready.value: f_obj = io.BytesIO(_jpeg_header + data + "\xff\xd9") img = Image.open(f_obj) self.log.info("Recovered image %s of %dx%d in mode %s" % ( img.format, img.size[0], img.size[1], img.mode)) yield clkedge self._recv(img) data = "" class ImageDriver(Driver): def __init__(self, dut): self.dut = dut Driver.__init__(self) @cocotb.coroutine def _driver_send(self, image, **kwargs): """ Send an image into the DUT. Image should be in RGB format and a multiple of 8 pixels in both width and height Args: image (PIL.Image) image to send into the dut """ if image.mode != "RGB": raise TypeError("Require an format RGB image") width, height = image.size dut = self.dut # Local reference to save lookup clk_edge = RisingEdge(dut.clk) # Recycle objects for efficiency yield clk_edge # Reset the dut first dut.rst <= 1 yield clk_edge dut.rst <= 0 dut.end_of_file_signal <= 0 pixels = image.load() for y in xrange(0,height,8): for x in xrange(0,width,8): dut.enable <= 1 self.log.debug("Sending block X% 4d/% 4d, Y% 4d/% 4d" % ( x, width, y, height)) if y >= height-8 and x >= width-8: dut.end_of_file_signal <= 1 for y_block in xrange(8): for x_block in xrange(8): # If the image isn't a multiple of 8 pixels we # repeat the edge values (see Readme.doc) x_ofs = min(x+x_block, width-1) y_ofs = min(y+y_block, height-1) r,g,b = pixels[x_ofs, y_ofs] dut.data_in <= (b<<16 | g<<8 | r) yield clk_edge dut.end_of_file_signal <= 0 for i in xrange(33): yield clk_edge dut.enable <= 0 yield clk_edge tb/test_jpeg_top.py +3 −95 Original line number Original line Diff line number Diff line Loading @@ -5,109 +5,17 @@ and check that the output is sufficiently similar to the input. NB Limited to 96x96 images since we're using a static JPEG header. NB Limited to 96x96 images since we're using a static JPEG header. """ """ import os import os import io import logging import logging from itertools import izip from itertools import izip from PIL import Image from PIL import Image import cocotb import cocotb from cocotb.result import TestFailure from cocotb.result import TestFailure from cocotb.clock import Clock from cocotb.triggers import RisingEdge, ReadOnly from cocotb.drivers import Driver from cocotb.monitors import Monitor from cocotb.regression import TestFactory from cocotb.regression import TestFactory from cocotb.clock import Clock _jpeg_header = open("header.bin", "r").read() from interfaces import ImageDriver, JpegMonitor class JpegMonitor(Monitor): def __init__(self, dut, **kwargs): self.dut = dut Monitor.__init__(self, **kwargs) @cocotb.coroutine def _monitor_recv(self): """Creates an Image object from the output of the DUT""" data = "" clkedge = RisingEdge(self.dut.clk) ro = ReadOnly() while True: yield clkedge yield ro if self.dut.data_ready.value: data += self.dut.JPEG_bitstream.value.buff if self.dut.eof_data_partial_ready.value: f_obj = io.BytesIO(_jpeg_header + data + "\xff\xd9") img = Image.open(f_obj) self.log.info("Recovered image %s of %dx%d in mode %s" % ( img.format, img.size[0], img.size[1], img.mode)) yield clkedge self._recv(img) data = "" class ImageDriver(Driver): def __init__(self, dut): self.dut = dut Driver.__init__(self) @cocotb.coroutine def _driver_send(self, image, **kwargs): """ Send an image into the DUT. Image should be in RGB format and a multiple of 8 pixels in both width and height Args: image (PIL.Image) image to send into the dut """ if image.mode != "RGB": raise TypeError("Require an format RGB image") width, height = image.size dut = self.dut # Local reference to save lookup clk_edge = RisingEdge(dut.clk) # Recycle objects for efficiency yield clk_edge # Reset the dut first dut.rst <= 1 yield clk_edge dut.rst <= 0 dut.end_of_file_signal <= 0 pixels = image.load() for y in xrange(0,height,8): for x in xrange(0,width,8): dut.enable <= 1 self.log.debug("Sending block X% 4d/% 4d, Y% 4d/% 4d" % ( x, width, y, height)) if y >= height-8 and x >= width-8: dut.end_of_file_signal <= 1 for y_block in xrange(8): for x_block in xrange(8): # If the image isn't a multiple of 8 pixels we # repeat the edge values (see Readme.doc) x_ofs = min(x+x_block, width-1) y_ofs = min(y+y_block, height-1) r,g,b = pixels[x_ofs, y_ofs] dut.data_in <= (b<<16 | g<<8 | r) yield clk_edge dut.end_of_file_signal <= 0 for i in xrange(33): yield clk_edge dut.enable <= 0 yield clk_edge def compare(i1, i2): def compare(i1, i2): """ """ Loading Loading
tb/interfaces.py 0 → 100644 +101 −0 Original line number Original line Diff line number Diff line """ A driver and monitor to abstract the interface to the JPEG encoder """ import io from PIL import Image import cocotb from cocotb.triggers import RisingEdge, ReadOnly from cocotb.drivers import Driver from cocotb.monitors import Monitor _jpeg_header = open("header.bin", "r").read() class JpegMonitor(Monitor): def __init__(self, dut, **kwargs): self.dut = dut Monitor.__init__(self, **kwargs) @cocotb.coroutine def _monitor_recv(self): """Creates an Image object from the output of the DUT""" data = "" clkedge = RisingEdge(self.dut.clk) ro = ReadOnly() while True: yield clkedge yield ro if self.dut.data_ready.value: data += self.dut.JPEG_bitstream.value.buff if self.dut.eof_data_partial_ready.value: f_obj = io.BytesIO(_jpeg_header + data + "\xff\xd9") img = Image.open(f_obj) self.log.info("Recovered image %s of %dx%d in mode %s" % ( img.format, img.size[0], img.size[1], img.mode)) yield clkedge self._recv(img) data = "" class ImageDriver(Driver): def __init__(self, dut): self.dut = dut Driver.__init__(self) @cocotb.coroutine def _driver_send(self, image, **kwargs): """ Send an image into the DUT. Image should be in RGB format and a multiple of 8 pixels in both width and height Args: image (PIL.Image) image to send into the dut """ if image.mode != "RGB": raise TypeError("Require an format RGB image") width, height = image.size dut = self.dut # Local reference to save lookup clk_edge = RisingEdge(dut.clk) # Recycle objects for efficiency yield clk_edge # Reset the dut first dut.rst <= 1 yield clk_edge dut.rst <= 0 dut.end_of_file_signal <= 0 pixels = image.load() for y in xrange(0,height,8): for x in xrange(0,width,8): dut.enable <= 1 self.log.debug("Sending block X% 4d/% 4d, Y% 4d/% 4d" % ( x, width, y, height)) if y >= height-8 and x >= width-8: dut.end_of_file_signal <= 1 for y_block in xrange(8): for x_block in xrange(8): # If the image isn't a multiple of 8 pixels we # repeat the edge values (see Readme.doc) x_ofs = min(x+x_block, width-1) y_ofs = min(y+y_block, height-1) r,g,b = pixels[x_ofs, y_ofs] dut.data_in <= (b<<16 | g<<8 | r) yield clk_edge dut.end_of_file_signal <= 0 for i in xrange(33): yield clk_edge dut.enable <= 0 yield clk_edge
tb/test_jpeg_top.py +3 −95 Original line number Original line Diff line number Diff line Loading @@ -5,109 +5,17 @@ and check that the output is sufficiently similar to the input. NB Limited to 96x96 images since we're using a static JPEG header. NB Limited to 96x96 images since we're using a static JPEG header. """ """ import os import os import io import logging import logging from itertools import izip from itertools import izip from PIL import Image from PIL import Image import cocotb import cocotb from cocotb.result import TestFailure from cocotb.result import TestFailure from cocotb.clock import Clock from cocotb.triggers import RisingEdge, ReadOnly from cocotb.drivers import Driver from cocotb.monitors import Monitor from cocotb.regression import TestFactory from cocotb.regression import TestFactory from cocotb.clock import Clock _jpeg_header = open("header.bin", "r").read() from interfaces import ImageDriver, JpegMonitor class JpegMonitor(Monitor): def __init__(self, dut, **kwargs): self.dut = dut Monitor.__init__(self, **kwargs) @cocotb.coroutine def _monitor_recv(self): """Creates an Image object from the output of the DUT""" data = "" clkedge = RisingEdge(self.dut.clk) ro = ReadOnly() while True: yield clkedge yield ro if self.dut.data_ready.value: data += self.dut.JPEG_bitstream.value.buff if self.dut.eof_data_partial_ready.value: f_obj = io.BytesIO(_jpeg_header + data + "\xff\xd9") img = Image.open(f_obj) self.log.info("Recovered image %s of %dx%d in mode %s" % ( img.format, img.size[0], img.size[1], img.mode)) yield clkedge self._recv(img) data = "" class ImageDriver(Driver): def __init__(self, dut): self.dut = dut Driver.__init__(self) @cocotb.coroutine def _driver_send(self, image, **kwargs): """ Send an image into the DUT. Image should be in RGB format and a multiple of 8 pixels in both width and height Args: image (PIL.Image) image to send into the dut """ if image.mode != "RGB": raise TypeError("Require an format RGB image") width, height = image.size dut = self.dut # Local reference to save lookup clk_edge = RisingEdge(dut.clk) # Recycle objects for efficiency yield clk_edge # Reset the dut first dut.rst <= 1 yield clk_edge dut.rst <= 0 dut.end_of_file_signal <= 0 pixels = image.load() for y in xrange(0,height,8): for x in xrange(0,width,8): dut.enable <= 1 self.log.debug("Sending block X% 4d/% 4d, Y% 4d/% 4d" % ( x, width, y, height)) if y >= height-8 and x >= width-8: dut.end_of_file_signal <= 1 for y_block in xrange(8): for x_block in xrange(8): # If the image isn't a multiple of 8 pixels we # repeat the edge values (see Readme.doc) x_ofs = min(x+x_block, width-1) y_ofs = min(y+y_block, height-1) r,g,b = pixels[x_ofs, y_ofs] dut.data_in <= (b<<16 | g<<8 | r) yield clk_edge dut.end_of_file_signal <= 0 for i in xrange(33): yield clk_edge dut.enable <= 0 yield clk_edge def compare(i1, i2): def compare(i1, i2): """ """ Loading