📄 iviterbi.bsv
字号:
Vector#(ConvOutSz, VMetricSum) addMetrics = newVector; for (Integer i = 0; i < conv_out_sz; i = i + 1) addMetrics[i] = zeroExtend(getMetric(expBits[i]) ^ recMetrics[i]); // |expMetric[i] - recMetrics[i]| return inSum + fold(\+ , addMetrics); endfunction RadixEntry#(tEntry_T) outVec = newVector;// MetricLUT metricLUT = getMetricLUT; Bit#(TSub#(VStateSz, ConvInSz)) prevStatePrefix = tpl_1(split(tpl_1(inVec[0]))); // all input states must have the same prefix RadixEntry#(tEntry_T) sumVec = newVector; // for calculating next result for (Integer in_bits = 0; in_bits < radix_sz; in_bits = in_bits + 1) begin Bit#(ConvInSz) inBits = fromInteger(in_bits); VState nextState = {inBits, prevStatePrefix}; for (Integer prev_state_suffix = 0; prev_state_suffix < radix_sz; prev_state_suffix = prev_state_suffix + 1) begin// Bit#(KSz) lutIdx = (zeroExtend(nextState) << fromInteger(conv_in_sz)) + fromInteger(prev_state_suffix); sumVec[prev_state_suffix] = tuple3(tpl_1(inVec[prev_state_suffix]), // same calcVMetricSum(tpl_2(inVec[prev_state_suffix]), getConvEncOutput(tpl_1(inVec[prev_state_suffix]), inBits),// metricLUT[lutIdx], inMetrics), // add tpl_3(inVec[prev_state_suffix])); // same end let minRadix = fold(chooseMin, sumVec); let nextSum = tpl_2(minRadix); let nextT = getNextTEntry(tpl_1(minRadix), nextState, tpl_3(minRadix)); outVec[in_bits] = tuple3(nextState, nextSum, nextT); end // for (Integer in_bits = 0; in_bits < radix_sz; in_bits = in_bits + 1) return outVec;endfunction // unmatched end(function|task|module|primitive) function FwdEntry#(tEntry_T) fwdCompute(FwdEntry#(tEntry_T) inVec, VInType inMetricsV, function tEntry_T getNextTEntry(VState prevState, VState nextState, tEntry_T oldTEntry)); FwdEntry#(tEntry_T) outVec = inVec; Integer no_radix = fwd_entry_sz / radix_sz; for (Integer stage = 0; stage < fwd_steps; stage = stage + 1) begin RadixEntry#(tEntry_T) radixVec = newVector; if (stage != 0) outVec = readSelect(conv_in_sz, stage, 0, outVec); // permute if not the first step for (Integer radix_idx = 0; radix_idx < no_radix; radix_idx = radix_idx + 1) begin for (Integer k = 0; k < radix_sz; k = k + 1) radixVec[k] = outVec[radix_idx*radix_sz+k]; radixVec = radixCompute(radixVec, inMetricsV[stage], getNextTEntry); for (Integer k = 0; k < radix_sz; k = k + 1) outVec[radix_idx*radix_sz+k] = radixVec[k]; end // for (Integer j = 0; j < noOfRadix; j = j + 1) if (stage != 0) outVec = reverseReadSelect(conv_in_sz, stage, 0, outVec); // reverse the permutation if not the first step end // for (Integer i = 0; i < fwd_steps; i = i + 1) return outVec; endfunction // ForwardEntry// output the state with the minimum value and the new outentryfunction Tuple3#(VState, tEntry_T, VRegsOutEntry#(tEntry_T)) vRegsOutCompute(VRegsOutEntry#(tEntry_T) inVec, VInType inMetricsV, function tEntry_T getNextTEntry(VState prevState, VState nextState, tEntry_T oldTEntry)); VRegsOutEntry#(tEntry_T) outVec = newVector; Integer no_fwd_unit = vregs_out_sz / fwd_entry_sz; FwdEntry#(tEntry_T) fwdVec = newVector; for (Integer fwd_idx = 0; fwd_idx < no_fwd_unit; fwd_idx = fwd_idx + 1) begin for (Integer k = 0; k < fwd_entry_sz; k = k + 1) fwdVec[k] = inVec[fwd_idx * fwd_entry_sz + k]; fwdVec = fwdCompute(fwdVec, inMetricsV, getNextTEntry); for (Integer k = 0; k < fwd_entry_sz; k = k + 1) outVec[fwd_idx * fwd_entry_sz + k] = fwdVec[k]; end // for (Integer j = 0; j < noOfRadix; j = j + 1) let minPrimEntry = fold(chooseMin, outVec); VState minState = tpl_1(minPrimEntry); tEntry_T minTEntry = tpl_3(minPrimEntry); return tuple3(minState, minTEntry, outVec); endfunction // ForwardEntry(* noinline *)function Tuple3#(VState, VTrellisEntry, VRegsOutEntry#(VTrellisEntry)) vRegsOutComputeTBPath(VRegsOutEntry#(VTrellisEntry) inVec, VInType inMetricsV); return vRegsOutCompute(inVec, inMetricsV, getNextTrellisEntry); endfunction(* noinline *)function Tuple3#(VState, VTBEntry, VRegsOutEntry#(VTBEntry)) vRegsOutComputeTB(VRegsOutEntry#(VTBEntry) inVec, VInType inMetricsV); return vRegsOutCompute(inVec, inMetricsV, getNextTB); endfunctionfunction Vector#(VRegsOutSz, VState) getNextStates(Bit#(VRegsSubIdxSz) stage); Vector#(VRegsOutSz, VState) outVec = newVector; VState subIdx = zeroExtend(stage) << fromInteger(valueOf(VRegsOutIdxSz)); for (Integer i = 0; i < valueOf(VRegsOutSz); i = i + 1) outVec[i] = subIdx + fromInteger(i); return outVec; endfunction // Vector /////////////////////////////////////////////////////////// Begin of Viterbi Module /////////////////////////////////////////////////////////(*synthesize*)module mkIViterbiTBPath (IViterbi); // states FIFO#(VInType) inQ <- mkLFIFO; FIFO#(VOutType) outQ <- mkSizedFIFO(2); VRegFile#(VRegsSubIdxSz,VRegsOutSz,VMetricSum) metricSums <- mkMetricSums; VRegFile#(VRegsSubIdxSz,VRegsOutSz,VTrellisEntry) trellis <- mkTrellis; Reg#(Bit#(VRegsSubIdxSz)) stage <- mkReg(0); Reg#(Bit#(1)) colIdx <- mkReg(0); Reg#(VState) curMinState <- mkReg(0); Reg#(VTrellisEntry) curMinPath <- mkRegU; Reg#(TBStageIdx) tbStage <- mkReg(0); // keep track of whether we can output TB result yet rule processInput(True); begin let nextMSums = metricSums.sub(colIdx, stage); let nextTrellis = trellis.sub(colIdx, stage); let nextStates = getNextStates(stage); let vRegsOutEntry = zip3(nextStates, nextMSums, nextTrellis); let vRegsOutNew = vRegsOutComputeTBPath(vRegsOutEntry, inQ.first); let minState = tpl_1(vRegsOutNew); let minPath = tpl_2(vRegsOutNew); let newMinState = (stage == 0 || minState < curMinState) ? minState : curMinState; let newMinPath = (stage == 0 || minState < curMinState) ? minPath : curMinPath; let newMSums = map(tpl_2, tpl_3(vRegsOutNew)); let newTrellis = map(tpl_3, tpl_3(vRegsOutNew)); Bit#(VStateSuffixSz) out = tpl_2(split(newMinPath)); VOutType vOut = unpack(out); curMinState <= newMinState; // new min curMinPath <= newMinPath; stage <= stage + 1; metricSums.upd(colIdx+1, stage, newMSums); trellis.upd(colIdx+1, stage, newTrellis); `ifdef isDebug $display ("viterbi return: colIdx=%d stage=%d newMinState=%d, newMinPath=%h", colIdx, stage, newMinState, newMinPath); $write ("viterbi return: newMSums="); for (Integer i = 0; i < no_states; i = i + 1) begin $write ("%d: %d ", tpl_1(tpl_3(vRegsOutNew)[i]), newMSums[i]); end $display (""); $write ("viterbi return: newTrellis="); for (Integer i = 0; i < no_states; i = i + 1) begin $write ("%d: %h ", tpl_1(tpl_3(vRegsOutNew)[i]), newTrellis[i]); end $display (""); `endif if (stage == maxBound) // last stage, output trace back begin inQ.deq; if (tbStage == fromInteger(no_tbstage-1)) outQ.enq(vOut); else tbStage <= tbStage + 1; colIdx <= colIdx + 1; end end endrule method Action putData (VInType dataIn); inQ.enq(dataIn); endmethod method ActionValue#(VOutType) getResult (); outQ.deq; return outQ.first; endmethod endmodule(*synthesize*)module mkIViterbiTB (IViterbi); // states FIFO#(VInType) inQ <- mkLFIFO; FIFO#(VOutType) outQ <- mkSizedFIFO(2); VRegFile#(VRegsSubIdxSz,VRegsOutSz,VMetricSum) metricSums <- mkMetricSums; Reg#(Vector#(VTotalStates, Bit#(1))) tbcol <- mkRegU; // save tb col Reg#(Bit#(VRegsSubIdxSz)) stage <- mkReg(0); Reg#(Bit#(1)) colIdx <- mkReg(0); Reg#(VState) curMinState <- mkReg(0); Reg#(TBStageIdx) tbStage <- mkReg(0); // keep track of whether we can output TB result yet Traceback tbu <- mkTraceback; rule performACS(True); begin let nextMSums = metricSums.sub(colIdx, stage); let nextTBEntry = newVector; let nextStates = getNextStates(stage); let vRegsOutEntry = zip3(nextStates, nextMSums, nextTBEntry); let vRegsOutNew = vRegsOutComputeTB(vRegsOutEntry, inQ.first); let minState = tpl_1(vRegsOutNew); let newMinState = (stage == 0 || minState < curMinState) ? minState : curMinState; let newMSums = map(tpl_2, tpl_3(vRegsOutNew)); let newTBEntry = map(tpl_3, tpl_3(vRegsOutNew)); let newTBCol = writeSelect(stage, tbcol, newTBEntry); curMinState <= newMinState; // new min stage <= stage + 1; metricSums.upd(colIdx+1, stage, newMSums); tbcol <= newTBCol; `ifdef isDebug $display ("viterbi return: colIdx=%d stage=%d newMinState=%d", colIdx, stage, newMinState); $write ("viterbi return: newMSums="); for (Integer i = 0; i < no_states; i = i + 1) begin $write ("%d: %d ", tpl_1(tpl_3(vRegsOutNew)[i]), newMSums[i]); end $display (""); $write ("viterbi return: newTBEntry="); for (Integer i = 0; i < no_states; i = i + 1) begin $write ("%d: %h ", tpl_1(tpl_3(vRegsOutNew)[i]), newTBEntry[i]); end $display (""); `endif if (stage == maxBound) // last stage, output trace back begin inQ.deq; colIdx <= colIdx + 1; tbu.updateMemory(vPermute(conv_in_sz, fwd_steps, newTBCol), newMinState); // put to traceback end end endrule rule performTB(True); begin let result <- tbu.getDecodedOutput; //get result from tb outQ.enq(unpack(pack(result))); end endrule method Action putData (VInType dataIn); inQ.enq(dataIn); endmethod method ActionValue#(VOutType) getResult (); outQ.deq; return outQ.first; endmethod endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -