Pytorch에서 quantization을 구현 코드를 verilog로 변환하기 위해서는 fixed point scaler 연산이 필요하다.
연산에 있어서 필요한 여러 개념들이 있는데 아래 블로그 글을 참고하면 좋다.
2023.09.05 - [Digital Logic/Verilog] - [Verilog] Fixed point Scaler 연산 (Quantization - binary 연산)
비트 수가 다른 bias와 덧셈 연산
이번에는 convolution 연산 후에 bias를 더해주는 작업을 한다.
여기서 주의할 점은 Q_conv와 bias의 bit 수가 다르다.
정확하게는 둘의 bit수를 동일하게 맞추어 메모리에 저장할 수 있지만 값이 더 적은 bias는 그럴 필요가 없다.
메모리 용량(혹은 버퍼)을 많이 차지하는 것은 결코 좋은 일이 아니기에 더 적은 bit를 할당한다.
그렇게 메모리에서 불러온 둘을 사칙 연산해야 하는데 이때 발생하는 이슈가 있다.
pytorch 코드는 아래와 같다.
Q_w, S_w = self.quant_weight(self.weight) # Quantized Integer, Float Scale
Q_conv = nn.functional.conv2d(Q_x, Q_w, None, self.stride, self.padding, self.dilation, self.groups)
// scaling
Q_conv = Q_conv * S_y
// bias
Q_conv = Q_conv + bias
// rounding
Q_conv = torch.round(Q_conv)
// clamping
Q_conv = torch.clamp(Q_conv, -self.qa.a_qmax, self.qa.a_qmax)
비트 수가 다른 두 파라미터를 verilog로 구현하기 위해서는 아래 조건을 만족해야 한다.
- 비트 수를 맞추기 위해 sign extension하고
- fraction 위치를 맞추기 위해 shift 함
module ConvScalerUnit #(
parameter INP_WL = 40,
parameter RF_WL = 16, // Register File (bias)
parameter SCALE_WL = 14,
parameter SCALE_FL = 13
)(
input wire clk,
input wire reset,
input wire [INP_WL-1:0] din,
output wire [INP_WL-1:0] dout
);
wire [INP_WL-1:0] psum_bias;
// rf_rd_data: bias value (16bit)
// scaling psum
wire [SCALE_WL-1:0] s_y;
assign s_y = 14'b00_0000_0011_1001; // 0.00695801 // sign bit
wire [INP_WL+SCALE_WL-1:0] scaled_psum = $signed(din) * $signed(s_y); //it's better that both are casted to $signed.
// convert from 16bit to 54bit
wire [INP_WL+SCALE_WL-1:0] bias_54bit; // (40 + 14)
// sign extension and left shift
assign bias_54bit = {{(INP_WL+SCALE_WL-RF_WL+1){rf_rd_data[RF_WL-1]}}, rf_rd_data[RF_WL-2:0]} <<< 7; //sign extension n shift
// add
wire [INP_WL+SCALE_WL-1:0] psum_bias_54 = $signed(scaled_psum) + $signed(bias_54bit);
// round
wire [INP_WL-1:0] round_psum_bias;
SignedRoundSaturate #(
.IN_WLEN(INP_WL+SCALE_WL),
.OUT_WLEN(INP_WL+SCALE_WL-SCALE_FL),
.IN_FLEN(SCALE_FL)
) ROUND_PSUM_BIAS1 (
.din(psum_bias_54),
.dout(round_psum_bias)
);
// 41bit -> 16bit clipping
wire [OUT_WL-1:0] clip_psum = $signed({round_psum_bias[INP_WL-1], round_psum_bias[OUT_WL-2:0]});
// clamp
wire [OUT_WL-1:0] clamp_max = 16'd65535;
assign psum_scaled = (clip_psum < 0) ? 0 : (clip_psum > clamp_max) ? clamp_max : clip_psum; // pytorch code: -2^15 ~ 2^15
endgenerate
그림으로 묘사하면 다음과 같다.
반응형
'Digital Logic > Verilog' 카테고리의 다른 글
[Verilog] Fixed point Scaler 연산 (Sign 연산 - right shift) (0) | 2023.09.09 |
---|---|
[Verilog] Fixed point Scaler 연산 (Quantization - sign 곱셈/덧셈 연산) (0) | 2023.09.06 |
[Verilog] Fixed point Scaler 연산 (Quantization - binary 연산) (0) | 2023.09.05 |
Verilog 설계에서 중요한 존재들 - Counter (카운터) (0) | 2021.05.10 |
Verilog 설계에서 중요한 존재들 - 순차 논리 회로(Sequential logic circuits)_#Flip-Flop (0) | 2021.05.09 |
댓글