Skip to content

Commit

Permalink
Memory Mapping Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Siudya committed Feb 7, 2024
1 parent 107407b commit 6b1dca3
Show file tree
Hide file tree
Showing 12 changed files with 364 additions and 116 deletions.
239 changes: 239 additions & 0 deletions src/main/scala/device/AXI4FakeDMA.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
* Copyright (c) 2020-2021 Peng Cheng Laboratory
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

package device

import org.chipsalliance.cde.config.Parameters
import chisel3._
import chisel3.util._
import freechips.rocketchip.amba.axi4.{AXI4MasterNode, AXI4MasterPortParameters, AXI4Parameters}
import freechips.rocketchip.diplomacy.AddressSet

class DMAFakeMSHR(implicit p: Parameters) extends Module {
val io = IO(new Bundle {
val enable = Input(Bool())
val slave = new Bundle {
val wen = Input(Bool())
val addr = Input(UInt(3.W))
val rdata = Output(UInt(64.W))
val wdata = Input(UInt(64.W))
}
val master = new Bundle {
val req = new Bundle {
val valid = Output(Bool())
val ready = Input(Bool())
val is_write = Output(Bool())
val addr = Output(UInt(64.W))
val mask = Output(UInt(32.W))
val data = Output(UInt(256.W))
}
val resp = Flipped(ValidIO(UInt(256.W)))
}
})

val state = Reg(UInt(8.W))
val address = Reg(UInt(64.W))
val mask = Reg(UInt(32.W))
val data = Reg(Vec(4, UInt(64.W)))

val s_idle :: s_read :: s_write :: s_wait_resp_b :: s_wait_resp_r :: Nil = Enum(5)
when (state === s_read) {
when (io.master.req.valid && io.master.req.ready) {
state := s_wait_resp_r
}
}.elsewhen (state === s_write) {
when (io.master.req.valid && io.master.req.ready) {
state := s_wait_resp_b
}
}.elsewhen (state === s_wait_resp_b) {
when (io.master.resp.valid) {
state := s_idle
}
}.elsewhen (state === s_wait_resp_r) {
when (io.master.resp.valid) {
state := s_idle
}
}

when (io.slave.wen) {
when (io.slave.addr === 4.U) {
state := io.slave.wdata
}.elsewhen(io.slave.addr === 5.U) {
address := io.slave.wdata
}.elsewhen(io.slave.addr === 6.U) {
mask := io.slave.wdata
}.otherwise {
data(io.slave.addr) := io.slave.wdata
}
}
io.slave.rdata := Mux(io.slave.addr === 4.U, state,
Mux(io.slave.addr === 5.U, address,
Mux(io.slave.addr === 6.U, mask, data(io.slave.addr))))

io.master.req.valid := io.enable && (state === s_read || state === s_write)
io.master.req.is_write := state === s_write
io.master.req.addr := address
io.master.req.mask := mask
io.master.req.data := data.asUInt

when (io.master.resp.valid) {
when (state === s_wait_resp_r) {
for (i <- 0 until 4) {
data(i) := io.master.resp.bits(64 * i + 63, 64 * i)
}
}
}

// val last_state = RegNext(state, init=s_idle)
// val read_valid = last_state === s_wait_resp_r && state === s_idle
// val write_valid = last_state === s_wait_resp_b && state === s_idle
// val difftest = Module(new DifftestDMATransaction)
// difftest.io.clock := clock
// difftest.io.coreid := 0.U
// difftest.io.valid := read_valid || write_valid
// difftest.io.is_write := last_state === s_wait_resp_b
// difftest.io.address := address
// difftest.io.mask := mask
// difftest.io.data := data

def slave_read(addr: UInt): UInt = {
io.slave.wen := false.B
io.slave.addr := addr
io.slave.rdata
}
def slave_write(addr: UInt, data: UInt): Unit = {
io.slave.wen := true.B
io.slave.addr := addr
io.slave.wdata := data
}
def has_read_req: Bool = io.master.req.valid && !io.master.req.is_write
def has_write_req: Bool = io.master.req.valid && io.master.req.is_write
}

class AXI4FakeDMA
(
address: Seq[AddressSet],
params: AXI4MasterPortParameters
)(implicit p: Parameters)
extends AXI4SlaveModule(address, executable = true)
{
val dma_node = AXI4MasterNode(Seq(params))

override lazy val module = new AXI4SlaveModuleImp(this) {
val numInflight = 64
require(isPow2(numInflight))

// 0x0 - (0x80 * numInflight)
val mshr = Seq.fill(numInflight)(Module(new DMAFakeMSHR))
val enable_addr_bit = log2Ceil(numInflight) + 4 + 3
val enable = RegInit(0.U(numInflight.W))
mshr.zip(enable.asBools).foreach(x => x._1.io.enable := x._2)

// DMACtrl slave READ
val reqReadOffset = raddr(5, 3)
val reqReadIdx = raddr(6 + log2Ceil(numInflight + 1) - 1, 6)
val req_r = VecInit(mshr.map(_.slave_read(reqReadOffset)))
in.r.bits.data := Mux(raddr(enable_addr_bit), enable, req_r(reqReadIdx))

// DMACtrl slave WRITE
val reqWriteOffset = waddr(5, 3)
val reqWriteIdx = waddr(6 + log2Ceil(numInflight + 1) - 1, 6)
for ((req, i) <- mshr.zipWithIndex) {
req.io.slave.wdata := DontCare
when (in.w.fire && reqWriteIdx === i.U && !waddr(enable_addr_bit)) {
req.slave_write(reqWriteOffset, in.w.bits.data)
}
}
when (in.w.fire && waddr(enable_addr_bit)) {
enable := in.w.bits.data
}

// DMA master
val (out, dma_edge) = dma_node.out.head
val dmaReqBytes = 32
val dmaBeatBytes = dma_edge.slave.beatBytes
val numBeats = dmaReqBytes / dmaBeatBytes
val axi_len = numBeats - 1
def selectByBeatIndex(i: UInt, data: UInt): UInt = {
data.asTypeOf(Vec(numBeats, UInt((data.getWidth / numBeats).W)))(i)
}

// DMA master READ Request
val has_read_req = VecInit(mshr.map(_.has_read_req))
val out_read_index = PriorityEncoderOH(has_read_req)
val out_read_req = Mux1H(out_read_index, mshr.map(_.io.master.req))
out.ar.valid := has_read_req.asUInt.orR
out.ar.bits := 0.U.asTypeOf(out.ar.bits.cloneType)
out.ar.bits.id := OHToUInt(out_read_index)
out.ar.bits.addr := out_read_req.addr
out.ar.bits.len := axi_len.U
out.ar.bits.size := log2Ceil(dmaReqBytes).U
out.ar.bits.burst := AXI4Parameters.BURST_INCR

// DMA master WRIET Request
val has_write_req = VecInit(mshr.map(_.has_write_req))
val out_write_index = PriorityEncoderOH(has_write_req)
val out_write_req = Mux1H(out_write_index, mshr.map(_.io.master.req))
out.aw.valid := has_write_req.asUInt.orR
out.aw.bits := 0.U.asTypeOf(out.aw.bits.cloneType)
out.aw.bits.id := OHToUInt(out_write_index)
out.aw.bits.addr := out_write_req.addr
out.aw.bits.len := axi_len.U
out.aw.bits.size := log2Ceil(dmaReqBytes).U
out.aw.bits.burst := AXI4Parameters.BURST_INCR

// DMA master READ/WRITE handshake
for ((req_ready, i) <- mshr.map(_.io.master.req.ready).zipWithIndex) {
val read_fire = out.ar.fire && out_read_index(i)
val write_fire = out.aw.fire && out_write_index(i)
req_ready := read_fire || write_fire
}

// DMA master WRITE DATA
val w_valid = RegInit(false.B)
when (out.aw.fire) {
w_valid := true.B
}.elsewhen(out.w.fire && out.w.bits.last) {
w_valid := false.B
}
// Only one inflight aw: disable aw.valid when !w.bits.last
when (w_valid) {
out.aw.valid := false.B
}
val beatCount = RegInit(0.U(log2Ceil(numBeats).W))
val w_mask = RegEnable(out_write_req.mask, out.aw.fire)
val w_data = RegEnable(out_write_req.data, out.aw.fire)
out.w.valid := w_valid
out.w.bits := DontCare
out.w.bits.data := selectByBeatIndex(beatCount, w_data)
out.w.bits.strb := selectByBeatIndex(beatCount, w_mask)
out.w.bits.last := beatCount === (numBeats - 1).U
when (out.w.fire) {
beatCount := beatCount + 1.U
}

// DMA master READ/WRITE Response
out.r.ready := true.B
out.b.ready := true.B
for ((resp, i) <- mshr.map(_.io.master.resp).zipWithIndex) {
val read_resp_fire = out.r.fire && out.r.bits.id === i.U
val write_resp_fire = out.b.fire && out.b.bits.id === i.U
resp.valid := read_resp_fire || write_resp_fire
resp.bits := out.r.bits.data
}

}
}
49 changes: 30 additions & 19 deletions src/main/scala/device/AXI4IntrGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,52 +23,63 @@ import freechips.rocketchip.diplomacy.AddressSet
import xs.utils._

// we support 256 interrupt bits by default
class IntrGenIO extends Bundle {
val intrVec = Output(UInt(64.W))
trait IntrGenConfig {
// we support 256 interrupt bits by default
def intrWidth = 256
// Delay the intr gen for 1000 cycles.
def delayCycles = 1000
// Defined in riscv-plic-1.0.0_rc1, page 11
def registerWidth = 32
def numIntrReg: Int = intrWidth / registerWidth
def numIntrGenReg: Int = 4 * numIntrReg
}

class IntrGenIO extends Bundle with IntrGenConfig {
val intrVec = Output(UInt(this.intrWidth.W))
}

class AXI4IntrGenerator
(
address: Seq[AddressSet]
)(implicit p: Parameters)
extends AXI4SlaveModule(address, executable = false, _extra = new IntrGenIO)
with IntrGenConfig
{

override lazy val module = new AXI4SlaveModuleImp(this){

val intrGenRegs = RegInit(VecInit(Seq.fill(8)(0.U(32.W))))

// 0x0 - 0x8
val intrReg = VecInit(intrGenRegs.take(2))
// 0x8 - 0x10
val randEnable = VecInit(intrGenRegs.slice(2, 4))
// 0x10
val randMask = intrGenRegs(4)
val randCounter = intrGenRegs(5)
val randThres = intrGenRegs(6)
val intrGenRegs = RegInit(VecInit(Seq.fill(numIntrGenReg)(0.U(registerWidth.W))))
// 0x0 - 0x20
val intrReg = VecInit(intrGenRegs.take(numIntrReg))
// 0x20 - 0x40
val randEnable = VecInit(intrGenRegs.slice(numIntrReg, 2 * numIntrReg))
// 0x40
val randMask = intrGenRegs(2 * numIntrReg)
val randCounter = intrGenRegs(2 * numIntrReg + 1)
val randThres = intrGenRegs(2 * numIntrReg + 2)

val randomPosition = LFSR64()(5, 0)
val randomCondition = randCounter === randThres && randEnable(randomPosition(5))(randomPosition(4, 0))
val randomPosition = LFSR64()(4 + log2Up(numIntrReg), 0)
val randomCondition = randCounter === randThres &&
randEnable(randomPosition(4 + log2Up(numIntrReg), 5))(randomPosition(4, 0))
randCounter := randCounter + 1.U
when (randomCondition) {
intrGenRegs(randomPosition(5)) := intrReg(randomPosition(5)) | UIntToOH(randomPosition(4, 0))
intrGenRegs(randomPosition(4 + log2Up(numIntrReg), 5)) :=
intrReg(randomPosition(4 + log2Up(numIntrReg), 5)) | UIntToOH(randomPosition(4, 0))
}

io.extra.get.intrVec := Cat(intrReg.reverse)

// Delay the intr gen for 1000 cycles.
val delayCycles = 1000
var w_fire = in.w.fire && in.w.bits.data =/= 0.U
for (i <- 0 until delayCycles) {
w_fire = RegNext(w_fire, init=false.B)
}
val w_data = DelayN(in.w.bits.data(31, 0), delayCycles)
when (w_fire) {
intrGenRegs(DelayN(waddr(4, 2), delayCycles)) := w_data
intrGenRegs(DelayN(waddr(log2Up(numIntrGenReg) + 1, 2), delayCycles)) := w_data
}
// Clear takes effect immediately
when (in.w.fire && in.w.bits.data === 0.U) {
intrGenRegs(waddr(4, 2)) := 0.U
intrGenRegs(waddr(log2Up(numIntrGenReg) + 1, 2)) := 0.U
}
// write resets the threshold and counter
when (in.w.fire && in.w.bits.data === 0.U || w_fire) {
Expand Down
10 changes: 5 additions & 5 deletions src/main/scala/system/SoC.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ trait HaveSlaveAXI4Port {
)))
private val errorDevice = LazyModule(new TLError(
params = DevNullParams(
address = Seq(AddressSet(0x0, 0x7fffffffL)),
address = Seq(AddressSet(0x0, 0xfffffffffL)),
maxAtomic = 8,
maxTransfer = 64),
beatBytes = L3InnerBusWidth / 8
Expand All @@ -136,7 +136,7 @@ trait HaveAXI4MemPort {
val device = new MemoryDevice

val memAddrMask = (1L << PAddrBits) - 1L
val memRange = AddressSet(0x00000000L, memAddrMask).subtract(AddressSet(0x00000000L, 0x7FFFFFFFL))
val memRange = AddressSet(0x000000000L, memAddrMask).subtract(AddressSet(0x000000000L, 0xFFFFFFFFFL))
val memAXI4SlaveNode = AXI4SlaveNode(Seq(
AXI4SlavePortParameters(
slaves = Seq(
Expand Down Expand Up @@ -182,7 +182,7 @@ trait HaveAXI4MemPort {
trait HaveAXI4PeripheralPort { this: BaseSoC =>
// on-chip devices: 0x3800_0000 - 0x3fff_ffff 0x0000_0000 - 0x0000_0fff
val onChipPeripheralRange = AddressSet(0x38000000L, 0x07ffffffL)
val uartRange = AddressSet(0x40600000, 0xf)
val uartRange = AddressSet(0x37000000, 0xf)
val uartDevice = new SimpleDevice("serial", Seq("xilinx,uartlite"))
val uartParams = AXI4SlaveParameters(
address = Seq(uartRange),
Expand All @@ -191,8 +191,8 @@ trait HaveAXI4PeripheralPort { this: BaseSoC =>
supportsWrite = TransferSizes(1, 8),
resources = uartDevice.reg
)
val periAddrMask = (1L << PAddrBits) - 1L
val peripheralRange = AddressSet(0x00000000L, periAddrMask).subtract(onChipPeripheralRange).flatMap(x => x.subtract(uartRange))
val periAddrMask = 0xFFFFFFFFFL
val peripheralRange = AddressSet(0x0000000000L, periAddrMask).subtract(onChipPeripheralRange).flatMap(x => x.subtract(uartRange))
val peripheralNode = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
Seq(AXI4SlaveParameters(
address = peripheralRange,
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/top/Configs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,6 @@ class DefaultConfig(n: Int = 1) extends Config(
new WithNKBL3(4 * 1024, inclusive = false, banks = 4, ways = 8, core_num = n)
++ new WithNKBL2(256, inclusive = false, banks = 2, ways = 8, alwaysReleaseData = true)
++ new WithNKBL1D(64)
++ new BaseConfig(n)
++ new BaseConfig(n, true)
)

Loading

0 comments on commit 6b1dca3

Please sign in to comment.