xref: /XiangShan/src/main/scala/device/AXI4SlaveModule.scala (revision c6d439803a044ea209139672b25e35fe8d7f4aa0)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*
4* XiangShan is licensed under Mulan PSL v2.
5* You can use this software according to the terms and conditions of the Mulan PSL v2.
6* You may obtain a copy of Mulan PSL v2 at:
7*          http://license.coscl.org.cn/MulanPSL2
8*
9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12*
13* See the Mulan PSL v2 for more details.
14***************************************************************************************/
15
16package device
17
18import chisel3._
19import chisel3.util._
20import utils._
21import freechips.rocketchip.diplomacy.{AddressSet, LazyModule, LazyModuleImp, RegionType, TransferSizes}
22import chipsalliance.rocketchip.config.Parameters
23import freechips.rocketchip.amba.axi4.{AXI4Parameters, AXI4SlaveNode, AXI4SlaveParameters, AXI4SlavePortParameters}
24
25abstract class AXI4SlaveModule[T <: Data]
26(
27  address: Seq[AddressSet],
28  executable: Boolean = true,
29  beatBytes: Int = 8,
30  burstLen: Int = 1,
31  val _extra: T = null
32)(implicit p: Parameters) extends LazyModule {
33
34  val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
35    Seq(AXI4SlaveParameters(
36      address,
37      regionType = RegionType.UNCACHED,
38      executable = executable,
39      supportsWrite = TransferSizes(1, beatBytes * burstLen),
40      supportsRead = TransferSizes(1, beatBytes * burstLen),
41      interleavedId = Some(0)
42    )),
43    beatBytes = beatBytes
44  )))
45
46  lazy val module = new AXI4SlaveModuleImp[T](this)
47
48}
49
50class AXI4SlaveModuleImp[T<:Data](outer: AXI4SlaveModule[T])
51  extends LazyModuleImp(outer)
52{
53  val io = IO(new Bundle {
54    val extra = if(outer._extra == null) None else Some(outer._extra.cloneType)
55  })
56
57  val (in, edge) = outer.node.in.head
58  // do not let MMIO AXI signals optimized out
59  chisel3.dontTouch(in)
60
61
62//  val timer = GTimer()
63  when(in.ar.fire()){
64    XSDebug(p"[ar] addr: ${Hexadecimal(in.ar.bits.addr)} " +
65      p"arlen:${in.ar.bits.len} arsize:${in.ar.bits.size} " +
66      p"id: ${in.ar.bits.id}\n"
67    )
68  }
69  when(in.aw.fire()){
70    XSDebug(p"[aw] addr: ${Hexadecimal(in.aw.bits.addr)} " +
71      p"awlen:${in.aw.bits.len} awsize:${in.aw.bits.size} " +
72      p"id: ${in.aw.bits.id}\n"
73    )
74  }
75  when(in.w.fire()){
76    XSDebug(p"[w] wmask: ${Binary(in.w.bits.strb)} last:${in.w.bits.last} data:${Hexadecimal(in.w.bits.data)}\n")
77  }
78  when(in.b.fire()){
79    XSDebug(p"[b] id: ${in.b.bits.id}\n")
80  }
81  when(in.r.fire()){
82    XSDebug(p"[r] id: ${in.r.bits.id} data: ${Hexadecimal(in.r.bits.data)}\n")
83  }
84
85  when(in.aw.fire()){
86    assert(in.aw.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
87  }
88  when(in.ar.fire()){
89    assert(in.ar.bits.burst === AXI4Parameters.BURST_INCR, "only support busrt ince!")
90  }
91
92  val s_idle :: s_rdata :: s_wdata :: s_wresp :: Nil = Enum(4)
93
94  val state = RegInit(s_idle)
95
96  switch(state){
97    is(s_idle){
98      when(in.ar.fire()){
99        state := s_rdata
100      }
101      when(in.aw.fire()){
102        state := s_wdata
103      }
104    }
105    is(s_rdata){
106      when(in.r.fire() && in.r.bits.last){
107        state := s_idle
108      }
109    }
110    is(s_wdata){
111      when(in.w.fire() && in.w.bits.last){
112        state := s_wresp
113      }
114    }
115    is(s_wresp){
116      when(in.b.fire()){
117        state := s_idle
118      }
119    }
120  }
121
122
123  val fullMask = MaskExpand(in.w.bits.strb)
124
125  def genWdata(originData: UInt) = (originData & (~fullMask).asUInt()) | (in.w.bits.data & fullMask)
126
127  val raddr = Wire(UInt())
128  val (readBeatCnt, rLast) = {
129    val c = Counter(256)
130    val len = HoldUnless(in.ar.bits.len, in.ar.fire())
131    raddr := HoldUnless(in.ar.bits.addr, in.ar.fire())
132    in.r.bits.last := (c.value === len)
133
134    when(in.r.fire()) {
135      c.inc()
136      when(in.r.bits.last) {
137        c.value := 0.U
138      }
139    }
140    when(in.ar.fire()) {
141      assert(
142        in.ar.bits.len === 0.U ||
143          in.ar.bits.len === 1.U ||
144          in.ar.bits.len === 3.U ||
145          in.ar.bits.len === 7.U ||
146          in.ar.bits.len === 15.U
147      )
148    }
149    (c.value, in.r.bits.last)
150  }
151
152  in.ar.ready := state === s_idle
153  in.r.bits.resp := AXI4Parameters.RESP_OKAY
154  in.r.valid := state === s_rdata
155
156
157  val waddr = Wire(UInt())
158  val (writeBeatCnt, wLast) = {
159    val c = Counter(256)
160    waddr := HoldUnless(in.aw.bits.addr, in.aw.fire())
161    when(in.w.fire()) {
162      c.inc()
163      when(in.w.bits.last) {
164        c.value := 0.U
165      }
166    }
167    (c.value, in.w.bits.last)
168  }
169
170  in.aw.ready := state === s_idle && !in.ar.valid
171  in.w.ready := state === s_wdata
172
173  in.b.bits.resp := AXI4Parameters.RESP_OKAY
174  in.b.valid := state===s_wresp
175
176  in.b.bits.id := RegEnable(in.aw.bits.id, in.aw.fire())
177  in.b.bits.user := RegEnable(in.aw.bits.user, in.aw.fire())
178  in.r.bits.id := RegEnable(in.ar.bits.id, in.ar.fire())
179  in.r.bits.user := RegEnable(in.ar.bits.user, in.ar.fire())
180}
181