calyx
calyx copied to clipboard
Bit splitting in Calyx.
Sometimes we only want to access a certain subset of the bits in a multi-bit bus. std_slice provides limited functionality in this regard.
For example, in SV, we could access the ith bit of in with: in[i].
Following this, a Calyx interface for a single-bit split primitive might look like:
module std_split #(
parameter WIDTH,
parameter INDEX_SIZE
) (
input wire logic [WIDTH-1:0] in,
input wire logic [INDEX_SIZE-1:0] index,
output logic out;
);
assign out = in[index];
`ifdef VERILATOR
always_comb begin
if (index < 0 || index > (WIDTH - 1))
$error(
"std_split: Index is outside the bounds of the WIDTH.\n",
"WIDTH: %0d", WIDTH,
"index: %0d", index
);
end
`endif
endmodule
This would require N individual std_splits to access each bit in a N-bit bus.
For example, we could also add an OUT_WIDTH if we want to split off a subset of bits with size > 1. We would then also need to provide a begin_index and end_index.
This also begs the question, perhaps we should differentiate between "compile-time"* splits and "runtime" splits? For example,
if I know I will always want to access the first and second bit, then this would simply be a two wire split off the bus. I would imagine this is a bit more complicated when the index (or indices) are determined at runtime.
*There's probably better terminology that fits here
Yes! It does seem like static vs. dynamic slices should probably be different primitives altogether. Static slices would get their indices as meta-level parameters, while dynamic slices would get their inputs as input wires. A good reason to separate them is that their costs are very different: static slices are effectively "free" in hardware, while dynamic slices are not.
Would it suffice to make std_slice take a begin_index and end_index instead of just the out_index? For reference, std_slice does this:
assign out = in[OUT_WIDTH-1:0];
@cgyurgyik can add some context on where you were trying to use this?
I don't recall (TCAM maybe?), but I imagine it would be useful to make certain wires of a bus available statically. I mean a concrete example would be ISA parser, but I don't think Calyx will target that.
For example,
[0][0][1][1] // Some 4-bit value
| | |
a = std_reg(2);
b = std_reg(2);
a = bit_slice(0, 2); // Statically known
b = bit_slice(2, 4);
Edit: A next step would be allowing arbitrary splicing, e.g. a=bit_slice(0, 3, 4) // Bits 0, 3, and 4.
@rachitnigam I will like to tackle this issue. I suppose the plan is to go with your suggestion here?
Hi, @anthonyabeo—I think that would be a good place to start! We would probably want to create a new, different primitive (to avoid conflicts with code that currently uses std_slice), and then consider migrating code over to it that could use the new primitive?
@sampsyo sure, that sounds good. I'll put something together and revert.