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

Cmv12k remapper #34

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Cmv12k remapper #34

wants to merge 3 commits into from

Conversation

rroohhh
Copy link
Member

@rroohhh rroohhh commented Apr 29, 2024

This adds a remapper, that reorders the pixels coming from the cmv12k to follow the ImageStream convention, though notably with more than a single pixel per cycle.
Untested in hw, but tested in sim.

@rroohhh rroohhh requested a review from anuejn April 29, 2024 13:55
Copy link
Member

@anuejn anuejn left a comment

Choose a reason for hiding this comment

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

Very, very nice work. I cant say that I understand everything fully bug I roughly get it, thatks to your very nice comments :).

My remarks are a bit bike-shed-y, sorry for that 🙈

# | 2 | 2 | 18 | | 4082 |
# | ... | | | | |
# | 7 | 15 | 31 | | 4095 |
# Note, that we have half as many output channels as input channels. We provide valid data on every clock cycle. (Almost, there will be some cycles where the data is not valid).
Copy link
Member

Choose a reason for hiding this comment

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

Can I haz some line wrapping for that?

# Concretely this produces a pattern like this (for `n_channels = 8`)
# The sensor output is sturctured into bursts of 128 pixels, so we need to pay attention to the burst boundaries, as after a burst some overhead cycles take place
# channel written:
# | clock -> | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Copy link
Member

Choose a reason for hiding this comment

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

I do not understand what bram v is

Copy link
Member

Choose a reason for hiding this comment

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

also why does this start with clock 2

# And a single channel gets 1 pixel per clock cycle, for a total of 4096 / n_channel pixels. For example for 8 channels (per side): 512 pixels.
# This means we read out all of the 512 pixels in 32 cycles, so we can start the read out process with 32 pixels left.
# The next row will start soon after the first, so we store two rows and ping pong the buffers
# TODO(robin): this is fucked because of OH, no?
Copy link
Member

Choose a reason for hiding this comment

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

???

"""Remaps one output port (if top and bottom outputs of the cmv12k are used, instantiate this twice!) to provide a linear output.
def __init__(self, input: ImageStream, n_bits=12, two_sided_readout=True):
assert two_sided_readout == True, "single sided readout is not supported"
assert n_bits == 12, "bit depth other than 12 is not supported"
Copy link
Member

Choose a reason for hiding this comment

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

nice way to do this :)

class Cmv12kPixelRemapper(Elaboratable):
"""Remaps one output port (if top and bottom outputs of the cmv12k are used, instantiate this twice!) to provide a linear output.
def __init__(self, input: ImageStream, n_bits=12, two_sided_readout=True):
Copy link
Member

Choose a reason for hiding this comment

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

why is the input an image stream though?

Copy link
Member

Choose a reason for hiding this comment

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

and are input and output domains the same?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, input and output domains are the same.
This is a ImageStream, because the cmv12k rx core outputs an ImageStream, I just built something that plugs into this.
But of course we could change this. We do not have a "clear" definition of ImageStream currently and the rx core also output line_last and frame_last, so it kind of makes sense to have its output be an ImageStream, but of course the pixel ordering is a bit "weird".

wr_enable = Signal()

# write address, write data and rea data is independent for each memory.
wr_address = [Signal(self.addr_width, name=f"wr_address_{i:02}") for i in range(self.n_mem)]
Copy link
Member

Choose a reason for hiding this comment

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

bikeshed: maybe we should rather store the ports here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, don't have a strong feeling either way.

# first step: double up the input words. We want to do this with as few FFs as possible. So
# we use the knowledge that we write the first fourth of channel immediately and only need to store a single pixel
# for the middle fourths we need to store two pixels, as we need to wait atleast one cycle more
# for the last forth we need to store three pixels, as a new one comes in before we can write the ol pixel data
Copy link
Member

Choose a reason for hiding this comment

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

ye good 'ol pixel data

channel_number = rd_address_delayed[bits_for(self.channel_block_size - 1) :]

# for debugging
m.d.comb += Signal(16, name="channel_number").eq(channel_number)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe do that directly above (as it also yields nicer rtlil?)

@pytest.mark.parametrize("channels_per_side", [4, 8, 16, 32])
def test_cmv12k_pixel_remapper(channels_per_side):
platform = SimPlatform()
# fixed for now
Copy link
Member

Choose a reason for hiding this comment

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

???

@@ -24,7 +24,8 @@ def __init__(self, filename=None):
caller_path = ""
stack = inspect.stack()
for frame in stack[1:]:
if "unittest" in frame.filename:
print(frame, frame.filename)
Copy link
Member

Choose a reason for hiding this comment

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

🖨️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants