Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding RLE-core module for JPEG encoder #2

Merged
merged 12 commits into from Aug 31, 2017
Merged

Conversation

ishan98
Copy link

@ishan98 ishan98 commented Aug 20, 2017

This includes the addition of RLE module to the JPEG encoder with Test Bench :

RLE module :
The module takes an input_data and generate an output compressing all the zeros within two non-zero values in the form of runlength, which is used to compress the image.
RLEmain.py :
Connect the input to both the RLEcore and the Entrophycoder.
RLEcore.py :
Takes the input and calculate the runlength that is number of zeros between two non-zero values.
Entrophycoder.py :
Takes the input of the non-zero amplitude and calculate the number of bits required to store that amplitude.

Test Bench :
new_rlemain_tb.py
new_entrophycoder_tb.py
new_rlecore_tb.py
This three modules are made for the testing of the RLEmain, Entrophycoder and RLEcore respectively.

Common.py :
Added input_data for testing the RLE module and various functions such as setdata() to get the input and output in the required format.

After adding the above changes, the resultant repository contains the working model of the RLE module along with the test suite.


from litejpeg.core.common import *

"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be the first thing in the file. Can you move it there?

Parameters:
-----------
sink : Get the input from the other modules.
The input is the modulus of the input.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input is the modulus of the input? I'm not sure what that means?


# For calculating the size.

# Storing the size in the input_data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your comments should concentrate on why you are doing something. The code explains how you are doing it.

For example, why do you want to iterate over different values from 1 to 12? Any python programmer understands that for i in range(12) iterates over the values 0->11.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

This module will connect the Entropycoder datapath with the input
and output either from other modules or from the Test Benches.
The input is been taken from the sink and source and is been transferred to
the Entropycoder datapath by using read and write count.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what does the Entropycoder actually do?

self.comb += source.data.eq(size)


class Entropycoder(PipelinedActor, Module):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EntropyCoder

]


class Runlength(PipelinedActor, Module):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RunLength

test/common.py Outdated
testing.
"""
def __init__(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do these values come from? What are they for?

Why is red_pixels_1, self.red_pixels_1 while everything else is not assigned to self?

test/common.py Outdated
for i in range(64):
temp=self.data[i]
Amplitude = temp%4096
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amplitude

test/common.py Outdated
for i in range(64):
temp=self.data[i]
Amplitude = temp%4096
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These numbers seem important. Why are you doing a %4096 and a %16 below.

@@ -0,0 +1,66 @@
# This is the module for testing the RLEmain.

# !/usr/bin/env python3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# !/usr/bin/env python3 must be the first line in the file.

Copy link
Contributor

@mithro mithro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another round of comments. You are getting closer, I think we can probably get this merged today!


Parameters:
-----------
sink : Get the input from the other modules.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it want the input from the other modules?

I should be able to understand what the other module this is being connected and why is that a separate module.

-----------
sink : Get the input from the other modules.
source : Give the output to the other modules.
input_data : modulus of input of the matrix.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What matrix? I assume the matrix is coming from somewhere else?

It contains the steps for the Entropycoder to calculate the bits for the
Amplitude to store.

Parameters:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are actually Attributes not Parameters.

Parameters is pretty much a synonym for "argument". For example def foo(a, b) has 2 parameters a & b.

"""
EntropyDatapath :
------------------
It contains the steps for the Entropycoder to calculate the bits for the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entroycoder case is wrong.

write_fsm.act("WRITE_INPUT",
sink.ready.eq(1),
If(sink.valid,
If(write_count == 63,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If(write_count == (BLOCK_COUNT-1), and then define BLOCK_COUNT to be 64 (and use it elsewhere).

Parameters:
-----------
sink : 12 bits
Recieves an input of 12 bits either from test bench or from
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What to the 12 bits of data represent?

sink : 12 bits
Recieves an input of 12 bits either from test bench or from
other modules.
source : 21 bits
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do the 21 bits represent?

datapath_latency = 3


class RLEmain(PipelinedActor, Module):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RLEmain should be RLEMain right?

test/common.py Outdated
These class is been created in order to store the value or the matrix which
are been used to test the RLE module.
The matrix are from github repositories for the purpose of input for
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which github repositories? There are plenty out there... How do I check that you haven't made a mistake in the matrixes?

test/common.py Outdated
# number therefore in order to extracts the two we take the modulus
# by 4096 to get last 12 bits and than shift and than again extracts
# the next 4 representing runlength.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't explain why we want to modulus by 4096? Is this the size of the data? Is it got something to do with runlength?

Copy link
Contributor

@mithro mithro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there for merging this pull request!

-----------
sink : Get the input from the Entrophycoder.
source : Give the output to the Entrophycoder.
input_data : for temporary storing the value of input, used
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input_data / get_data / size are all not attributes. Attributes are things stored on self

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

EntropyDatapath :
------------------
It contains the steps for the EntropyCoder to calculate the bits for the
Amplitude to store.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is amplitude capitalized here?

A better description would be something like Calculate the bit value for the amplitude using EntropyCoder.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE


Attributes:
-----------
sink : Get the input from the Entrophycoder.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things here;

  • Capitalization should always match. If the class is called EntrophyCoder you should always refer to it as EntrophyCoder never entrophyCoder or Entrophycoder.
  • "Get the input from the Entrophycoder." is not informative. It should be something like "Accepts data which is encoded in huffman entropy foo bad, such as the output from the EntrophyCoder class." -- The difference is that it tells me what the data is.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

# number of bits required to store the input_data.
for i in range(12):
self.sync += get_data[i].eq(input_data >> i)
for i in range(12):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for i in range(11, -1, -1):

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't not able to understand this one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

the amplitude.

Attributes :
------------
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indenting of the below things in a bit weird...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

self.source = source = stream.Endpoint(
EndpointDescription(block_layout(17)))

# Adding PipelineActor to provide additional clock for the module.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need an additional clock?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

RLE core as the output will contain the amplitude in the last 12 bits along
with the number of bits to store the amplitude as the next 4 bits and
finally the RunLength for the next 4 bits.
All these information is been synchronized once by the RLEmain and than
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"and then"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

test/common.py Outdated
"""
These class is been created in order to store the value or the matrix which
are been used to test the RLE module.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class stores the value of the matrixes used to test the RLE module.

These matrixes were taken from [`rle_test_inputs.py` in cfelton's test_jpeg code](https://github.com/cfelton/test_jpeg/blob/master/test/rle_test_inputs.py).

The matrix is an example of what the quantization module might produce.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

self.data = data
for i in range(64):
temp=self.data[i]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data we get contains amplitude and run length as a single number. In order to extract the values we use mod 4096 to get the last 12bits and then shift to extract the next 4 representing the run length.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

input to the RLE core and the output is been printed and compared
with the one from the reference modules.
In this way the result from the RLEcore is been verified.
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module takes a matrix containing 64 blocks of XXXX and verifies the RLECore produces the same output as the reference data.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

# To keep track over which value of the matrix is under process.
write_count = Signal(6)

# For tracking the data adress.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW For migen we normally wrap the code like this;

       self.sync += \
            If(write_clear,
                write_count.eq(0)
            ).Elif(write_inc,
                write_count.eq(write_count + 1)
            )

IE

  If(<condition>,
  <4 spaces>statement
  ).Elif(<condition>,
  <4 spaces>statement1,
  <4 spaces>statement2,
  ).Else(
  <4 spaces>statement1,
  <4 spaces>statement2,
  )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE to most of the places.

Copy link
Contributor

@mithro mithro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Merging.

@mithro mithro merged commit 2bd67e5 into litex-hub:master Aug 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants