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