Merge "Add floating point regfile."
diff --git a/hdl/chisel/BUILD b/hdl/chisel/BUILD
index 88cf0d0..f32c099 100644
--- a/hdl/chisel/BUILD
+++ b/hdl/chisel/BUILD
@@ -17,14 +17,14 @@
srcs = [
"//hdl/chisel/src/matcha:Kelvin.sv",
"//hdl/chisel/src/matcha:Crossbar.sv",
- "//hdl/verilog:ClockGate.v",
+ "//hdl/verilog:ClockGate.sv",
"//hdl/verilog:Sram_1rw_256x256.v",
"//hdl/verilog:Sram_1rwm_256x288.v",
],
outs = [
"kelvin.sv",
"crossbar.sv",
- "ClockGate.v",
+ "ClockGate.sv",
"Sram_1rw_256x256.v",
"Sram_1rwm_256x288.v",
],
@@ -41,7 +41,7 @@
\\`define ASSERT_VERBOSE_COND 0
" > $(location crossbar.sv)
cat $(location //hdl/chisel/src/matcha:Crossbar.sv) >> $(location crossbar.sv)
- cp -f $(location //hdl/verilog:ClockGate.v) $(location ClockGate.v)
+ cp -f $(location //hdl/verilog:ClockGate.sv) $(location ClockGate.sv)
cp -f $(location //hdl/verilog:Sram_1rw_256x256.v) $(location Sram_1rw_256x256.v)
cp -f $(location //hdl/verilog:Sram_1rwm_256x288.v) $(location Sram_1rwm_256x288.v)
""",
diff --git a/hdl/chisel/kelvin.core.in b/hdl/chisel/kelvin.core.in
index e8d61c6..95f7fa3 100644
--- a/hdl/chisel/kelvin.core.in
+++ b/hdl/chisel/kelvin.core.in
@@ -8,7 +8,7 @@
files_rtl:
files:
- kelvin.sv
- - ClockGate.v
+ - ClockGate.sv
- Sram_1rw_256x256.v
- Sram_1rwm_256x288.v
file_type: systemVerilogSource
diff --git a/hdl/chisel/src/chai/BUILD b/hdl/chisel/src/chai/BUILD
new file mode 100644
index 0000000..b4e1c48
--- /dev/null
+++ b/hdl/chisel/src/chai/BUILD
@@ -0,0 +1,45 @@
+# 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.
+
+load("@kelvin_hw//rules:chisel.bzl", "chisel_cc_library", "chisel_library")
+
+package(default_visibility = ["//visibility:public"])
+
+chisel_library(
+ name = "chai",
+ srcs = [
+ "ChAI.scala",
+ "KelvinToTlul.scala",
+ "TlulAdapterSram.scala",
+ "Uart.scala",
+ ],
+ deps = [
+ "//hdl/chisel/src/matcha:matcha",
+ "//hdl/chisel/src/kelvin:kelvin",
+ ],
+)
+
+chisel_cc_library(
+ name = "chai_cc_library",
+ chisel_lib = ":chai",
+ emit_class = "chai.EmitChAI",
+ module_name = "ChAI",
+ verilog_deps = [
+ "//hdl/verilog:clock_gate",
+ "//hdl/verilog:sram_1rw_256x256",
+ "//hdl/verilog:sram_1rw_256x288",
+ "//hdl/verilog:tlul_adapter_sram",
+ "//hdl/verilog:uart",
+ ],
+)
diff --git a/hdl/chisel/src/chai/ChAI.scala b/hdl/chisel/src/chai/ChAI.scala
new file mode 100644
index 0000000..97ce896
--- /dev/null
+++ b/hdl/chisel/src/chai/ChAI.scala
@@ -0,0 +1,119 @@
+// 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)
+}
diff --git a/hdl/chisel/src/chai/KelvinToTlul.scala b/hdl/chisel/src/chai/KelvinToTlul.scala
new file mode 100644
index 0000000..c8573c2
--- /dev/null
+++ b/hdl/chisel/src/chai/KelvinToTlul.scala
@@ -0,0 +1,114 @@
+// 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._
+
+object KelvinToTlul {
+ object State extends ChiselEnum {
+ val sIdle, sWaitForReady, sWaitForResponse = Value
+ }
+
+ def apply(tlul_p: kelvin.TLULParameters, kelvin_p: kelvin.Parameters): KelvinToTlul = {
+ return Module(new KelvinToTlul(tlul_p, kelvin_p))
+ }
+}
+
+class KelvinToTlul(tlul_p: kelvin.TLULParameters, kelvin_p: kelvin.Parameters) extends Module {
+ import KelvinToTlul.State
+ import KelvinToTlul.State._
+
+ val io = IO(new Bundle {
+ val tl_i = Input(new _root_.kelvin.TileLinkULIO_D2H(tlul_p))
+ val tl_o = Output(new _root_.kelvin.TileLinkULIO_H2D(tlul_p))
+ val kelvin = Flipped(new matcha.KelvinMemIO(kelvin_p))
+ })
+ val state = RegInit(sIdle)
+
+ val wmask_width = io.kelvin.wmask.getWidth
+ val wmask_bits = (0 until wmask_width)
+ .map(x => Mux(io.kelvin.wmask(x), 0xff.U(wmask_width.W) << (x * 8).U, 0.U(wmask_width.W)))
+ .reduce(_ | _)
+
+ io.tl_o := 0.U.asTypeOf(new kelvin.TileLinkULIO_H2D(tlul_p))
+ io.tl_o.a_user.instr_type := 9.U
+ io.tl_o.a_source := 0.U
+ io.tl_o.d_ready := true.B
+ io.kelvin.rid := 0.U
+ io.kelvin.cready := true.B
+ io.kelvin.rvalid := false.B
+ io.kelvin.rdata := 0.U
+ io.tl_o.a_mask := -1.S(io.tl_o.a_mask.getWidth.W).asUInt
+ io.tl_o.a_param := 0.U
+ io.tl_o.a_size := 5.U
+
+ // state | transition | next state
+ // sIdle | valid & a_ready | sWaitForResponse
+ // sIdle | valid & !a_ready | sWaitForReady
+ // sWaitForReady | a_ready | sWaitForResponse
+ // sWaitForResponse | d_valid | sIdle
+ switch(state) {
+ is(sIdle) {
+ io.kelvin.cready := true.B
+ when(io.kelvin.cvalid) {
+ io.kelvin.cready := false.B
+ io.tl_o.a_valid := true.B
+ io.tl_o.a_address := io.kelvin.caddr
+ val cwrite = io.kelvin.cwrite
+ io.tl_o.a_opcode := Mux(cwrite, kelvin.TLULOpcodesA.PutFullData.asUInt, kelvin.TLULOpcodesA.Get.asUInt)
+ io.tl_o.a_data := Mux(cwrite, io.kelvin.wdata & wmask_bits, 0.U)
+ state := Mux(io.tl_i.a_ready, sWaitForResponse, sWaitForReady)
+ }
+ }
+ is(sWaitForReady) {
+ when(io.tl_i.a_ready) {
+ state := sWaitForResponse
+ }
+ }
+ is(sWaitForResponse) {
+ io.tl_o.a_valid := false.B
+ when(io.tl_i.d_valid) {
+ val (value, valid) = kelvin.TLULOpcodesD.safe(io.tl_i.d_opcode)
+ val valid2 = valid && (value =/= kelvin.TLULOpcodesD.End)
+ assert(valid2, "Received invalid TLUL-D opcode\n")
+
+ val rdata = chisel3.util.MuxLookup(value, 0.U(32.W))(
+ Array(
+ kelvin.TLULOpcodesD.AccessAck -> 0.U,
+ kelvin.TLULOpcodesD.AccessAckData -> io.tl_i.d_data
+ )
+ )
+ val rvalid = chisel3.util.MuxLookup(value, false.B)(
+ Array(
+ kelvin.TLULOpcodesD.AccessAck -> false.B,
+ kelvin.TLULOpcodesD.AccessAckData -> true.B
+ )
+ )
+ val rid = chisel3.util.MuxLookup(value, 0.U)(
+ Array(
+ kelvin.TLULOpcodesD.AccessAck -> 0.U,
+ kelvin.TLULOpcodesD.AccessAckData -> io.kelvin.cid
+ )
+ )
+ io.kelvin.rvalid := rvalid
+ io.kelvin.rdata := rdata
+ io.kelvin.cready := true.B
+ io.kelvin.rid := rid
+ state := sIdle
+ }
+ }
+ }
+}
diff --git a/hdl/chisel/src/chai/TlulAdapterSram.scala b/hdl/chisel/src/chai/TlulAdapterSram.scala
new file mode 100644
index 0000000..345db11
--- /dev/null
+++ b/hdl/chisel/src/chai/TlulAdapterSram.scala
@@ -0,0 +1,55 @@
+// 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._
+
+package object sram_params {
+ val SramAw = 17
+ val SramDw = 256
+ val Outstanding = 1
+ val ByteAccess = 1
+ val ErrOnRead = 0
+ val EnableDataIntgPt = 0
+}
+
+class TlulAdapterSram extends BlackBox {
+ val tlul_p = new kelvin.TLULParameters()
+ val io = IO(new Bundle {
+ val clk_i = Input(Clock())
+ val rst_ni = Input(AsyncReset())
+
+ // TL-UL
+ val tl_i = Input(new kelvin.TileLinkULIO_H2D(tlul_p))
+ val tl_o = Output(new kelvin.TileLinkULIO_D2H(tlul_p))
+
+ // control
+ val en_ifetch_i = Input(UInt(4.W)) // mubi4_t
+
+ // SRAM interface
+ val req_o = Output(Bool())
+ val req_type_o = Output(UInt(4.W)) // mubi4_t
+ val gnt_i = Input(Bool())
+ val we_o = Output(Bool())
+ val addr_o = Output(UInt(sram_params.SramAw.W))
+ val wdata_o = Output(UInt(sram_params.SramDw.W))
+ val wmask_o = Output(UInt(sram_params.SramDw.W))
+ val intg_error_o = Output(Bool())
+ val rdata_i = Input(UInt(sram_params.SramDw.W))
+ val rvalid_i = Input(Bool())
+ val rerror_i = Input(UInt(2.W))
+ })
+}
diff --git a/hdl/chisel/src/chai/Uart.scala b/hdl/chisel/src/chai/Uart.scala
new file mode 100644
index 0000000..4fa3090
--- /dev/null
+++ b/hdl/chisel/src/chai/Uart.scala
@@ -0,0 +1,45 @@
+// 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._
+
+class Uart(tlul_p: kelvin.TLULParameters) extends BlackBox {
+ val io = IO(new Bundle {
+ val clk_i = Input(Clock())
+ val rst_ni = Input(AsyncReset())
+
+ val tl_i = Input(new kelvin.TileLinkULIO_H2D(tlul_p))
+ val tl_o = Output(new kelvin.TileLinkULIO_D2H(tlul_p))
+
+ // These have some alert_{rx|tx}_t types.
+ val alert_rx_i = Input(UInt(4.W))
+ val alert_tx_o = Output(UInt(2.W))
+
+ val cio_rx_i = Input(Bool())
+ val cio_tx_o = Output(Bool())
+ val cio_tx_en_o = Output(Bool())
+
+ val intr_tx_watermark_o = Output(Bool())
+ val intr_rx_watermark_o = Output(Bool())
+ val intr_tx_empty_o = Output(Bool())
+ val intr_rx_overflow_o = Output(Bool())
+ val intr_rx_frame_err_o = Output(Bool())
+ val intr_rx_break_err_o = Output(Bool())
+ val intr_rx_timeout_o = Output(Bool())
+ val intr_rx_parity_err_o = Output(Bool())
+ })
+}
diff --git a/hdl/chisel/src/kelvin/BUILD b/hdl/chisel/src/kelvin/BUILD
index be34cc6..a8eb9d6 100644
--- a/hdl/chisel/src/kelvin/BUILD
+++ b/hdl/chisel/src/kelvin/BUILD
@@ -50,6 +50,7 @@
"L1ICache.scala",
"Library.scala",
"Parameters.scala",
+ "TileLinkUL.scala",
"scalar/Alu.scala",
"scalar/Bru.scala",
"scalar/Csr.scala",
diff --git a/hdl/chisel/src/kelvin/Parameters.scala b/hdl/chisel/src/kelvin/Parameters.scala
index bb8a149..7c4b983 100644
--- a/hdl/chisel/src/kelvin/Parameters.scala
+++ b/hdl/chisel/src/kelvin/Parameters.scala
@@ -17,7 +17,21 @@
import chisel3._
import chisel3.util._
-case class Parameters() {
+class MemoryRegion(
+ val memStart: Int,
+ val memSize: Int,
+ val cacheable: Boolean,
+ val dataWidthBits: Int,
+) {
+
+def contains(addr: UInt): Bool = {
+ val addrWidth = addr.getWidth.W
+ (addr >= memStart.U(addrWidth)) && (addr < memStart.U(addrWidth) + memSize.U(addrWidth))
+}
+
+}
+
+case class Parameters(m: Seq[MemoryRegion] = Seq()) {
case object Core {
val tiny = 0
val little = 1
diff --git a/hdl/chisel/src/kelvin/TileLinkUL.scala b/hdl/chisel/src/kelvin/TileLinkUL.scala
new file mode 100644
index 0000000..155fa3d
--- /dev/null
+++ b/hdl/chisel/src/kelvin/TileLinkUL.scala
@@ -0,0 +1,127 @@
+// 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 kelvin
+
+import chisel3._
+import chisel3.util._
+import _root_.circt.stage.ChiselStage
+
+case class TLULParameters() {
+ val w = 32
+ val a = 32
+ val z = 6
+ val o = 10
+ val i = 1
+}
+
+object TLULOpcodesA extends ChiselEnum {
+ val PutFullData = Value(0.U(3.W))
+ val PutPartialData = Value(1.U(3.W))
+ val Get = Value(4.U(3.W))
+ val End = Value(7.U(3.W))
+}
+
+object TLULOpcodesD extends ChiselEnum {
+ val AccessAck = Value(0.U(3.W))
+ val AccessAckData = Value(1.U(3.W))
+ val End = Value(7.U(3.W))
+}
+
+class TileLinkULIO_H2D(p: TLULParameters) extends Bundle {
+ val a_valid = (Bool())
+ val a_opcode = (UInt(3.W))
+ val a_param = (UInt(3.W))
+ val a_size = (UInt(p.z.W))
+ val a_source = (UInt(p.o.W))
+ val a_address = (UInt(p.a.W))
+ val a_mask = (UInt(p.w.W))
+ val a_data = (UInt((8 * p.w).W))
+ val a_user = new Bundle {
+ val rsvd = UInt(5.W)
+ val instr_type = UInt(4.W) // mubi4_t
+ val cmd_intg = UInt(7.W)
+ val data_intg = UInt(7.W)
+ }
+ val d_ready = (Bool())
+}
+
+class TileLinkULIO_D2H(p: TLULParameters) extends Bundle {
+ val d_valid = (Bool())
+ val d_opcode = (UInt(3.W))
+ val d_param = (UInt(3.W))
+ val d_size = (UInt(p.z.W))
+ val d_source = (UInt(p.o.W))
+ val d_sink = (UInt(p.i.W))
+ val d_data = (UInt((8 * p.w).W))
+ val d_user = new Bundle {
+ val rsp_intg = UInt(7.W)
+ val data_intg = UInt(7.W)
+ }
+ val d_error = (Bool())
+ val a_ready = (Bool())
+}
+
+class TileLinkUL(p: TLULParameters, m: Seq[MemoryRegion], hosts: Int) extends Module {
+ val devices = m.length
+ val io = IO(new Bundle {
+ val hosts_a = Vec(hosts, Input(new TileLinkULIO_H2D(p)))
+ val hosts_d = Vec(hosts, Output(new TileLinkULIO_D2H(p)))
+ val devices_a = Vec(devices, Output(new TileLinkULIO_H2D(p)))
+ val devices_d = Vec(devices, Input(new TileLinkULIO_D2H(p)))
+ })
+
+
+ for (i <- 0 until hosts) {
+ io.hosts_d(i) := 0.U.asTypeOf(new TileLinkULIO_D2H(p))
+ }
+ for (i <- 0 until devices) {
+ io.devices_a(i) := 0.U.asTypeOf(new TileLinkULIO_H2D(p))
+ }
+
+ val aValids = io.hosts_a.map(x => x.a_valid)
+ val anyAValid = PopCount(aValids) > 0.U
+ when(anyAValid) {
+ val aValidIndex = PriorityEncoder(aValids)
+ val host_a = io.hosts_a(aValidIndex)
+ val host_d = io.hosts_d(aValidIndex)
+ val address = host_a.a_address
+
+ val addressOk = (0 until devices).map(x => m(x).contains(address))
+ val startAddresses = VecInit(m.map(x => x.memStart.U(p.a.W)))
+ assert(PopCount(addressOk) === 1.U)
+ val deviceIndex = PriorityEncoder(addressOk)
+ val device_a = io.devices_a(deviceIndex)
+ val device_d = io.devices_d(deviceIndex)
+
+ device_a :<>= host_a
+ device_a.a_address := host_a.a_address - startAddresses(deviceIndex)
+ host_d :<>= device_d
+ }
+
+ val dValids = io.devices_d.map(x => x.d_valid)
+ val anyDValid = dValids.reduce(_ || _)
+ when(anyDValid) {
+ val dValidIndex = PriorityEncoder(dValids)
+ val device_d = io.devices_d(dValidIndex)
+ val device_a = io.devices_a(dValidIndex)
+ val source = device_d.d_source
+ val sink = device_d.d_sink
+ val host_d = io.hosts_d(source)
+ val host_a = io.hosts_a(source)
+
+ host_d :<>= device_d
+ device_a :<>= host_a
+ }
+}
diff --git a/hdl/chisel/src/kelvin/scalar/Lsu.scala b/hdl/chisel/src/kelvin/scalar/Lsu.scala
index 520693b..60aa158 100644
--- a/hdl/chisel/src/kelvin/scalar/Lsu.scala
+++ b/hdl/chisel/src/kelvin/scalar/Lsu.scala
@@ -136,8 +136,10 @@
// Control Port Inputs.
ctrl.io.in.valid := io.req.map(_.valid).reduce(_||_)
+ val uncacheable = p.m.filter(x => !x.cacheable)
for (i <- 0 until 4) {
- val uncached = io.busPort.addr(i)(31)
+ val uncached = io.busPort.addr(i)(31) ||
+ (if (uncacheable.length > 0) uncacheable.map(x => (io.busPort.addr(i) >= x.memStart.U) && (io.busPort.addr(i) < (x.memStart + x.memSize).U)).reduce(_||_) else false.B)
val opstore = io.req(i).op(lsu.SW) || io.req(i).op(lsu.SH) || io.req(i).op(lsu.SB)
val opiload = io.req(i).op(lsu.LW) || io.req(i).op(lsu.LH) || io.req(i).op(lsu.LB) || io.req(i).op(lsu.LHU) || io.req(i).op(lsu.LBU)
@@ -218,7 +220,6 @@
io.ubus.size := ctrl.io.out.bits.size
io.ubus.wdata := wdata
io.ubus.wmask := wmask
- assert(!(io.ubus.valid && !ctrl.io.out.bits.addr(31)))
assert(!(io.ubus.valid && io.dbus.addr(31)))
assert(!(io.ubus.valid && io.dbus.adrx(31)))
diff --git a/hdl/chisel/src/matcha/Kelvin.scala b/hdl/chisel/src/matcha/Kelvin.scala
index 65c8da0..b8ed6cf 100644
--- a/hdl/chisel/src/matcha/Kelvin.scala
+++ b/hdl/chisel/src/matcha/Kelvin.scala
@@ -19,6 +19,19 @@
import common._
import _root_.circt.stage.ChiselStage
+class KelvinMemIO(p: kelvin.Parameters) extends Bundle {
+ val cvalid = (Output(Bool()))
+ val cready = (Input(Bool()))
+ val cwrite = (Output(Bool()))
+ val caddr = (Output(UInt(p.axiSysAddrBits.W)))
+ val cid = (Output(UInt(p.axiSysIdBits.W)))
+ val wdata = (Output(UInt(p.axiSysDataBits.W)))
+ val wmask = (Output(UInt((p.axiSysDataBits / 8).W)))
+ val rvalid = (Input(Bool()))
+ val rid = (Input(UInt(p.axiSysIdBits.W)))
+ val rdata = (Input(UInt(p.axiSysDataBits.W)))
+}
+
object Kelvin {
def apply(p: kelvin.Parameters): Kelvin = {
return Module(new Kelvin(p))
@@ -30,16 +43,7 @@
val clk_i = IO(Input(Clock()))
val rst_ni = IO(Input(AsyncReset()))
- val cvalid = IO(Output(Bool()))
- val cready = IO(Input(Bool()))
- val cwrite = IO(Output(Bool()))
- val caddr = IO(Output(UInt(p.axiSysAddrBits.W)))
- val cid = IO(Output(UInt(p.axiSysIdBits.W)))
- val wdata = IO(Output(UInt(p.axiSysDataBits.W)))
- val wmask = IO(Output(UInt((p.axiSysDataBits / 8).W)))
- val rvalid = IO(Input(Bool()))
- val rid = IO(Input(UInt(p.axiSysIdBits.W)))
- val rdata = IO(Input(UInt(p.axiSysDataBits.W)))
+ val mem = IO(new KelvinMemIO(p))
val clk_freeze = IO(Input(Bool()))
val ml_reset = IO(Input(Bool()))
@@ -118,16 +122,16 @@
// -------------------------------------------------------------------------
// SRAM bridge.
- cvalid := bus.io.out.cvalid
- bus.io.out.cready := cready
- cwrite := bus.io.out.cwrite
- caddr := bus.io.out.caddr
- cid := bus.io.out.cid
- wdata := bus.io.out.wdata
- wmask := bus.io.out.wmask
- bus.io.out.rvalid := rvalid
- bus.io.out.rid := rid
- bus.io.out.rdata := rdata
+ mem.cvalid := bus.io.out.cvalid
+ bus.io.out.cready := mem.cready
+ mem.cwrite := bus.io.out.cwrite
+ mem.caddr := bus.io.out.caddr
+ mem.cid := bus.io.out.cid
+ mem.wdata := bus.io.out.wdata
+ mem.wmask := bus.io.out.wmask
+ bus.io.out.rvalid := mem.rvalid
+ bus.io.out.rid := mem.rid
+ bus.io.out.rdata := mem.rdata
// -------------------------------------------------------------------------
// Command interface.
@@ -140,6 +144,6 @@
}
object EmitKelvin extends App {
- val p = new kelvin.Parameters()
+ val p = new kelvin.Parameters(Seq())
ChiselStage.emitSystemVerilogFile(new Kelvin(p), args)
}
diff --git a/hdl/verilog/BUILD b/hdl/verilog/BUILD
index 802e2db..440262a 100644
--- a/hdl/verilog/BUILD
+++ b/hdl/verilog/BUILD
@@ -16,16 +16,21 @@
exports_files(
srcs = [
- "ClockGate.v",
+ "ClockGate.sv",
"Sram_1rw_256x256.v",
"Sram_1rwm_256x288.v",
+ "TlulAdapterSram.sv",
+ "Uart.sv",
],
visibility = ["//visibility:public"],
)
verilog_library(
name = "clock_gate",
- srcs = ["ClockGate.v"],
+ srcs = ["ClockGate.sv"],
+ deps = [
+ "//third_party/ip/lowrisc:prim",
+ ],
visibility = ["//visibility:public"],
)
@@ -40,3 +45,22 @@
srcs = ["Sram_1rwm_256x288.v"],
visibility = ["//visibility:public"],
)
+
+verilog_library(
+ name = "tlul_adapter_sram",
+ srcs = ["TlulAdapterSram.sv"],
+ deps = [
+ "//third_party/ip/lowrisc:prim",
+ "//third_party/ip/lowrisc:tlul_adapter_sram",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "uart",
+ srcs = ["Uart.sv"],
+ deps = [
+ "//third_party/ip/lowrisc:uart",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/hdl/verilog/ClockGate.v b/hdl/verilog/ClockGate.sv
similarity index 67%
rename from hdl/verilog/ClockGate.v
rename to hdl/verilog/ClockGate.sv
index f6b9e7c..02c7f09 100644
--- a/hdl/verilog/ClockGate.v
+++ b/hdl/verilog/ClockGate.sv
@@ -17,22 +17,12 @@
input enable, // '1' passthrough, '0' disable.
output clk_o
);
-// Note: Bypass clock gate for now. It causes FPGA build failures and
-// simulation issues
-assign clk_o = clk_i;
-/*
-reg clk_en;
-`ifdef FPGA
- assign clk_o = clk_i;
-`else
- // Capture 'enable' during low phase of the clock.
- always @(clk_i or enable)
- begin
- if (~clk_i)
- clk_en = enable;
- end
- assign clk_o = clk_i & clk_en;
-`endif
-*/
+prim_clock_gating u_cg(
+ .clk_i(clk_i),
+ .en_i(enable),
+ .test_en_i('0),
+ .clk_o(clk_o)
+);
+
endmodule // ClockGate
diff --git a/hdl/verilog/TlulAdapterSram.sv b/hdl/verilog/TlulAdapterSram.sv
new file mode 100644
index 0000000..e1a295c
--- /dev/null
+++ b/hdl/verilog/TlulAdapterSram.sv
@@ -0,0 +1,113 @@
+// 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.
+
+module TlulAdapterSram
+import prim_mubi_pkg::mubi4_t;
+(
+ input clk_i,
+ input rst_ni,
+ input tl_i_a_valid,
+ input [2:0] tl_i_a_opcode,
+ input [2:0] tl_i_a_param,
+ input [5:0] tl_i_a_size,
+ input [9:0] tl_i_a_source,
+ input [31:0] tl_i_a_address,
+ input [31:0] tl_i_a_mask,
+ input [255:0] tl_i_a_data,
+ input [4:0] tl_i_a_user_rsvd,
+ input [3:0] tl_i_a_user_instr_type,
+ input [6:0] tl_i_a_user_cmd_intg,
+ input [6:0] tl_i_a_user_data_intg,
+ input tl_i_d_ready,
+ input [3:0] en_ifetch_i,
+ input gnt_i,
+ input [255:0] rdata_i,
+ input rvalid_i,
+ input [1:0] rerror_i,
+ output tl_o_d_valid,
+ output [2:0] tl_o_d_opcode,
+ output [2:0] tl_o_d_param,
+ output [5:0] tl_o_d_size,
+ output [9:0] tl_o_d_source,
+ output tl_o_d_sink,
+ output [255:0] tl_o_d_data,
+ output [6:0] tl_o_d_user_rsp_intg,
+ output [6:0] tl_o_d_user_data_intg,
+ output tl_o_d_error,
+ output tl_o_a_ready,
+ output req_o,
+ output [3:0] req_type_o,
+ output we_o,
+ output [16:0] addr_o,
+ output [255:0] wdata_o,
+ output [255:0] wmask_o,
+ output intg_error_o
+);
+
+mubi4_t en_ifetch_i_ = mubi4_t'(en_ifetch_i);
+
+tlul_adapter_sram #(
+ .SramAw(17),
+ .SramDw(256),
+ .Outstanding(1),
+ .ByteAccess(1),
+ .ErrOnRead(0),
+ .EnableDataIntgPt(0)
+) u_tlul_adapter_sram (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .tl_i(
+ {
+ tl_i_a_valid,
+ tl_i_a_opcode,
+ tl_i_a_param,
+ tl_i_a_size,
+ tl_i_a_source,
+ tl_i_a_address,
+ tl_i_a_mask,
+ tl_i_a_data,
+ tl_i_a_user_rsvd,
+ tl_i_a_user_instr_type,
+ tl_i_a_user_cmd_intg,
+ tl_i_a_user_data_intg,
+ tl_i_d_ready
+ }),
+ .tl_o({
+ tl_o_d_valid,
+ tl_o_d_opcode,
+ tl_o_d_param,
+ tl_o_d_size,
+ tl_o_d_source,
+ tl_o_d_sink,
+ tl_o_d_data,
+ tl_o_d_user_rsp_intg,
+ tl_o_d_user_data_intg,
+ tl_o_d_error,
+ tl_o_a_ready
+ }),
+ .en_ifetch_i(en_ifetch_i_),
+ .req_o(req_o),
+ .req_type_o(req_type_o),
+ .gnt_i(gnt_i),
+ .we_o(we_o),
+ .addr_o(addr_o),
+ .wdata_o(wdata_o),
+ .wmask_o(wmask_o),
+ .intg_error_o(intg_error_o),
+ .rdata_i(rdata_i),
+ .rvalid_i(rvalid_i),
+ .rerror_i(rerror_i)
+);
+
+endmodule
\ No newline at end of file
diff --git a/hdl/verilog/Uart.sv b/hdl/verilog/Uart.sv
new file mode 100644
index 0000000..b00a4b4
--- /dev/null
+++ b/hdl/verilog/Uart.sv
@@ -0,0 +1,109 @@
+// 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.
+
+module Uart(
+ input clk_i,
+ input rst_ni,
+ input tl_i_a_valid,
+ input [2:0] tl_i_a_opcode,
+ input [2:0] tl_i_a_param,
+ input [5:0] tl_i_a_size,
+ input [9:0] tl_i_a_source,
+ input [31:0] tl_i_a_address,
+ input [31:0] tl_i_a_mask,
+ input [255:0] tl_i_a_data,
+ input [4:0] tl_i_a_user_rsvd,
+ input [3:0] tl_i_a_user_instr_type,
+ input [6:0] tl_i_a_user_cmd_intg,
+ input [6:0] tl_i_a_user_data_intg,
+ input tl_i_d_ready,
+ output tl_o_d_valid,
+ output [2:0] tl_o_d_opcode,
+ output [2:0] tl_o_d_param,
+ output [5:0] tl_o_d_size,
+ output [9:0] tl_o_d_source,
+ output tl_o_d_sink,
+ output [255:0] tl_o_d_data,
+ output [6:0] tl_o_d_user_rsp_intg,
+ output [6:0] tl_o_d_user_data_intg,
+ output tl_o_d_error,
+ output tl_o_a_ready,
+
+ input [3:0] alert_rx_i,
+ output [1:0] alert_tx_o,
+
+ input cio_rx_i,
+ output cio_tx_o,
+ output cio_tx_en_o,
+
+ output intr_tx_watermark_o,
+ output intr_rx_watermark_o,
+ output intr_tx_empty_o,
+ output intr_rx_overflow_o,
+ output intr_rx_frame_err_o,
+ output intr_rx_break_err_o,
+ output intr_rx_timeout_o,
+ output intr_rx_parity_err_o
+);
+
+uart #() u_uart (
+ .clk_i(clk_i),
+ .rst_ni(rst_ni),
+ .tl_i(
+ {
+ tl_i_a_valid,
+ tl_i_a_opcode,
+ tl_i_a_param,
+ tl_i_a_size,
+ tl_i_a_source,
+ tl_i_a_address,
+ tl_i_a_mask,
+ tl_i_a_data,
+ tl_i_a_user_rsvd,
+ tl_i_a_user_instr_type,
+ tl_i_a_user_cmd_intg,
+ tl_i_a_user_data_intg,
+ tl_i_d_ready
+ }),
+ .tl_o({
+ tl_o_d_valid,
+ tl_o_d_opcode,
+ tl_o_d_param,
+ tl_o_d_size,
+ tl_o_d_source,
+ tl_o_d_sink,
+ tl_o_d_data,
+ tl_o_d_user_rsp_intg,
+ tl_o_d_user_data_intg,
+ tl_o_d_error,
+ tl_o_a_ready
+ }),
+ .alert_rx_i(alert_rx_i),
+ .alert_tx_o(alert_tx_o),
+
+ .cio_rx_i(cio_rx_i),
+ .cio_tx_o(cio_tx_o),
+ .cio_tx_en_o(cio_tx_en_o),
+
+ .intr_tx_watermark_o(intr_tx_watermark_o),
+ .intr_rx_watermark_o(intr_rx_watermark_o),
+ .intr_tx_empty_o(intr_tx_empty_o),
+ .intr_rx_overflow_o(intr_rx_overflow_o),
+ .intr_rx_frame_err_o(intr_rx_frame_err_o),
+ .intr_rx_break_err_o(intr_rx_break_err_o),
+ .intr_rx_timeout_o(intr_rx_timeout_o),
+ .intr_rx_parity_err_o(intr_rx_parity_err_o)
+);
+
+endmodule
\ No newline at end of file
diff --git a/rules/repos.bzl b/rules/repos.bzl
index b6e8e55..6a70d75 100644
--- a/rules/repos.bzl
+++ b/rules/repos.bzl
@@ -80,3 +80,16 @@
urls = ["https://repo1.maven.org/maven2/org/chipsalliance/llvm-firtool/1.52.0/llvm-firtool-1.52.0.jar"],
build_file = "@kelvin_hw//third_party/llvm-firtool:BUILD.bazel",
)
+
+ http_archive(
+ name = "lowrisc_opentitan",
+ sha256 = "cffed2c3c9c026ecb0b14a48b6cc300aa145bb2a316903dcb4cb7976ca8857af",
+ strip_prefix = "opentitan-f243e6802143374741739d2c164c4f2f61697669",
+ urls = ["https://github.com/lowrisc/opentitan/archive/f243e6802143374741739d2c164c4f2f61697669.zip"],
+ patches = [
+ "@kelvin_hw//third_party/ip/lowrisc:0001-Add-BUILD.bazel.patch",
+ "@kelvin_hw//third_party/ip/lowrisc:0002-Modify-TLUL-and-SRAM-adapter-for-ChAI.patch",
+ "@kelvin_hw//third_party/ip/lowrisc:0003-Modify-UART-for-ChAI.patch",
+ ],
+ patch_args = ["-p1"],
+ )
diff --git a/rules/verilator.bzl b/rules/verilator.bzl
index c00bad3..2f8fdd9 100644
--- a/rules/verilator.bzl
+++ b/rules/verilator.bzl
@@ -140,10 +140,16 @@
args.add("--Mdir", verilator_output.path)
args.add("--top-module", ctx.attr.module_top)
args.add("--prefix", prefix)
+ verilog_dirs = dict()
+ for file in verilog_files:
+ verilog_dirs[file.dirname] = None
+ for vdir in verilog_dirs:
+ args.add("-I" + vdir)
if ctx.attr.trace:
args.add("--trace")
for verilog_file in verilog_files:
args.add(verilog_file.path)
+ args.add("-Wno-UNOPTFLAT")
args.add_all(ctx.attr.vopts, expand_directories = False)
ctx.actions.run(
diff --git a/tests/verilator_sim/BUILD b/tests/verilator_sim/BUILD
index 681096f..10c126e 100644
--- a/tests/verilator_sim/BUILD
+++ b/tests/verilator_sim/BUILD
@@ -66,6 +66,25 @@
],
)
+cc_binary(
+ name = "chai_sim",
+ srcs = [
+ "chai/chai_if.h",
+ "chai/chai_tb.cc",
+ ],
+ deps = [
+ ":kelvin_if",
+ ":sim_libs",
+ "//hdl/chisel/src/chai:chai_cc_library",
+ "@com_google_absl//absl/flags:flag",
+ "@com_google_absl//absl/flags:parse",
+ "@com_google_absl//absl/flags:usage",
+ "@com_google_absl//absl/log",
+ "@com_google_absl//absl/log:check",
+ ],
+)
+
+
cc_test(
name = "dbus2axi_tb",
size = "small",
diff --git a/tests/verilator_sim/chai/chai_if.h b/tests/verilator_sim/chai/chai_if.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/verilator_sim/chai/chai_if.h
diff --git a/tests/verilator_sim/chai/chai_tb.cc b/tests/verilator_sim/chai/chai_tb.cc
new file mode 100644
index 0000000..74fa133
--- /dev/null
+++ b/tests/verilator_sim/chai/chai_tb.cc
@@ -0,0 +1,245 @@
+// 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.
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <algorithm>
+
+#include "VChAI.h" // Generated
+#include "absl/flags/flag.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/usage.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
+#include "tests/verilator_sim/sysc_module.h"
+#include "tests/verilator_sim/sysc_tb.h"
+
+ABSL_FLAG(int, cycles, 10'000'000, "Simulation cycles");
+ABSL_FLAG(bool, trace, false, "Enable tracing");
+
+namespace {
+
+struct ChAI_tb : Sysc_tb {
+ sc_in<bool> io_halted;
+ sc_in<bool> io_fault;
+ using Sysc_tb::Sysc_tb; // constructor
+
+ void posedge() {
+ check(!io_fault, "io_fault");
+ if (io_halted) sc_stop();
+ }
+};
+
+struct Memory : Sysc_module {
+ sc_out<sc_bv<17> > write_address;
+ sc_out<bool> write_enable;
+ sc_out<sc_bv<256> > write_data;
+ sc_out<bool> loadedn;
+
+ sc_bv<256> wdata = 0;
+
+ Memory(sc_module_name n, const char* path)
+ : Sysc_module(n), path_(path), offset_(0) {
+ int fd = open(path, 0);
+ CHECK(fd > 0);
+ struct stat sb;
+ CHECK(fstat(fd, &sb) == 0);
+ LOG(INFO) << "Input file size: " << sb.st_size;
+ size_ = sb.st_size;
+ if (size_ % 256 != 0) {
+ LOG(FATAL) << "Please align your file size to 256 bytes.";
+ }
+ void* data = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ CHECK(data != MAP_FAILED);
+ close(fd);
+ data_ = reinterpret_cast<uint8_t*>(data);
+ data32_ = reinterpret_cast<uint32_t*>(data_);
+ }
+
+ ~Memory() {
+ LOG(INFO) << "Cycles at teardown: " << cycle_;
+ munmap(data_, size_);
+ data_ = nullptr;
+ data32_ = nullptr;
+ }
+
+ void eval() {
+ if (reset) {
+ cycle_ = 0;
+ loadedn = true;
+ write_address = 0;
+ write_enable = false;
+ write_data = 0;
+ }
+ if (clock->posedge()) {
+ cycle_++;
+ if (offset_ == size_) {
+ static bool logged = false;
+ if (!logged) {
+ LOG(INFO) << "[" << cycle_ << "] setting loadedn to false";
+ logged = true;
+ }
+ loadedn = false;
+ write_enable = false;
+ }
+ if (offset_ < size_) {
+ const size_t wordsPerWrite = 32 / sizeof(uint32_t); // 32B / 4B
+ for (size_t i = 0; i < wordsPerWrite; i++) {
+ uint32_t val = data32_[(offset_ / sizeof(uint32_t)) + i];
+ wdata.set_word(i, val);
+ }
+ write_data.write(wdata);
+ write_enable = true;
+ write_address = offset_ >> 5;
+ offset_ += 32; // 32 bytes == 8 words
+ }
+ }
+ if (cycle_ % 10000 == 0) {
+ LOG(INFO) << "Cycle " << cycle_;
+ }
+ }
+
+ private:
+ uint32_t cycle_ = 0;
+ const char* path_;
+ size_t offset_; // bytes
+ size_t size_; // bytes
+ uint8_t* data_; // bytes
+ uint32_t* data32_; // words
+};
+
+struct Uart : Sysc_module {
+ sc_in<bool> rx;
+ sc_out<bool> tx;
+ Uart(sc_module_name n) : Sysc_module(n) {}
+ uint64_t kBaudrate = 115200;
+ uint64_t kFrequencyHz = 10000000; // 10MHz
+ uint32_t nco_rx = static_cast<uint32_t>((kBaudrate << 20) / kFrequencyHz);
+ void eval() {
+ if (reset) {
+ last_rx_val_ = true;
+ uart_baud_ctr_ = 0;
+ baud_cnt_ = 0;
+ s_ = State::sIdle;
+ bit_in_pkt_ = 0;
+ rx_data_ = 0;
+ }
+ if (clock->posedge()) {
+ if (uart_baud_ctr_ & 0x10000) {
+ baud_cnt_++;
+ }
+ if (baud_cnt_ == 16) {
+ bool rx_val = rx;
+ bool edge = rx_val != last_rx_val_;
+ switch (s_) {
+ case State::sIdle: {
+ if (edge) {
+ s_ = State::sStarted;
+ bit_in_pkt_ = 0;
+ }
+ break;
+ }
+ case State::sStarted: {
+ if (bit_in_pkt_ == 8) {
+ LOG(INFO) << "UART val: " << (char)rx_data_;
+ rx_data_ = 0;
+ s_ = State::sIdle;
+ }
+ rx_data_ = (rx_data_ >> 1) | ((uint8_t)rx_val << 7);
+ bit_in_pkt_++;
+ break;
+ }
+ }
+ last_rx_val_ = rx_val;
+ baud_cnt_ = 0;
+ }
+ uart_baud_ctr_ = (uart_baud_ctr_ & 0xFFFF) + nco_rx;
+ }
+ }
+
+ private:
+ enum class State { sIdle, sStarted };
+ bool last_rx_val_ = true;
+ size_t uart_baud_ctr_ = 0;
+ size_t baud_cnt_ = 0;
+ State s_ = State::sIdle;
+ size_t bit_in_pkt_ = 0;
+ uint8_t rx_data_ = 0;
+};
+
+void ChAI_run(const char* name, const char* path, const int cycles,
+ const bool trace) {
+ VChAI chai(name);
+ ChAI_tb tb("ChAI_tb", cycles, /* random= */ false);
+ Memory mem("ChAI_mem", path);
+ Uart uart("ChAI_uart");
+
+ sc_signal<bool> io_halted, io_fault;
+ sc_signal<sc_bv<17> > io_sram_write_address;
+ sc_signal<bool> io_sram_write_enable;
+ sc_signal<sc_bv<256> > io_sram_write_data;
+ sc_signal<bool> mem_loadedn;
+ sc_signal<bool> uart_tx; // Output from ChAI
+ sc_signal<bool> uart_rx; // Input to ChAI
+
+ tb.io_halted(io_halted);
+ tb.io_fault(io_fault);
+
+ chai.io_clk_i(tb.clock);
+ chai.io_rst_ni(tb.resetn);
+ chai.io_sram_write_address(io_sram_write_address);
+ chai.io_sram_write_enable(io_sram_write_enable);
+ chai.io_sram_write_data(io_sram_write_data);
+ chai.io_finish(io_halted);
+ chai.io_fault(io_fault);
+ chai.io_freeze(mem_loadedn);
+ chai.io_uart_tx(uart_tx);
+ chai.io_uart_rx(uart_rx);
+
+ mem.clock(tb.clock);
+ mem.reset(tb.reset);
+ mem.write_address(io_sram_write_address);
+ mem.write_enable(io_sram_write_enable);
+ mem.write_data(io_sram_write_data);
+ mem.loadedn(mem_loadedn);
+
+ uart.clock(tb.clock);
+ uart.reset(tb.reset);
+ uart.rx(uart_tx);
+ uart.tx(uart_rx);
+
+ if (trace) {
+ tb.trace(chai);
+ }
+
+ tb.start();
+}
+
+} // namespace
+
+extern "C" int sc_main(int argc, char** argv) {
+ absl::SetProgramUsageMessage("ChAI sim");
+ auto out_args = absl::ParseCommandLine(argc, argv);
+ argc = out_args.size();
+ argv = &out_args[0];
+ if (argc < 2) {
+ LOG(FATAL) << "Need an input file";
+ }
+ const char* path = argv[1];
+ ChAI_run(Sysc_tb::get_name(argv[0]), path, absl::GetFlag(FLAGS_cycles),
+ absl::GetFlag(FLAGS_trace));
+ return 0;
+}
\ No newline at end of file
diff --git a/tests/verilator_sim/matcha/kelvin_tb.cc b/tests/verilator_sim/matcha/kelvin_tb.cc
index fe1a765..5211117 100644
--- a/tests/verilator_sim/matcha/kelvin_tb.cc
+++ b/tests/verilator_sim/matcha/kelvin_tb.cc
@@ -78,16 +78,16 @@
core.slog_addr(slog_addr);
core.slog_data(slog_data);
- core.cvalid(cvalid);
- core.cready(cready);
- core.cwrite(cwrite);
- core.caddr(caddr);
- core.cid(cid);
- core.wdata(wdata);
- core.wmask(wmask);
- core.rvalid(rvalid);
- core.rid(rid);
- core.rdata(rdata);
+ core.mem_cvalid(cvalid);
+ core.mem_cready(cready);
+ core.mem_cwrite(cwrite);
+ core.mem_caddr(caddr);
+ core.mem_cid(cid);
+ core.mem_wdata(wdata);
+ core.mem_wmask(wmask);
+ core.mem_rvalid(rvalid);
+ core.mem_rid(rid);
+ core.mem_rdata(rdata);
mif.clock(tb.clock);
mif.reset(tb.reset);
diff --git a/third_party/ip/lowrisc/0001-Add-BUILD.bazel.patch b/third_party/ip/lowrisc/0001-Add-BUILD.bazel.patch
new file mode 100644
index 0000000..2ab35be
--- /dev/null
+++ b/third_party/ip/lowrisc/0001-Add-BUILD.bazel.patch
@@ -0,0 +1,37 @@
+From 35d1dec2153a5d5e9f45d86215708d046d05f85a Mon Sep 17 00:00:00 2001
+From: Alex Van Damme <atv@google.com>
+Date: Thu, 15 Feb 2024 11:25:11 -0800
+Subject: [PATCH 1/3] Add BUILD.bazel
+
+---
+ hw/BUILD.bazel | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+ create mode 100644 hw/BUILD.bazel
+
+diff --git a/hw/BUILD.bazel b/hw/BUILD.bazel
+new file mode 100644
+index 0000000000..7f502f35ea
+--- /dev/null
++++ b/hw/BUILD.bazel
+@@ -0,0 +1,18 @@
++# 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.
++
++exports_files(
++ glob(["vendor/lowrisc_ibex/dv/uvm/core_ibex/common/prim/*.sv*"]),
++)
++
+--
+2.43.0.687.g38aa6559b0-goog
+
diff --git a/third_party/ip/lowrisc/0002-Modify-TLUL-and-SRAM-adapter-for-ChAI.patch b/third_party/ip/lowrisc/0002-Modify-TLUL-and-SRAM-adapter-for-ChAI.patch
new file mode 100644
index 0000000..3d104a1
--- /dev/null
+++ b/third_party/ip/lowrisc/0002-Modify-TLUL-and-SRAM-adapter-for-ChAI.patch
@@ -0,0 +1,180 @@
+From 617fc52a30d18725e50080e64bc6459fa24ca709 Mon Sep 17 00:00:00 2001
+From: Alex Van Damme <atv@google.com>
+Date: Thu, 15 Feb 2024 11:24:49 -0800
+Subject: [PATCH 2/3] Modify TLUL and SRAM adapter for ChAI
+
+---
+ hw/ip/tlul/rtl/tlul_adapter_reg.sv | 12 +++++-------
+ hw/ip/tlul/rtl/tlul_adapter_sram.sv | 21 +++------------------
+ hw/ip/tlul/rtl/tlul_err.sv | 15 ++++++++++-----
+ hw/ip/tlul/rtl/tlul_pkg.sv | 18 ------------------
+ 4 files changed, 18 insertions(+), 48 deletions(-)
+
+diff --git a/hw/ip/tlul/rtl/tlul_adapter_reg.sv b/hw/ip/tlul/rtl/tlul_adapter_reg.sv
+index ac48750129..85e89d63f4 100644
+--- a/hw/ip/tlul/rtl/tlul_adapter_reg.sv
++++ b/hw/ip/tlul/rtl/tlul_adapter_reg.sv
+@@ -82,8 +82,8 @@ module tlul_adapter_reg
+
+ assign we_o = wr_req & ~err_internal;
+ assign re_o = rd_req & ~err_internal;
+- assign wdata_o = tl_i.a_data;
+- assign be_o = tl_i.a_mask;
++ assign wdata_o = tl_i.a_data[RegDw-1:0];
++ assign be_o = tl_i.a_mask[RegBw-1:0];
+
+ if (RegAw <= 2) begin : gen_only_one_reg
+ assign addr_o = '0;
+@@ -161,7 +161,7 @@ module tlul_adapter_reg
+ d_size: reqsz_q,
+ d_source: reqid_q,
+ d_sink: '0,
+- d_data: rdata,
++ d_data: {224'b0, rdata},
+ d_user: '0,
+ d_error: error
+ };
+@@ -201,14 +201,12 @@ module tlul_adapter_reg
+
+ // An instruction type transaction is only valid if en_ifetch is enabled
+ // If the instruction type is completely invalid, also considered an instruction error
+- assign instr_error = prim_mubi_pkg::mubi4_test_invalid(tl_i.a_user.instr_type) |
+- (prim_mubi_pkg::mubi4_test_true_strict(tl_i.a_user.instr_type) &
+- prim_mubi_pkg::mubi4_test_false_loose(en_ifetch_i));
++ assign instr_error = '0;
+
+ assign err_internal = addr_align_err | malformed_meta_err | tl_err | instr_error | intg_error;
+
+ // Don't allow unsupported values.
+- assign malformed_meta_err = tl_a_user_chk(tl_i.a_user);
++ assign malformed_meta_err = '0;
+
+ // addr_align_err
+ // Raised if addr isn't aligned with the size
+diff --git a/hw/ip/tlul/rtl/tlul_adapter_sram.sv b/hw/ip/tlul/rtl/tlul_adapter_sram.sv
+index ec764cbefa..8f41f38581 100644
+--- a/hw/ip/tlul/rtl/tlul_adapter_sram.sv
++++ b/hw/ip/tlul/rtl/tlul_adapter_sram.sv
+@@ -106,7 +106,7 @@ module tlul_adapter_sram
+ // Here it checks any partial write if ByteAccess isn't allowed.
+ assign wr_attr_error = (tl_i.a_opcode == PutFullData || tl_i.a_opcode == PutPartialData)
+ ? ((ByteAccess == 0) ?
+- (tl_i.a_mask != '1 || tl_i.a_size != 2'h2) : 1'b0)
++ (tl_i.a_mask != '1 || tl_i.a_size != 6'h2) : 1'b0)
+ : 1'b0;
+
+ // An instruction type transaction is only valid if en_ifetch is enabled
+@@ -268,24 +268,9 @@ module tlul_adapter_sram
+ DataWhenInstrError :
+ DataWhenError;
+
+- // Since DataWhenInstrError and DataWhenError can be arbitrary parameters
+- // we statically calculate the correct integrity values for these parameters here so that
+- // they do not have to be supplied externally.
+- logic [top_pkg::TL_DW-1:0] unused_instr, unused_data;
+- logic [DataIntgWidth-1:0] error_instr_integ, error_data_integ;
+- tlul_data_integ_enc u_tlul_data_integ_enc_instr (
+- .data_i(DataMaxWidth'(DataWhenInstrError)),
+- .data_intg_o({error_instr_integ, unused_instr})
+- );
+- tlul_data_integ_enc u_tlul_data_integ_enc_data (
+- .data_i(DataMaxWidth'(DataWhenError)),
+- .data_intg_o({error_data_integ, unused_data})
+- );
+
+ logic [DataIntgWidth-1:0] error_blanking_integ;
+- assign error_blanking_integ = (prim_mubi_pkg::mubi4_test_true_strict(reqfifo_rdata.instr_type)) ?
+- error_instr_integ :
+- error_data_integ;
++ assign error_blanking_integ = '0;
+
+ logic [top_pkg::TL_DW-1:0] d_data;
+ assign d_data = (vld_rd_rsp & ~d_error) ? rspfifo_rdata.data // valid read
+@@ -445,7 +430,7 @@ module tlul_adapter_sram
+ error : rerror_i[1] // Only care for Uncorrectable error
+ };
+ assign rspfifo_rready = (reqfifo_rdata.op == OpRead & ~reqfifo_rdata.error)
+- ? reqfifo_rready : 1'b0 ;
++ ? reqfifo_rready : 1'b1 ;
+
+ // This module only cares about uncorrectable errors.
+ logic unused_rerror;
+diff --git a/hw/ip/tlul/rtl/tlul_err.sv b/hw/ip/tlul/rtl/tlul_err.sv
+index c887cc387b..6cb3ea380a 100644
+--- a/hw/ip/tlul/rtl/tlul_err.sv
++++ b/hw/ip/tlul/rtl/tlul_err.sv
+@@ -29,11 +29,10 @@ module tlul_err import tlul_pkg::*; (
+
+ // An instruction type transaction cannot be write
+ logic instr_wr_err;
+- assign instr_wr_err = prim_mubi_pkg::mubi4_test_true_strict(tl_i.a_user.instr_type) &
+- (op_full | op_partial);
++ assign instr_wr_err = '0;
+
+ logic instr_type_err;
+- assign instr_type_err = prim_mubi_pkg::mubi4_test_invalid(tl_i.a_user.instr_type);
++ assign instr_type_err = '0;
+
+ // Anything that doesn't fall into the permitted category, it raises an error
+ assign err_o = ~(opcode_allowed & a_config_allowed) | instr_wr_err | instr_type_err;
+@@ -68,8 +67,8 @@ module tlul_err import tlul_pkg::*; (
+ 'h1: begin // 2 Byte
+ addr_sz_chk = ~tl_i.a_address[0];
+ // check inactive lanes if lower 2B, check a_mask[3:2], if uppwer 2B, a_mask[1:0]
+- mask_chk = (tl_i.a_address[1]) ? ~|(tl_i.a_mask & 4'b0011)
+- : ~|(tl_i.a_mask & 4'b1100);
++ mask_chk = (tl_i.a_address[1]) ? ~|(tl_i.a_mask & 32'b0011)
++ : ~|(tl_i.a_mask & 32'b1100);
+ fulldata_chk = (tl_i.a_address[1]) ? &tl_i.a_mask[3:2] : &tl_i.a_mask[1:0] ;
+ end
+
+@@ -79,6 +78,12 @@ module tlul_err import tlul_pkg::*; (
+ fulldata_chk = &tl_i.a_mask[3:0];
+ end
+
++ 'h5: begin // 32 Byte
++ addr_sz_chk = 1'b1;
++ mask_chk = 1'b1;
++ fulldata_chk = 1'b1;
++ end
++
+ default: begin // else
+ addr_sz_chk = 1'b0;
+ mask_chk = 1'b0;
+diff --git a/hw/ip/tlul/rtl/tlul_pkg.sv b/hw/ip/tlul/rtl/tlul_pkg.sv
+index 4e9401fdf9..dae9671f25 100644
+--- a/hw/ip/tlul/rtl/tlul_pkg.sv
++++ b/hw/ip/tlul/rtl/tlul_pkg.sv
+@@ -179,17 +179,6 @@ package tlul_pkg;
+ return cmd_intg;
+ endfunction // get_cmd_intg
+
+- // calculate ecc for data checking
+- function automatic logic [DataIntgWidth-1:0] get_data_intg(logic [top_pkg::TL_DW-1:0] data);
+- logic [DataIntgWidth-1:0] data_intg;
+- logic [top_pkg::TL_DW-1:0] unused_data;
+- logic [DataIntgWidth + top_pkg::TL_DW - 1 : 0] enc_data;
+- enc_data = prim_secded_pkg::prim_secded_inv_39_32_enc(data);
+- data_intg = enc_data[DataIntgWidth + top_pkg::TL_DW - 1 : top_pkg::TL_DW];
+- unused_data = enc_data[top_pkg::TL_DW - 1 : 0];
+- return data_intg;
+- endfunction // get_data_intg
+-
+ // return inverted integrity for command payload
+ function automatic logic [H2DCmdIntgWidth-1:0] get_bad_cmd_intg(tl_h2d_t tl);
+ logic [H2DCmdIntgWidth-1:0] cmd_intg;
+@@ -197,11 +186,4 @@ package tlul_pkg;
+ return ~cmd_intg;
+ endfunction // get_bad_cmd_intg
+
+- // return inverted integrity for data payload
+- function automatic logic [H2DCmdIntgWidth-1:0] get_bad_data_intg(logic [top_pkg::TL_DW-1:0] data);
+- logic [H2DCmdIntgWidth-1:0] data_intg;
+- data_intg = get_data_intg(data);
+- return ~data_intg;
+- endfunction // get_bad_data_intg
+-
+ endpackage
+--
+2.43.0.687.g38aa6559b0-goog
+
diff --git a/third_party/ip/lowrisc/0003-Modify-UART-for-ChAI.patch b/third_party/ip/lowrisc/0003-Modify-UART-for-ChAI.patch
new file mode 100644
index 0000000..a68a3e7
--- /dev/null
+++ b/third_party/ip/lowrisc/0003-Modify-UART-for-ChAI.patch
@@ -0,0 +1,84 @@
+From 37adcc443c2d7879079ca6e634f2992dbc9bfac8 Mon Sep 17 00:00:00 2001
+From: Alex Van Damme <atv@google.com>
+Date: Wed, 14 Feb 2024 15:29:54 -0800
+Subject: [PATCH 3/3] Modify UART for ChAI
+
+---
+ hw/ip/uart/rtl/uart_reg_pkg.sv | 28 ++++++++++++++--------------
+ hw/ip/uart/rtl/uart_reg_top.sv | 7 ++-----
+ 2 files changed, 16 insertions(+), 19 deletions(-)
+
+diff --git a/hw/ip/uart/rtl/uart_reg_pkg.sv b/hw/ip/uart/rtl/uart_reg_pkg.sv
+index 355afaff1b..8a44cd5af8 100644
+--- a/hw/ip/uart/rtl/uart_reg_pkg.sv
++++ b/hw/ip/uart/rtl/uart_reg_pkg.sv
+@@ -10,7 +10,7 @@ package uart_reg_pkg;
+ parameter int NumAlerts = 1;
+
+ // Address widths within the block
+- parameter int BlockAw = 6;
++ parameter int BlockAw = 9;
+
+ ////////////////////////////
+ // Typedefs for registers //
+@@ -324,19 +324,19 @@ package uart_reg_pkg;
+ } uart_hw2reg_t;
+
+ // Register offsets
+- parameter logic [BlockAw-1:0] UART_INTR_STATE_OFFSET = 6'h 0;
+- parameter logic [BlockAw-1:0] UART_INTR_ENABLE_OFFSET = 6'h 4;
+- parameter logic [BlockAw-1:0] UART_INTR_TEST_OFFSET = 6'h 8;
+- parameter logic [BlockAw-1:0] UART_ALERT_TEST_OFFSET = 6'h c;
+- parameter logic [BlockAw-1:0] UART_CTRL_OFFSET = 6'h 10;
+- parameter logic [BlockAw-1:0] UART_STATUS_OFFSET = 6'h 14;
+- parameter logic [BlockAw-1:0] UART_RDATA_OFFSET = 6'h 18;
+- parameter logic [BlockAw-1:0] UART_WDATA_OFFSET = 6'h 1c;
+- parameter logic [BlockAw-1:0] UART_FIFO_CTRL_OFFSET = 6'h 20;
+- parameter logic [BlockAw-1:0] UART_FIFO_STATUS_OFFSET = 6'h 24;
+- parameter logic [BlockAw-1:0] UART_OVRD_OFFSET = 6'h 28;
+- parameter logic [BlockAw-1:0] UART_VAL_OFFSET = 6'h 2c;
+- parameter logic [BlockAw-1:0] UART_TIMEOUT_CTRL_OFFSET = 6'h 30;
++ parameter logic [BlockAw-1:0] UART_INTR_STATE_OFFSET = 9'h 0;
++ parameter logic [BlockAw-1:0] UART_INTR_ENABLE_OFFSET = 9'h 20;
++ parameter logic [BlockAw-1:0] UART_INTR_TEST_OFFSET = 9'h 40;
++ parameter logic [BlockAw-1:0] UART_ALERT_TEST_OFFSET = 9'h 60;
++ parameter logic [BlockAw-1:0] UART_CTRL_OFFSET = 9'h 80;
++ parameter logic [BlockAw-1:0] UART_STATUS_OFFSET = 9'h a0;
++ parameter logic [BlockAw-1:0] UART_RDATA_OFFSET = 9'h c0;
++ parameter logic [BlockAw-1:0] UART_WDATA_OFFSET = 9'h e0;
++ parameter logic [BlockAw-1:0] UART_FIFO_CTRL_OFFSET = 9'h 100;
++ parameter logic [BlockAw-1:0] UART_FIFO_STATUS_OFFSET = 9'h120 ;
++ parameter logic [BlockAw-1:0] UART_OVRD_OFFSET = 9'h 140;
++ parameter logic [BlockAw-1:0] UART_VAL_OFFSET = 9'h 160;
++ parameter logic [BlockAw-1:0] UART_TIMEOUT_CTRL_OFFSET = 9'h180;
+
+ // Reset values for hwext registers and their fields
+ parameter logic [7:0] UART_INTR_TEST_RESVAL = 8'h 0;
+diff --git a/hw/ip/uart/rtl/uart_reg_top.sv b/hw/ip/uart/rtl/uart_reg_top.sv
+index 6b6952f5d8..b105550cc4 100644
+--- a/hw/ip/uart/rtl/uart_reg_top.sv
++++ b/hw/ip/uart/rtl/uart_reg_top.sv
+@@ -24,7 +24,7 @@ module uart_reg_top (
+
+ import uart_reg_pkg::* ;
+
+- localparam int AW = 6;
++ localparam int AW = 9;
+ localparam int DW = 32;
+ localparam int DBW = DW/8; // Byte Width
+
+@@ -48,10 +48,7 @@ module uart_reg_top (
+
+ // incoming payload check
+ logic intg_err;
+- tlul_cmd_intg_chk u_chk (
+- .tl_i(tl_i),
+- .err_o(intg_err)
+- );
++ assign intg_err = '0;
+
+ // also check for spurious write enables
+ logic reg_we_err;
+--
+2.43.0.687.g38aa6559b0-goog
+
diff --git a/third_party/ip/lowrisc/BUILD b/third_party/ip/lowrisc/BUILD
new file mode 100644
index 0000000..0a97a9c
--- /dev/null
+++ b/third_party/ip/lowrisc/BUILD
@@ -0,0 +1,136 @@
+# 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.
+
+load("@rules_hdl//verilog:providers.bzl", "verilog_library")
+
+verilog_library(
+ name = "prim_generic",
+ srcs = [
+ "@lowrisc_opentitan//hw/ip/prim_generic:rtl/prim_generic_buf.sv",
+ "@lowrisc_opentitan//hw/ip/prim_generic:rtl/prim_generic_clock_gating.sv",
+ "@lowrisc_opentitan//hw/ip/prim_generic:rtl/prim_generic_flop.sv",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "prim_xilinx",
+ srcs = [
+ "@lowrisc_opentitan//hw/ip/prim_xilinx:rtl/prim_xilinx_clock_gating.sv",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "prim",
+ # Do not sort: "*_pkg" comes first.
+ srcs = [
+ "@lowrisc_opentitan//hw:vendor/lowrisc_ibex/dv/uvm/core_ibex/common/prim/prim_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_alert_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_mubi_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_secded_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_subreg_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_util_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_alert_sender.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_assert.sv",
+ # Verilator
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_assert_dummy_macros.svh",
+ # Synth
+ # "@lowrisc_opentitan//hw/ip/prim:rtl/prim_assert_standard_macros.svh",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_assert_sec_cm.svh",
+ "@lowrisc_opentitan//hw:vendor/lowrisc_ibex/dv/uvm/core_ibex/common/prim/prim_buf.sv",
+ "@lowrisc_opentitan//hw:vendor/lowrisc_ibex/dv/uvm/core_ibex/common/prim/prim_clock_gating.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_count.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_diff_decode.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_fifo_sync.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_fifo_sync_cnt.sv",
+ "@lowrisc_opentitan//hw:vendor/lowrisc_ibex/dv/uvm/core_ibex/common/prim/prim_flop.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_flop_2sync.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_flop_macros.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_intr_hw.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_onehot_check.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_reg_we_check.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_sec_anchor_buf.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_sec_anchor_flop.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_secded_inv_64_57_dec.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_secded_inv_39_32_dec.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_secded_inv_39_32_enc.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_secded_inv_64_57_enc.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_subreg.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_subreg_arb.sv",
+ "@lowrisc_opentitan//hw/ip/prim:rtl/prim_subreg_ext.sv",
+ ],
+ deps = [
+ ":prim_generic",
+ ":prim_xilinx",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "top",
+ srcs = [
+ "top_pkg.sv",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "tlul",
+ # Do not sort: "tlul_pkg" comes first.
+ srcs = [
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_adapter_reg.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_cmd_intg_chk.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_data_integ_dec.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_data_integ_enc.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_err.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_rsp_intg_gen.sv",
+ ],
+ deps = [
+ ":top",
+ ":prim",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "tlul_adapter_sram",
+ srcs = [
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_adapter_sram.sv",
+ "@lowrisc_opentitan//hw/ip/tlul:rtl/tlul_sram_byte.sv",
+ ],
+ deps = [
+ ":prim",
+ ":tlul",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+verilog_library(
+ name = "uart",
+ srcs = [
+ "@lowrisc_opentitan//hw/ip/uart:rtl/uart_reg_pkg.sv",
+ "@lowrisc_opentitan//hw/ip/uart:rtl/uart_core.sv",
+ "@lowrisc_opentitan//hw/ip/uart:rtl/uart_reg_top.sv",
+ "@lowrisc_opentitan//hw/ip/uart:rtl/uart_rx.sv",
+ "@lowrisc_opentitan//hw/ip/uart:rtl/uart_tx.sv",
+ "@lowrisc_opentitan//hw/ip/uart:rtl/uart.sv",
+ ],
+ deps = [
+ ":prim",
+ ":tlul",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/third_party/ip/lowrisc/top_pkg.sv b/third_party/ip/lowrisc/top_pkg.sv
new file mode 100644
index 0000000..0af4c75
--- /dev/null
+++ b/third_party/ip/lowrisc/top_pkg.sv
@@ -0,0 +1,27 @@
+// Copyright 2024 Google LLC
+// Copyright lowRISC contributors
+//
+// 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 top_pkg;
+
+localparam int TL_AW=32;
+localparam int TL_DW=256; // = TL_DBW * 8; TL_DBW must be a power-of-two
+localparam int TL_AIW=10; // a_source, d_source
+localparam int TL_DIW=1; // d_sink
+localparam int TL_AUW=21; // a_user
+localparam int TL_DUW=14; // d_user
+localparam int TL_DBW=(TL_DW>>3);
+localparam int TL_SZW=6;
+
+endpackage