gary/lib/PackUnpack.bsv

78 lines
2.8 KiB
Plaintext
Raw Permalink Normal View History

package PackUnpack;
import Vector::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import ClientServer::*;
// mkPacker makes a server that converts data_in values into one or
// more data_out values, both of which must be in the Bits
// typeclass. The packing is implemented by taking the bit
// representation of data_in and striping it across as many data_outs
// as needed to preserve all the bytes. If data_in is not an exact
// multiple of data_out, the final data_out is padded with zeros.
module mkPacker(Server#(data_in, data_out))
provisos(Bits#(data_in, data_in_bits),
Bits#(data_out, data_out_bits),
Div#(data_in_bits, data_out_bits, data_out_elts),
Min#(data_out_elts, 1, 1),
Log#(TAdd#(data_out_elts, 1), data_out_elts_cnt),
Add#(data_in_bits, _pad, TMul#(data_out_elts, data_out_bits)));
let data_out_elts = valueOf(data_out_elts);
Reg#(Vector#(data_out_elts, data_out)) vals_out <- mkRegU();
Reg#(UInt#(data_out_elts_cnt)) num_vals <- mkReg(0);
FIFOF#(data_out) out <- mkBypassFIFOF();
rule push_out (num_vals > 0);
out.enq(vals_out[0]);
vals_out <= shiftOutFrom0(unpack(0), vals_out, 1);
num_vals <= num_vals-1;
endrule
interface Put request;
method Action put(di) if (num_vals == 0);
vals_out <= reverse(unpack(extend(pack(di))));
num_vals <= fromInteger(data_out_elts);
endmethod
endinterface
interface response = toGet(out);
endmodule
// mkUnpacker makes a server that converts one or more data_in values
// into a data_out value. Both data_in and data_out must be in the
// Bits typeclass. The unpacking is implemented by concatenating the
// bit representation of consecutive data_in values until enough bits
// have been accumulated to represent one data_out. If data_out is not
// an exact multiple of data_in, the unneeded upper bits of the final
// data_in are discarded.
module mkUnpacker(Server#(data_in, data_out))
provisos(Bits#(data_in, data_in_bits),
Bits#(data_out, data_out_bits),
Div#(data_out_bits, data_in_bits, data_in_elts),
Min#(data_in_elts, 1, 1),
Log#(TAdd#(data_in_elts, 1), data_in_elts_cnt),
Add#(data_out_bits, _pad, TMul#(data_in_elts, data_in_bits)));
Reg#(Vector#(data_in_elts, data_in)) vals_in <- mkRegU();
Reg#(UInt#(data_in_elts_cnt)) num_vals <- mkReg(0);
FIFOF#(data_out) out <- mkBypassFIFOF();
rule push_out (num_vals == fromInteger(valueOf(data_in_elts)));
out.enq(unpack(truncate(pack(vals_in))));
num_vals <= 0;
endrule
interface Put request;
method Action put(di) if (num_vals < fromInteger(valueOf(data_in_elts)));
vals_in <= shiftInAt0(vals_in, di);
num_vals <= num_vals+1;
endmethod
endinterface
interface response = toGet(out);
endmodule
endpackage