xref: /XiangShan/src/main/scala/device/AXI4SlaveModule.scala (revision 24b11ca37f2240447b17e9d86b260876a9254f90)
1package device
2
3import chisel3._
4import chisel3.util._
5import utils._
6import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType, TransferSizes}
7import chipsalliance.rocketchip.config.Parameters
8import freechips.rocketchip.amba.axi4.{AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters}
9import xiangshan.HasXSLog
10
11abstract class AXI4SlaveModule[T <: Data]
12(
13  address: AddressSet,
14  executable: Boolean = true,
15  beatBytes: Int = 8,
16  burstLen: Int = 1,
17  val _extra: T = null
18)(implicit p: Parameters) extends LazyModule {
19
20  val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
21    Seq(AXI4SlaveParameters(
22      Seq(address),
23      regionType = RegionType.UNCACHED,
24      executable = executable,
25      supportsWrite = TransferSizes(1, beatBytes * burstLen),
26      supportsRead = TransferSizes(1, beatBytes * burstLen),
27      interleavedId = Some(0)
28    )),
29    beatBytes = beatBytes
30  )))
31
32  lazy val module = new AXI4SlaveModuleImp[T](this)
33
34}
35
36class AXI4SlaveModuleImp[T<:Data](outer: AXI4SlaveModule[T])
37  extends LazyModuleImp(outer) with HasXSLog
38{
39  val io = IO(new Bundle {
40    val extra = if(outer._extra == null) None else Some(outer._extra.cloneType)
41  })
42
43  val (in, edge) = outer.node.in.head
44
45//  val timer = GTimer()
46  when(in.ar.fire()){
47    XSDebug(p"[ar] addr: ${Hexadecimal(in.ar.bits.addr)} " +
48      p"arlen:${in.ar.bits.len} arsize:${in.ar.bits.size} " +
49      p"id: ${in.ar.bits.id}\n"
50    )
51  }
52  when(in.aw.fire()){
53    XSDebug(p"[aw] addr: ${Hexadecimal(in.aw.bits.addr)} " +
54      p"awlen:${in.aw.bits.len} awsize:${in.aw.bits.size} " +
55      p"id: ${in.aw.bits.id}\n"
56    )
57  }
58  when(in.w.fire()){
59    XSDebug(p"[w] wmask: ${Binary(in.w.bits.strb)} last:${in.w.bits.last} data:${Hexadecimal(in.w.bits.data)}\n")
60  }
61  when(in.b.fire()){
62    XSDebug(p"[b] id: ${in.b.bits.id}\n")
63  }
64  when(in.r.fire()){
65    XSDebug(p"[r] id: ${in.r.bits.id} data: ${Hexadecimal(in.r.bits.data)}\n")
66  }
67
68
69  private val s_idle :: s_rdata :: s_wdata :: s_wresp :: Nil = Enum(4)
70
71  private val state = RegInit(s_idle)
72
73  switch(state){
74    is(s_idle){
75      when(in.ar.fire()){
76        state := s_rdata
77      }
78      when(in.aw.fire()){
79        state := s_wdata
80      }
81    }
82    is(s_rdata){
83      when(in.r.fire() && in.r.bits.last){
84        state := s_idle
85      }
86    }
87    is(s_wdata){
88      when(in.w.fire() && in.w.bits.last){
89        state := s_wresp
90      }
91    }
92    is(s_wresp){
93      when(in.b.fire()){
94        state := s_idle
95      }
96    }
97  }
98
99
100  val fullMask = MaskExpand(in.w.bits.strb)
101
102  def genWdata(originData: UInt) = (originData & (~fullMask).asUInt()) | (in.w.bits.data & fullMask)
103
104  val raddr = Wire(UInt())
105  val ren = Wire(Bool())
106  val (readBeatCnt, rLast) = {
107    val c = Counter(256)
108    val beatCnt = Counter(256)
109    val len = HoldUnless(in.ar.bits.len, in.ar.fire())
110    val burst = HoldUnless(in.ar.bits.burst, in.ar.fire())
111    val wrapAddr = in.ar.bits.addr & (~(in.ar.bits.len << in.ar.bits.size)).asUInt()
112    raddr := HoldUnless(wrapAddr, in.ar.fire())
113    in.r.bits.last := (c.value === len)
114    when(ren) {
115      beatCnt.inc()
116      when(burst === AXI4Parameters.BURST_WRAP && beatCnt.value === len) {
117        beatCnt.value := 0.U
118      }
119    }
120    when(in.r.fire()) {
121      c.inc()
122      when(in.r.bits.last) {
123        c.value := 0.U
124      }
125    }
126    when(in.ar.fire()) {
127      beatCnt.value := (in.ar.bits.addr >> in.ar.bits.size).asUInt() & in.ar.bits.len
128      when(in.ar.bits.len =/= 0.U && in.ar.bits.burst === AXI4Parameters.BURST_WRAP) {
129        assert(in.ar.bits.len === 1.U || in.ar.bits.len === 3.U ||
130          in.ar.bits.len === 7.U || in.ar.bits.len === 15.U)
131      }
132    }
133    (beatCnt.value, in.r.bits.last)
134  }
135
136  val r_busy = BoolStopWatch(in.ar.fire(), in.r.fire() && rLast, startHighPriority = true)
137  in.ar.ready := state === s_idle
138  in.r.bits.resp := AXI4Parameters.RESP_OKAY
139  ren := RegNext(in.ar.fire()) || (in.r.fire() && !rLast)
140  in.r.valid := state === s_rdata
141
142
143  val waddr = Wire(UInt())
144  val (writeBeatCnt, wLast) = {
145    val c = Counter(256)
146    waddr := HoldUnless(in.aw.bits.addr, in.aw.fire())
147    when(in.w.fire()) {
148      c.inc()
149      when(in.w.bits.last) {
150        c.value := 0.U
151      }
152    }
153    (c.value, in.w.bits.last)
154  }
155
156  in.aw.ready := state === s_idle
157  in.w.ready := state === s_wdata
158
159  in.b.bits.resp := AXI4Parameters.RESP_OKAY
160  in.b.valid := state===s_wresp
161
162  in.b.bits.id := RegEnable(in.aw.bits.id, in.aw.fire())
163  in.b.bits.user := RegEnable(in.aw.bits.user, in.aw.fire())
164  in.r.bits.id := RegEnable(in.ar.bits.id, in.ar.fire())
165  in.r.bits.user := RegEnable(in.ar.bits.user, in.ar.fire())
166}
167