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