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

Any interest in a COBS Encoder/Decoder? #21

Open
fischermoseley opened this issue Nov 8, 2024 · 3 comments
Open

Any interest in a COBS Encoder/Decoder? #21

fischermoseley opened this issue Nov 8, 2024 · 3 comments
Labels

Comments

@fischermoseley
Copy link

Hello! I wanted to ask if there was any interest from the maintainers in adding a COBS encoder and decoder to this library.

I've been poking around with a very basic verison at fischermoseley/cobs that is absolutely in need of further development and definitely not ready for a PR - but if it would be an appropriate addition to amaranth-stdio I'm happy to develop it towards such. Otherwise I can keep it as a standalone project. No pressure either way, of course.

@whitequark
Copy link
Member

Sounds good to me, COBS is very useful. We could prototype its use in Glasgow, perhaps.

@fischermoseley
Copy link
Author

Great, thank you! I'll see if I can have a PR ready in the next few weeks.

@zyp
Copy link
Contributor

zyp commented Nov 9, 2024

I looked at your encoder and I have a couple of tips regarding improving throughput.

If I'm reading it right, your encoder will run at a fixed 50% throughput (not counting flow control), because it'll sit half the time in the SFZ state counting the number of bytes that doesn't need to be escaped, and half the time in the COB state outputting bytes.
The latency from counting bytes is unavoidable, but you can reach 100% throughput if you do the counting in parallel with the outputting.

For inspiration, here is a COBS encoder I wrote in Migen that I've been planning to eventually port to Amaranth.

In my implementation, a group is a set of contiguous unescaped bytes. The GroupSplitter block outputs the unescaped bytes to the data stream while counting and outputting the length to the len stream. Buffering the streams individually lets the GroupCombiner grab the len first to output the overhead byte, before outputting a group from the data stream.

The data buffer needs to be deep enough to hold a maximum sized group since the GroupCombiner won't start to consume a group before it has the length and the GroupSplitter won't output the length before all the data is out. Making the len buffer equally deep ensures that the GroupSplitter can keep busy while the GroupCombiner is still outputting even if you get a run of short groups following a long group. This ensures that the encoder is able to achieve and sustain full throughput regardless of the data it's fed.

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

No branches or pull requests

3 participants