diff --git a/src/main/scala/CapturePositions.scala b/src/main/scala/CapturePositions.scala new file mode 100644 index 0000000..9ed6286 --- /dev/null +++ b/src/main/scala/CapturePositions.scala @@ -0,0 +1,104 @@ +package Rs + +import chisel3._ +import circt.stage.ChiselStage +import chisel3.util._ + +class CapturePositions(c:Config) extends Module { + val io = IO(new Bundle { + val bitPos = Input(new BitPosIf(c.chienRootsPerCycle)) + val errPosIf = Output(Valid(new vecFfsIf(c.T_LEN, c.SYMB_WIDTH))) + }) + + //////////////////////////////// + // Extract position from incomming + // bit vector where bits are asserted + //////////////////////////////// + + val extrPos = Module(new ExtractPositions(c.chienRootsPerCycle, c.T_LEN, 4)) + val numStages = extrPos.numStages + + extrPos.io.in.bits := io.bitPos.pos + extrPos.io.in.valid := io.bitPos.valid + + // Shift last + val lastQ = Reg(Vec(numStages, Bool())) + + lastQ(0) := io.bitPos.last + for(i <- 1 until numStages) { + lastQ(i) := lastQ(i-1) + } + + //////////////////////////////// + // insertVec is used to capture and shift + // valid positions into shift register of + // length T_LEN. + // + // outShift is used to remove bubbles in + // the shift registers since number of + // errors could be less than T_LEN. + //////////////////////////////// + + val insertVec = Module(new InsertVec(new PositionsVld,c.T_LEN, c.T_LEN)) + val baseVec = Reg(Vec(c.T_LEN, new PositionsVld)) + val vecIn = Wire(Vec(c.T_LEN, new PositionsVld)) + val baseCntr = RegInit(UInt(log2Ceil(c.SYMB_NUM).W), 0.U) + + // Final shift + val outShift = Module(new BarrelShifter(new PositionsVld, c.T_LEN)) + val outputVec = Reg(Vec(c.T_LEN, new PositionsVld)) + + class PositionsVld extends Bundle { + val positions = UInt(c.SYMB_WIDTH.W) + val vld = Bool() + } + + insertVec.io.vecIn := vecIn + insertVec.io.baseVec := baseVec + insertVec.io.shiftVal := extrPos.io.outTkeep.map(_.asUInt).reduce(_ +& _) + + outShift.io.vecIn := insertVec.io.vecOut + outShift.io.shiftVal := insertVec.io.vecOut.map(bundle => (!bundle.vld).asUInt).reduce(_ +& _) + + // need to add baseCntr to get a proper position: + when(extrPos.io.outValid) { + when(lastQ(numStages-1)) { + baseCntr := 0.U + baseVec.foreach(x => x := 0.U.asTypeOf(new PositionsVld)) + outputVec := outShift.io.vecOut + //outputVec := outShift.io.vecOut + }.otherwise{ + baseCntr := baseCntr + c.chienRootsPerCycle.U + baseVec := insertVec.io.vecOut + } + } + + for(i <- 0 until c.T_LEN) { + vecIn(i).positions := extrPos.io.positions(i) + baseCntr + vecIn(i).vld := extrPos.io.outTkeep(i) + io.errPosIf.bits.vec(i) := outputVec(i).positions + } + + //io.errPosIf.bits.ffs := Reverse((VecInit(outputVec.map(_.vld))).asUInt) + //io.errPosIf.bits.vec := insertVec.io.vecOut + + io.errPosIf.valid := lastQ(numStages-1) + io.errPosIf.bits.ffs := (VecInit(insertVec.io.vecOut.map(_.vld))).asUInt + io.errPosIf.bits.vec := (VecInit(insertVec.io.vecOut.map(_.positions))) +} + +object GenCapturePositions extends App { + + val projectRoot = System.getProperty("project.root") + + ConfigParser.parse(args) match { + case Some(config) => + JsonHandler.writeToFile(config, "rs.json") + // Get + val rsCfg = RSDecoderConfigs.getConfig(config.N_LEN, config.K_LEN) + val c = Config(config, rsCfg) + ChiselStage.emitSystemVerilogFile(new CapturePositions(c), Array()) + case None => + sys.exit(1) + } +} diff --git a/src/main/scala/ExtractPositions.scala b/src/main/scala/ExtractPositions.scala new file mode 100644 index 0000000..da11040 --- /dev/null +++ b/src/main/scala/ExtractPositions.scala @@ -0,0 +1,104 @@ +package Rs + +import chisel3._ +import circt.stage.ChiselStage +import chisel3.util._ + +class ExtractPositions(val InWidth: Int, val PosNum: Int, val pipelineInterval: Int) extends Module { + val io = IO(new Bundle { + val in = Input(Valid(UInt(InWidth.W))) + val positions = Output(Vec(PosNum, UInt(log2Ceil(InWidth).W))) + val outTkeep = Output(Vec(PosNum, Bool())) + val outValid = Output(Bool()) + }) + + // Number of pipeline stages required + val numStages = (InWidth + pipelineInterval - 1) / pipelineInterval + + // Convert input to a vector of Bools + val inVec = io.in.bits.asBools + + val prefSumOut = Wire(Vec(InWidth, UInt(log2Ceil(InWidth).W))) + val prefSumVldOut = Wire(Bool()) + + val inOut = Wire(UInt(InWidth.W)) + val inQ = Reg(Vec(numStages, (UInt(InWidth.W)))) + val inVecQ = Reg(Vec(numStages, (Vec(InWidth, Bool())))) + + val prefSumQ = Reg(Vec(numStages, Vec(InWidth, UInt(log2Ceil(InWidth).W)))) + val vldQ = Reg(Vec(numStages, Bool())) + + // Compute prefix sum with pipeline registers + for (stage <- 0 until numStages+1) { + + val prefSumInit = Wire(Vec(InWidth, UInt(log2Ceil(InWidth).W))) + val prefSum = Wire(Vec(InWidth, UInt(log2Ceil(InWidth).W))) + + if(stage == 0) { + prefSumInit := VecInit(inVec.map(b => Mux(b, 1.U, 0.U))) + } else { + prefSumInit := prefSumQ(stage-1) + } + + val startIdx = stage * pipelineInterval + val endIdx = stage * pipelineInterval + pipelineInterval + + prefSum(0) := prefSumInit(0) + + for(pos <- 1 until InWidth) { + if(pos < startIdx) + prefSum(pos) := prefSumInit(pos) + else if(pos < endIdx) + prefSum(pos) := prefSumInit(pos) + prefSum(pos-1) + else + prefSum(pos) := prefSumInit(pos) + } + + if(stage == numStages) { + prefSumOut := prefSum.map(b => b - 1.U) + prefSumVldOut := vldQ(stage-1) + inOut := inQ(stage-1) + } + else { + prefSumQ(stage) := prefSum + if(stage == 0) { + vldQ(stage) := io.in.valid + inQ(stage) := io.in.bits + } + else { + vldQ(stage) := vldQ(stage-1) + inQ(stage) := inQ(stage-1) + } + } + } + + // Initialize outputs + val positionsReg = Reg(Vec(PosNum, UInt(log2Ceil(InWidth).W))) + val outTkeepReg = Reg(Vec(PosNum, Bool())) + val outputOutValid = RegInit(false.B) + + // Default assignments + for (i <- 0 until PosNum) { + positionsReg(i) := 0.U + outTkeepReg(i) := false.B + } + + // Assign positions + for (i <- 0 until InWidth) { + when(inOut.asBools(i) && prefSumOut(i) < PosNum.U) { + val index = prefSumOut(i)(log2Ceil(PosNum)-1, 0) // Truncate prefSumOut(i) to the correct width + positionsReg(index) := i.U + outTkeepReg(index) := true.B + } + } + + // Connect outputs + io.positions := positionsReg + io.outTkeep := outTkeepReg + io.outValid := RegNext(prefSumVldOut, init=false.B ) + //io.outValid := io.in.valid +} + +object GenExtractPositions extends App { + ChiselStage.emitSystemVerilogFile(new ExtractPositions(8, 4, 4), Array()) +} diff --git a/src/main/scala/InsertVec.scala b/src/main/scala/InsertVec.scala new file mode 100644 index 0000000..787e390 --- /dev/null +++ b/src/main/scala/InsertVec.scala @@ -0,0 +1,38 @@ +package Rs + +import chisel3._ +import circt.stage.ChiselStage +import chisel3.util._ + +class InsertVec[T <: Data](shiftUnit: T, inWidth: Int, outWidth: Int) extends Module { + val io = IO(new Bundle { + val baseVec = Input(Vec(outWidth, shiftUnit)) + val vecIn = Input(Vec(inWidth, shiftUnit)) + val shiftVal = Input(UInt(log2Ceil(inWidth+1).W)) + val vecOut = Output(Vec(outWidth, shiftUnit)) + }) + + val alignInVec = Module(new AlignInVec(shiftUnit, inWidth, outWidth)) + val barrelShifter = Module(new BarrelShifter(shiftUnit, outWidth)) + + alignInVec.io.vecIn := io.vecIn + alignInVec.io.shiftVal := io.shiftVal + + barrelShifter.io.vecIn := io.baseVec + barrelShifter.io.shiftVal := io.shiftVal + + // Perform the OR operation element-wise + for (i <- 0 until outWidth) { + io.vecOut(i) := (barrelShifter.io.vecOut(i).asUInt | alignInVec.io.vecOut(i).asUInt).asTypeOf(shiftUnit) + } + +} + +object GenInsertVec extends App { + class ShiftUnit extends Bundle { + val formDerSymb = UInt(10.W) + val errEvalXlInvSymb = UInt(8.W) + val XlSymb = UInt(1.W) + } + ChiselStage.emitSystemVerilogFile(new InsertVec(new ShiftUnit, 4, 8), Array()) +}