Introducing PCB-rs : Making it easier to write hardware
Tags: rust, showdev, beginners, computerscience
Published: 2022-04-08 14:20:04

Remember the [post I wrote about 2 months ago](https://dev.to/yjdoc2/what-is-keeping-you-from-dabbling-in-writing-hardware--1k1e) ? Asking why you don't write much hardware?
In it I said I was writing a library to make it easier. Well, I have completed the initial release version of it :tada: :tada: :tada:

---

Quick note : I don't usually ask this, but please share this article, or directly the library on your socials or such! I have spent quite some time on developing it, and I really want people who can benefit from this to use this. Your share might help this reach someone who needs it. Thank you!

---

## So, what is it?

Well, I'm happy to share with you : `pcb-rs` ! This is a library which will make it much easier for you to write hardware components, and simulate them. It does this by giving you two proc-macros, which you can use with your run-of-the-mill `struct`s and it will generate the interface implementation for you!

## Why ???

Because I want to make it easier for people who wish to explore hardware to do so. This does not aim to be the perfect and most-accurate-simulation ever ; or try to replace VHDL, (because it does not). This aims to be a rung in the ladder from high-level programming language to hardware level. That way those who are just starting to explore it, will have to jump a little less height : they can still work in comfort of Rust, but can have the taste of things that one has to consider when designing hardware.

It is choose-your-own-difficulty hardware design!

## Show, don't tell

Here I'm showing how you can write a simple 256-byte RAM as a hardware component using my library :
```rust
use pcb_rs::Chip;

#[derive(Chip)]
pub struct Memory {
    #[pin(input)]
    addr: u8,
    #[pin(io, io_latch)]
    data: Option<u8>,
    #[pin(input)]
    is_active: bool,
    #[pin(input)]
    is_read: bool,

    io_latch: bool,
    pub mem: [u8; 256],
}

impl Chip for Memory {
    fn tick(&mut self) {
        if !self.is_active {
            self.io_latch = true;
            return;
        }
        if self.is_read {
            let addr = self.addr as usize;
            let data = self.mem[addr];
            self.data = Some(data);
            self.io_latch = false;
        } else {
            let addr = self.addr as usize;
            let val = self.data.unwrap();
            self.mem[addr] = val;
        }
    }
}
```

Here the `derive(Chip)` is my prco-macro which automatically implements the required traits for your chip, and you just have to write `impl Chip` which defines the processing logic of your chip.

Thus in about ~33 lines, we have a working RAM. This is also modular - it can be used with other components, such as CPU :tada: :tada: And pcb-rs also provides another macro for that :
```rust
pcb!(PCB{
    chip cpu;
    chip mem;

    cpu::addr_bus - mem::addr;
    cpu::data_bus - mem::data;
    cpu::mem_active - mem::is_active;
    cpu::read_mem - mem::is_read;

});
```
Yep. That's it. That's all you have to define to interface a CPU and the RAM. the `pcb!` macro will parse this, derive the logic for validating the chips given to it , derive the logic to verify the pin connection, derive the logic for passing values from one chip to another, and write the builer and pcb struct.
Now to actually place the RAM and CPU pins in it:
```rust
let mem = Box::new(Memory::new());
let cpu = Box::new(CPU::new());
let temp::PCBBuilder = PCBBuilder::new();
let temp = temp.add_chip("cpu", cpu).add_chip("mem", mem);
let mut pcb:PCB = temp.build().unwrap();
pcb.tick();
```
This will place the chips in the builder, validate that correct chips have been placed, and give you the PCB struct, which contains all the running logic after calling build. The PCB itself will have the `tick()` method, which will run your chips.

And you know what, this itself is modular! You can use such chips as part of some other PCB, and so on :tada: :tada:

## Wait, you're telling me this is easier?

Well, yeah! This will allow you to write Hardware components from comfort of Rust, before you get into something more complex as VHDL. Also you have to write just the struct and annotate what members you want to use as pins, and then write the processing logic for the chip. Everything else is derived by the macro for you. 

Same for pcb, you just have to define the chips, connections and what pins you want to expose to others, rest, including the actual struct, will be derived by the macro.

## Ok, show me more 

I know this is pretty different that what many of you might be usually doing. So, as examples, I have written several components that range from pretty basic to a bit complex.

You know what's more? As Rust can compile to WASM, I have also done that and have made a web interface for the examples. You can run them directly from your browsers. Check it out at [https://yjdoc2.github.io/pcb-rs-examples/](https://yjdoc2.github.io/pcb-rs-examples/).
Currently the examples consist of :
- Basic gates such as Not, And, Or, Xor [wikipedia](https://en.wikipedia.org/wiki/Logic_gate)
- Ripple carry adder [wikipedia](https://en.wikipedia.org/wiki/Adder_(electronics)#Ripple-carry_adder)
- Look ahead Carry adder [wikipedia](https://en.wikipedia.org/wiki/Carry-lookahead_adder)
- SR, D, T, JK Latches [wikipedia](https://en.wikipedia.org/wiki/Flip-flop_(electronics))
- Straight and Twisted Ring counters [wikipedia](https://en.wikipedia.org/wiki/Ring_counter)
- CPU and PCB example which I showed above

You can try all these right in your browser, at [https://yjdoc2.github.io/pcb-rs-examples/](https://yjdoc2.github.io/pcb-rs-examples/).

I made these particular examples, as these are usually a part of basic hardware/electronics course, so these will be a good taste of how pcb-rs library can be used for that.

### Links, Links and Links

So,
The library :
{% embed https://github.com/YJDoc2/pcb-rs %}
The examples :
{% embed https://github.com/YJDoc2/pcb-rs-examples %}
The Web interface for the examples : [https://yjdoc2.github.io/pcb-rs-examples/](https://yjdoc2.github.io/pcb-rs-examples/).

## And ...?

Go Check It Out!!! Try it out in your own projects, share the projects and let me know how are you using it!

And as I said in the start, I don't usually ask this, but please consider sharing this. I really want this to help people who want to get into hardware. Your share will help this reach more people. 

Also if you think this is interesting, consider starring it on GitHub. That might also help getting this more attention.

Let me know in comments your thoughts and reviews for this.

Thanks a lot for reading! 

---

Note : header image is taken from google images search, and is not mine.