| // Copyright 2023 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 matcha |
| |
| import chisel3._ |
| import chisel3.util._ |
| 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)) |
| } |
| } |
| |
| class Kelvin(p: kelvin.Parameters) extends RawModule { |
| // IO ports. (RawModule removes default[clock, reset]) |
| val clk_i = IO(Input(Clock())) |
| val rst_ni = IO(Input(AsyncReset())) |
| |
| val mem = IO(new KelvinMemIO(p)) |
| |
| val clk_freeze = IO(Input(Bool())) |
| val ml_reset = IO(Input(Bool())) |
| val pc_start = IO(Input(UInt(32.W))) |
| val volt_sel = IO(Input(Bool())) |
| val debug_req = IO(Input(Bool())) |
| |
| val finish = IO(Output(Bool())) |
| val host_req = IO(Output(Bool())) |
| val fault = IO(Output(Bool())) |
| |
| val slog = IO(new kelvin.SLogIO(p)) |
| |
| // --------------------------------------------------------------------------- |
| // Gated Clock. |
| val cg = Module(new kelvin.ClockGate()) |
| cg.io.clk_i := clk_i |
| cg.io.enable := !clk_freeze |
| val clk_g = cg.io.clk_o |
| |
| // --------------------------------------------------------------------------- |
| // Reset inverter and synchronizer. |
| // |
| // Most registers in the design are loaded by literals and it is safe to use |
| // rst_i directly. However some registers {fetch.instAddr} load from io ports |
| // or use "reset.asBool" to initialize state which infers synchronous resets. |
| // This hybrid design allows for interfaces to reset immediately on reset |
| // assertion while ensuring all internal state will eventually be reset |
| // correctly before usage. |
| val rst_i = (!rst_ni.asBool || ml_reset).asAsyncReset |
| val rst_core = Wire(Bool()) |
| |
| withClockAndReset(clk_i, rst_i) { |
| val rst_q1 = RegInit(true.B) |
| val rst_q2 = RegInit(true.B) |
| rst_q1 := false.B |
| rst_q2 := rst_q1 |
| rst_core := rst_q2 |
| } |
| |
| // --------------------------------------------------------------------------- |
| // Connect clock and reset. |
| withClockAndReset(clk_g, rst_core.asAsyncReset) { |
| assert(p.vectorBits == 256) |
| |
| val core = kelvin.Core(p) |
| val l1d = kelvin.L1DCache(p) |
| val l1i = kelvin.L1ICache(p) |
| val bus = Axi2Sram(p) |
| |
| // ------------------------------------------------------------------------- |
| // Control interface. |
| finish := core.io.halted |
| host_req := false.B |
| fault := core.io.fault |
| |
| // ------------------------------------------------------------------------- |
| // Scalar Core logging. |
| slog := core.io.slog |
| |
| // ------------------------------------------------------------------------- |
| // Debug Request. |
| core.io.debug_req := debug_req |
| |
| // ------------------------------------------------------------------------- |
| // L1Cache. |
| l1d.io.dbus <> core.io.dbus |
| l1d.io.flush <> core.io.dflush |
| l1d.io.volt_sel := volt_sel |
| |
| l1i.io.ibus <> core.io.ibus |
| l1i.io.flush <> core.io.iflush |
| l1i.io.volt_sel := volt_sel |
| |
| // ------------------------------------------------------------------------- |
| // Bus Mux. |
| bus.io.in0 <> core.io.axi0 |
| bus.io.in1 <> core.io.axi1 |
| bus.io.in2 <> l1d.io.axi |
| bus.io.in3.read <> l1i.io.axi.read |
| |
| // ------------------------------------------------------------------------- |
| // SRAM bridge. |
| 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. |
| for (i <- 0 until 12) { |
| core.io.csr.in.value(i) := 0.U |
| } |
| |
| core.io.csr.in.value(0) := pc_start |
| } |
| } |
| |
| object EmitKelvin extends App { |
| val p = new kelvin.MatchaParameters |
| ChiselStage.emitSystemVerilogFile(new Kelvin(p), args) |
| } |