blob: 97ce8965faa0df43488febb7e7edaaf141b08ef3 [file] [log] [blame]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package chai
import chisel3._
import chisel3.util._
import _root_.circt.stage.ChiselStage
case class Parameters() {
val sramReadPorts = 1
val sramWritePorts = 1
val sramReadWritePorts = 0
val sramDataBits = 256
val sramBytes = 4 * 1024 * 1024
def sramDataEntries(): Int = {
((sramBytes * 8) / sramDataBits)
}
def sramAddrBits(): Int = {
log2Ceil(sramDataEntries())
}
}
object ChAI {
def apply(p: Parameters): ChAI = {
return Module(new ChAI(p))
}
}
class ChAI(p: Parameters) extends RawModule {
val io = IO(new Bundle {
val clk_i = Input(Clock())
val rst_ni = Input(AsyncReset())
val sram = new Bundle {
val write_address = Input(UInt(p.sramAddrBits().W))
val write_enable = Input(Bool())
val write_data = Input(UInt(p.sramDataBits.W))
}
val finish = Output(Bool())
val fault = Output(Bool())
val freeze = Input(Bool())
val uart_rx = Input(Bool())
val uart_tx = Output(Bool())
})
// TODO(atv): Compute that we don't have any overlaps in regions.
val memoryRegions = Seq(
new kelvin.MemoryRegion(0, 4 * 1024 * 1024, true, 256), // SRAM
new kelvin.MemoryRegion(4 * 1024 * 1024, 4 * 1024 * 1024, false, 256) // UART
)
val kelvin_p = kelvin.Parameters(memoryRegions)
val rst_i = (!io.rst_ni.asBool).asAsyncReset
val u_kelvin = matcha.Kelvin(kelvin_p)
u_kelvin.clk_i := io.clk_i
u_kelvin.rst_ni := io.rst_ni
u_kelvin.clk_freeze := io.freeze
u_kelvin.ml_reset := 0.U
u_kelvin.pc_start := 0.U
u_kelvin.volt_sel := 0.U
io.finish := u_kelvin.finish
io.fault := u_kelvin.fault
withClockAndReset(io.clk_i, rst_i) {
val tlul_p = new kelvin.TLULParameters()
val kelvin_to_tlul = chai.KelvinToTlul(tlul_p, kelvin_p)
kelvin_to_tlul.io.kelvin <> u_kelvin.mem
val tlul_sram =
SRAM(p.sramDataEntries(), UInt(p.sramDataBits.W), p.sramReadPorts, p.sramWritePorts, p.sramReadWritePorts)
val tlul_adapter_sram = Module(new chai.TlulAdapterSram())
tlul_adapter_sram.io.clk_i := io.clk_i
tlul_adapter_sram.io.rst_ni := io.rst_ni
tlul_adapter_sram.io.en_ifetch_i := 9.U // MuBi4False
tlul_sram.readPorts(0).enable := tlul_adapter_sram.io.req_o
tlul_sram.readPorts(0).address := tlul_adapter_sram.io.addr_o
tlul_sram.writePorts(0).enable := Mux(io.freeze, io.sram.write_enable, tlul_adapter_sram.io.we_o)
tlul_sram.writePorts(0).address := Mux(io.freeze, io.sram.write_address, tlul_adapter_sram.io.addr_o)
tlul_sram.writePorts(0).data := Mux(io.freeze, io.sram.write_data, tlul_adapter_sram.io.wdata_o)
tlul_adapter_sram.io.gnt_i := 1.U
tlul_adapter_sram.io.rdata_i := tlul_sram.readPorts(0).data
tlul_adapter_sram.io.rvalid_i := 1.U
tlul_adapter_sram.io.rerror_i := 0.U
val uart = Module(new chai.Uart(tlul_p))
uart.io.clk_i := io.clk_i
uart.io.rst_ni := io.rst_ni
uart.io.alert_rx_i := 0.U
uart.io.cio_rx_i := io.uart_rx
io.uart_tx := uart.io.cio_tx_o
val crossbar =
Module(new kelvin.TileLinkUL(tlul_p, kelvin_p.m, /* hosts= */ 1))
crossbar.io.hosts_a(0) <> kelvin_to_tlul.io.tl_o
crossbar.io.hosts_d(0) <> kelvin_to_tlul.io.tl_i
crossbar.io.devices_a(0) <> tlul_adapter_sram.io.tl_i
crossbar.io.devices_d(0) <> tlul_adapter_sram.io.tl_o
crossbar.io.devices_a(1) <> uart.io.tl_i
crossbar.io.devices_d(1) <> uart.io.tl_o
}
}
object EmitChAI extends App {
val p = new Parameters()
ChiselStage.emitSystemVerilogFile(new ChAI(p), args)
}