oc_jpegencode  1.0
JPEGencoder
interfaces.py
Go to the documentation of this file.
1 """
2 A driver and monitor to abstract the interface to the JPEG encoder
3 """
4 
5 import io
6 from PIL import Image
7 
8 import cocotb
9 from cocotb.triggers import RisingEdge, ReadOnly
10 from cocotb.drivers import Driver
11 from cocotb.monitors import Monitor
12 
13 _jpeg_header = open("header.bin", "r").read()
14 
15 class JpegMonitor(Monitor):
16 
17  def __init__(self, dut, **kwargs):
18  self.dut = dut
19  Monitor.__init__(self, **kwargs)
20 
21  @cocotb.coroutine
22  def _monitor_recv(self):
23  """Creates an Image object from the output of the DUT"""
24  data = ""
25 
26  clkedge = RisingEdge(self.dut.clk)
27  ro = ReadOnly()
28  while True:
29  yield clkedge
30  yield ro
31  if self.dut.data_ready.value:
32  data += self.dut.JPEG_bitstream.value.buff
33  if self.dut.eof_data_partial_ready.value:
34  f_obj = io.BytesIO(_jpeg_header + data + "\xff\xd9")
35  img = Image.open(f_obj)
36  self.log.info("Recovered image %s of %dx%d in mode %s" % (
37  img.format, img.size[0], img.size[1], img.mode))
38  yield clkedge
39  self._recv(img)
40  data = ""
41 
42 
43 class ImageDriver(Driver):
44 
45  def __init__(self, dut):
46  self.dut = dut
47  Driver.__init__(self)
48 
49  @cocotb.coroutine
50  def _driver_send(self, image, **kwargs):
51  """
52  Send an image into the DUT. Image should be in RGB format and a
53  multiple of 8 pixels in both width and height
54 
55  Args:
56 
57  image (PIL.Image) image to send into the dut
58  """
59  if image.mode != "RGB": # pragma: no cover
60  raise TypeError("Require an format RGB image")
61 
62  width, height = image.size
63  dut = self.dut # Local reference to save lookup
64  clk_edge = RisingEdge(dut.clk) # Recycle objects for efficiency
65 
66  yield clk_edge # Reset the dut first
67  dut.rst <= 1
68  yield clk_edge
69  dut.rst <= 0
70  dut.end_of_file_signal <= 0
71 
72  pixels = image.load()
73 
74  for y in xrange(0,height,8):
75  for x in xrange(0,width,8):
76  dut.enable <= 1
77 
78  self.log.debug("Sending block X% 4d/% 4d, Y% 4d/% 4d" % (
79  x, width, y, height))
80 
81  if y >= height-8 and x >= width-8:
82  dut.end_of_file_signal <= 1
83 
84  for y_block in xrange(8):
85  for x_block in xrange(8):
86  # If the image isn't a multiple of 8 pixels we
87  # repeat the edge values (see Readme.doc)
88  x_ofs = min(x+x_block, width-1)
89  y_ofs = min(y+y_block, height-1)
90 
91  r,g,b = pixels[x_ofs, y_ofs]
92  dut.data_in <= (b<<16 | g<<8 | r)
93  yield clk_edge
94  dut.end_of_file_signal <= 0
95 
96  for i in xrange(33):
97  yield clk_edge
98 
99  dut.enable <= 0
100  yield clk_edge
101 
def _monitor_recv( self)
Definition: interfaces.py:22
def __init__( self, dut, kwargs)
Definition: interfaces.py:17
def __init__( self, dut)
Definition: interfaces.py:45
def _driver_send( self, image, kwargs)
Definition: interfaces.py:50