diff --git a/flake.lock b/flake.lock index 1779ecd60..4a4e1dd75 100644 --- a/flake.lock +++ b/flake.lock @@ -36,11 +36,11 @@ }, "nixpkgs-for-circt": { "locked": { - "lastModified": 1710817074, - "narHash": "sha256-LeYqqFOre7AoHgGtAV6/7OSdaqu3S3sOFZtfsEQoA+o=", + "lastModified": 1714053995, + "narHash": "sha256-mgnyhE2ccqcp4gBxgQhoTxIt7avgf8FkZL6zkpGdWWY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "afa65506cb0b4bed7191223bc693e6779c690a5b", + "rev": "9a4f20210147ecaec0269ec02506be2696635ee7", "type": "github" }, "original": { diff --git a/nix/overlay.nix b/nix/overlay.nix index 3664e9847..27f3437d7 100644 --- a/nix/overlay.nix +++ b/nix/overlay.nix @@ -15,6 +15,21 @@ in # Override "nixpkgs" circt with "nixpkgs-for-circt". # To update the "nixpkgs-for-circt" input, run `nix flake lock --update-input nixpkgs-for-circt`. circt = self.inputs.nixpkgs-for-circt.legacyPackages."${final.system}".circt; + # uncomment this to build circt from source. + # circt = self.inputs.nixpkgs-for-circt.legacyPackages."${final.system}".circt.overrideAttrs (old: rec { + # version = "1.73.0"; + # src = final.fetchFromGitHub { + # owner = "llvm"; + # repo = "circt"; + # rev = "firtool-${version}"; + # sha256 = "sha256-C50PiToXrKf94Vg1yv++3xVhIuCW/KVPs0yLv5Fg0dY="; + # fetchSubmodules = true; + # }; + # preConfigure = '' + # find ./test -name '*.mlir' -exec sed -i 's|/usr/bin/env|${final.coreutils}/bin/env|g' {} \; + # substituteInPlace cmake/modules/GenVersionFile.cmake --replace "unknown git version" "nightly" + # ''; + # }); espresso = final.callPackage ./pkgs/espresso.nix { }; dramsim3 = final.callPackage ./pkgs/dramsim3.nix { }; libspike = final.callPackage ./pkgs/libspike.nix { }; diff --git a/nix/t1/_sources/generated.json b/nix/t1/_sources/generated.json index 95fa4c438..53fc8ed23 100644 --- a/nix/t1/_sources/generated.json +++ b/nix/t1/_sources/generated.json @@ -61,7 +61,7 @@ }, "chisel": { "cargoLocks": null, - "date": "2024-03-27", + "date": "2024-04-24", "extract": null, "name": "chisel", "passthru": null, @@ -73,11 +73,11 @@ "name": null, "owner": "chipsalliance", "repo": "chisel", - "rev": "9177535ff1be47ffd99034bf0154c0f1ec637419", - "sha256": "sha256-smqNuOnmz+MeVGyS7mdIzegniQ/6EJH4CFqK4JntvrI=", + "rev": "08edb717185201dffdad1c808fbe32df914aa55f", + "sha256": "sha256-AYqkdMJE2Ct8T6M+oTrEVPlLmWM7uvl3UQnPv6tjUwA=", "type": "github" }, - "version": "9177535ff1be47ffd99034bf0154c0f1ec637419" + "version": "08edb717185201dffdad1c808fbe32df914aa55f" }, "diplomacy": { "cargoLocks": null, diff --git a/nix/t1/_sources/generated.nix b/nix/t1/_sources/generated.nix index c8f7bebc9..6cb0a31a8 100644 --- a/nix/t1/_sources/generated.nix +++ b/nix/t1/_sources/generated.nix @@ -39,15 +39,15 @@ }; chisel = { pname = "chisel"; - version = "9177535ff1be47ffd99034bf0154c0f1ec637419"; + version = "08edb717185201dffdad1c808fbe32df914aa55f"; src = fetchFromGitHub { owner = "chipsalliance"; repo = "chisel"; - rev = "9177535ff1be47ffd99034bf0154c0f1ec637419"; + rev = "08edb717185201dffdad1c808fbe32df914aa55f"; fetchSubmodules = false; - sha256 = "sha256-smqNuOnmz+MeVGyS7mdIzegniQ/6EJH4CFqK4JntvrI="; + sha256 = "sha256-AYqkdMJE2Ct8T6M+oTrEVPlLmWM7uvl3UQnPv6tjUwA="; }; - date = "2024-03-27"; + date = "2024-04-24"; }; diplomacy = { pname = "diplomacy"; diff --git a/nix/t1/t1.nix b/nix/t1/t1.nix index 5b1d7e069..96293f3ca 100644 --- a/nix/t1/t1.nix +++ b/nix/t1/t1.nix @@ -42,7 +42,7 @@ let ./../../common.sc ]; }; - millDepsHash = "sha256-Ri0aB4SxBdwuNOnBvvsTwVdAnvtiKIW5EMrulDX4sVo="; + millDepsHash = "sha256-rkS/bTDnjnyzdQyTIhfLj3e0mMdDn4fzv/660rO3qYg="; nativeBuildInputs = [ submodules.setupHook ]; }; diff --git a/rocket/src/AbstractT1.scala b/rocket/src/AbstractT1.scala index 282951cbd..01663ab4d 100644 --- a/rocket/src/AbstractT1.scala +++ b/rocket/src/AbstractT1.scala @@ -1,6 +1,7 @@ package org.chipsalliance.t1.rockettile import chisel3._ +import chisel3.properties.{ClassType, Path, Property} import chisel3.util._ import chisel3.util.experimental.BitSet import freechips.rocketchip.diplomacy._ @@ -154,6 +155,13 @@ abstract class AbstractLazyT1()(implicit p: Parameters) extends LazyModule { BundleBridgeSource(() => Valid(new VectorResponse(xLen))) val hazardControlNode: BundleBridgeSource[VectorHazardControl] = BundleBridgeSource(() => Output(new VectorHazardControl)) + // Diplomacy is dirty and doesn't support Property yet, this is a dirty hack and will be bore from top + val om = InModuleBody { + // TODO: maybe affect by [[https://github.com/llvm/circt/issues/6866]]: + // Abstract T1 cannot view the classpath in T1OM. + val t1OMType = ClassType.unsafeGetClassTypeByName("T1OM") + IO(Output(Property[t1OMType.Type]())).suggestName("T1OM") + } } /** This is a vector interface comply to chipsalliance/t1 project. @@ -164,6 +172,7 @@ abstract class AbstractLazyT1ModuleImp(val outer: AbstractLazyT1)(implicit p: Pa val csr: CSRInterface = outer.csrSinkNode.bundle val response: ValidIO[VectorResponse] = outer.responseNode.bundle val hazardControl: VectorHazardControl = outer.hazardControlNode.bundle + val om: Property[ClassType] = outer.om } trait HasLazyT1 { this: BaseTile => diff --git a/subsystem/src/LazyT1.scala b/subsystem/src/LazyT1.scala index de282ee1f..e4f635e93 100644 --- a/subsystem/src/LazyT1.scala +++ b/subsystem/src/LazyT1.scala @@ -5,6 +5,7 @@ package org.chipsalliance.t1.subsystem import chisel3._ import chisel3.experimental.SerializableModuleGenerator +import chisel3.properties.{ClassType, Path, Property} import freechips.rocketchip.diplomacy.AddressSet import freechips.rocketchip.subsystem.{BaseSubsystem, InstantiatesHierarchicalElements} import org.chipsalliance.cde.config._ @@ -12,9 +13,6 @@ import org.chipsalliance.t1.rockettile.{AbstractLazyT1, AbstractLazyT1ModuleImp, import org.chipsalliance.t1.rtl.{T1, T1Parameter} case object T1Generator extends Field[SerializableModuleGenerator[T1, T1Parameter]] -trait HasT1Tiles { this: BaseSubsystem with InstantiatesHierarchicalElements => - lazy val t1Tiles = totalTiles.values.collect { case r: org.chipsalliance.t1.rocketcore.T1Tile => r } -} class LazyT1()(implicit p: Parameters) extends AbstractLazyT1 { lazy val module = new LazyT1Imp(this) @@ -82,4 +80,6 @@ class LazyT1Imp(outer: LazyT1)(implicit p: Parameters) extends AbstractLazyT1Mod bundle.d.ready := t1.memoryPorts(i).d.ready } + + om := t1.om } diff --git a/subsystem/src/Subsystem.scala b/subsystem/src/Subsystem.scala index 66cf852dc..501532a0f 100644 --- a/subsystem/src/Subsystem.scala +++ b/subsystem/src/Subsystem.scala @@ -4,7 +4,9 @@ package org.chipsalliance.t1.subsystem import chisel3._ +import chisel3.experimental.hierarchy.{Definition, Instance, Instantiate, instantiable, public} import chisel3.experimental.{SerializableModuleGenerator, UnlocatableSourceInfo} +import chisel3.properties.Class.ClassDefinitionOps import chisel3.util.experimental.BitSet import chisel3.util.{BitPat, Counter} import freechips.rocketchip.devices.debug.DebugModuleKey @@ -17,9 +19,24 @@ import freechips.rocketchip.tile.{FPUParams, MaxHartIdBits, XLen} import freechips.rocketchip.tilelink.{BroadcastFilter, HasTLBusParams, TLBusWrapper, TLBusWrapperConnection, TLBusWrapperInstantiationLike, TLBusWrapperTopology, TLEdge, TLFIFOFixer, TLFragmenter, TLInwardNode, TLManagerNode, TLOutwardNode, TLSlaveParameters, TLSlavePortParameters, TLWidthWidget, TLXbar} import freechips.rocketchip.util.Location import org.chipsalliance.cde.config._ -import org.chipsalliance.t1.rocketcore.{T1CrossingParams, T1TileAttachParams, T1TileParams} +import org.chipsalliance.t1.rocketcore.{T1CrossingParams, T1Tile, T1TileAttachParams, T1TileParams} import org.chipsalliance.t1.rockettile.BuildT1 -import org.chipsalliance.t1.rtl.{T1, T1Parameter} +import org.chipsalliance.t1.rtl.{T1, T1OM, T1Parameter} +import chisel3.properties.{Class, ClassType, Path, Property} +import chisel3.util.experimental.BoringUtils.bore + + +/** The top OM we need to read. */ +@instantiable +class T1SubsystemOM extends Class { + val t1OMType: ClassType = Instantiate.definition(new T1OM).getClassType + @public + val t1 = IO(Output(Property[t1OMType.Type]())) + @public + val t1In = IO(Input(Property[t1OMType.Type]())) + t1 := t1In + // TODO: add memory ranges, scalar core info, here. +} // The Subsystem that T1 lives in. case object T1Subsystem extends HierarchicalLocation("T1Subsystem") @@ -423,6 +440,14 @@ class T1Subsystem(implicit p: Parameters) }.unzip // IOs + val t1OM = InModuleBody { + val omInstance: Instance[T1SubsystemOM] = Instantiate(new T1SubsystemOM) + val omType: ClassType = omInstance.toDefinition.getClassType + val om: Property[ClassType] = IO(Output(Property[omType.Type]())) + om := omInstance.getPropertyReference + omInstance.t1In := bore(totalTiles.head._2.asInstanceOf[T1Tile].t1.map(_.om).get) + om + } val scalarPort = InModuleBody { scalarMemoryNode.makeIOs() } val mmioPort = InModuleBody { mmioNode.makeIOs() } val vectorPorts = InModuleBody { diff --git a/t1/src/Lane.scala b/t1/src/Lane.scala index af63a81b5..08b3512c5 100644 --- a/t1/src/Lane.scala +++ b/t1/src/Lane.scala @@ -4,15 +4,25 @@ package org.chipsalliance.t1.rtl import chisel3._ -import chisel3.experimental.hierarchy.{Instance, Instantiate, instantiable, public} +import chisel3.experimental.hierarchy.{Definition, Instance, Instantiate, instantiable, public} import chisel3.experimental.{SerializableModule, SerializableModuleParameter} import chisel3.probe.{Probe, ProbeValue, define} +import chisel3.properties.{AnyClassType, Class, ClassType, Path, Property} import chisel3.util._ import chisel3.util.experimental.decode.DecodeBundle import org.chipsalliance.t1.rtl.decoder.Decoder import org.chipsalliance.t1.rtl.lane._ import org.chipsalliance.t1.rtl.vrf.{RamType, VRF, VRFParam, VRFProbe} +@instantiable +class LaneOM extends Class { + @public + val vfus = IO(Output(Property[Seq[AnyClassType]]())) + @public + val vfusIn = IO(Input(Property[Seq[AnyClassType]]())) + vfus := vfusIn +} + class LaneSlotProbe extends Bundle { val stage0EnqueueReady: Bool = Bool() val stage0EnqueueValid: Bool = Bool() @@ -159,6 +169,11 @@ case class LaneParameter( */ @instantiable class Lane(val parameter: LaneParameter) extends Module with SerializableModule[LaneParameter] { + val omInstance: Instance[LaneOM] = Instantiate(new LaneOM) + val omType: ClassType = omInstance.toDefinition.getClassType + @public + val om: Property[ClassType] = IO(Output(Property[omType.Type]())) + om := omInstance.getPropertyReference /** laneIndex is a IO constant for D/I and physical implementations. */ @public @@ -796,19 +811,18 @@ class Lane(val parameter: LaneParameter) extends Module with SerializableModule[ // VFU // TODO: reuse logic, adder, multiplier datapath - { - val decodeResultVec: Seq[DecodeBundle] = slotControl.map(_.laneRequest.decodeResult) - - vfuConnect(parameter.vfuInstantiateParameter)( - requestVec, - executeEnqueueValid, - decodeResultVec, - executeEnqueueFire, - responseVec, - executeOccupied, - VFUNotClear - ) - } + val decodeResultVec: Seq[DecodeBundle] = slotControl.map(_.laneRequest.decodeResult) + + val vfus: Seq[Instance[VFUModule]] = instantiateVFU(parameter.vfuInstantiateParameter)( + requestVec, + executeEnqueueValid, + decodeResultVec, + executeEnqueueFire, + responseVec, + executeOccupied, + VFUNotClear + ) + omInstance.vfusIn := Property(vfus.map(_.om.asAnyClassType)) // It’s been a long time since I selected it. Need pipe val queueBeforeMaskWrite: Queue[VRFWriteRequest] = diff --git a/t1/src/T1.scala b/t1/src/T1.scala index 5e9096fcf..a2235ac5d 100644 --- a/t1/src/T1.scala +++ b/t1/src/T1.scala @@ -4,17 +4,31 @@ package org.chipsalliance.t1.rtl import chisel3._ -import chisel3.experimental.hierarchy.{Instance, Instantiate, public} +import chisel3.experimental.hierarchy.{Definition, Instance, Instantiate, instantiable, public} import chisel3.experimental.{SerializableModule, SerializableModuleParameter} import chisel3.util._ import chisel3.util.experimental.decode._ import tilelink.{TLBundle, TLBundleParameter, TLChannelAParameter, TLChannelDParameter} import chisel3.probe.{Probe, ProbeValue, define, force} +import chisel3.properties.{AnyClassType, Class, ClassType, Property} import chisel3.util.experimental.BitSet import org.chipsalliance.t1.rtl.decoder.Decoder import org.chipsalliance.t1.rtl.lsu.{LSU, LSUParameter, LSUProbe} import org.chipsalliance.t1.rtl.vrf.{RamType, VRFParam, VRFProbe} +// TODO: this should be a object model. There should 3 object model here: +// 1. T1SubsystemOM(T1(OM), MemoryRegion, Cache configuration) +// 2. T1(Lane(OM), VLEN, DLEN, uarch parameters, customer IDs(for floorplan);) +// 3. Lane(Retime, VRF memory type, id, multiple instances(does it affect dedup? not for sure)) +@instantiable +class T1OM extends Class { + @public + val lanes = IO(Output(Property[Seq[AnyClassType]]())) + @public + val lanesIn = IO(Input(Property[Seq[AnyClassType]]())) + lanes := lanesIn +} + object T1Parameter { implicit def bitSetP:upickle.default.ReadWriter[BitSet] = upickle.default.readwriter[String].bimap[BitSet]( bs => bs.terms.map("b" + _.rawString).mkString("\n"), @@ -244,6 +258,11 @@ class T1Probe(param: T1Parameter) extends Bundle { * The logic of [[T1]] contains the Vector Sequencer and Mask Unit. */ class T1(val parameter: T1Parameter) extends Module with SerializableModule[T1Parameter] { + val omInstance: Instance[T1OM] = Instantiate(new T1OM) + val omType: ClassType = omInstance.toDefinition.getClassType + @public + val om: Property[ClassType] = IO(Output(Property[omType.Type]())) + om := omInstance.getPropertyReference /** request from CPU. * because the interrupt and exception of previous instruction is unpredictable, @@ -1493,6 +1512,9 @@ class T1(val parameter: T1Parameter) extends Module with SerializableModule[T1Pa define(laneVrfProbes(index), lane.vrfProbe) lane } + + omInstance.lanesIn := Property(laneVec.map(_.om.asAnyClassType)) + define(lsuProbe, lsu.probe) writeQueueClearVec := VecInit(laneVec.map(_.writeQueueValid)) diff --git a/t1/src/VectorFunctionUnit.scala b/t1/src/VectorFunctionUnit.scala index 19da6a6c2..25ff98a49 100644 --- a/t1/src/VectorFunctionUnit.scala +++ b/t1/src/VectorFunctionUnit.scala @@ -5,8 +5,8 @@ package org.chipsalliance.t1.rtl import chisel3._ import chisel3.experimental.SerializableModuleGenerator -import chisel3.experimental.hierarchy.{instantiable, public} -import chisel3.properties.Property +import chisel3.experimental.hierarchy.{Instance, Instantiate, instantiable, public} +import chisel3.properties.{Class, ClassType, Path, Property} import org.chipsalliance.t1.rtl.decoder.BoolField import chisel3.util._ @@ -26,16 +26,29 @@ class VFUPipeBundle extends Bundle { val tag: UInt = UInt(2.W) } +@instantiable +// TODO: expose more metadatas to VFU OM, this is important for documentation generator. +class VFUOM extends Class { + @public + val cycles = IO(Output(Property[Int]())) + @public + val cyclesIn = IO(Input(Property[Int]())) + cycles := cyclesIn +} + @instantiable abstract class VFUModule(p: VFUParameter) extends Module { + val omInstance: Instance[VFUOM] = Instantiate(new VFUOM) + val omType: ClassType = omInstance.toDefinition.getClassType + + @public + val om: Property[ClassType] = IO(Output(Property[omType.Type]())) @public val requestIO: DecoupledIO[VFUPipeBundle] = IO(Flipped(Decoupled(p.inputBundle))) @public val responseIO: DecoupledIO[VFUPipeBundle] = IO(Decoupled(p.outputBundle)) - // FFUModule is a behavior Module which should be retimed to [[latency]] cycles. - @public - val retime: Option[Property[Int]] = Option.when(p.latency > 1)(IO(Property[Int]())) - retime.foreach(_ := Property(p.latency)) + om := omInstance.getPropertyReference + omInstance.cyclesIn := Property(p.latency) val vfuRequestReady: Option[Bool] = Option.when(!p.singleCycle)(Wire(Bool())) val requestReg: VFUPipeBundle = RegEnable(requestIO.bits, 0.U.asTypeOf(requestIO.bits), requestIO.fire) diff --git a/t1/src/package.scala b/t1/src/package.scala index 4ed30b20d..da172aa6c 100644 --- a/t1/src/package.scala +++ b/t1/src/package.scala @@ -180,7 +180,7 @@ package object rtl { id.map(f => (shifterReg :+ source).map(p => Mux(p.valid, indexToOH(f(p.bits), 4), 0.U)).reduce(_ | _)) } - def vfuConnect(parameter: VFUInstantiateParameter)( + def instantiateVFU(parameter: VFUInstantiateParameter)( requestVec: Vec[SlotRequestToVFU], requestValid: Vec[Bool], decodeResult: Seq[DecodeBundle], @@ -188,7 +188,7 @@ package object rtl { responseVec: Vec[ValidIO[VFUResponseToSlot]], executeOccupied: Vec[Bool], VFUNotClear: Bool - ): Unit = { + ): Seq[Instance[VFUModule]] = { // 声明 vfu 的入口 val requestVecFromSlot: Seq[SlotExecuteRequest[SlotRequestToVFU]] = Seq.tabulate(parameter.slotCount) { index => @@ -214,12 +214,14 @@ package object rtl { } val vrfIsBusy = Wire(Vec(parameter.genVec.size, Bool())) - // 处理vfu - val vfuResponse: Seq[ValidIO[VFUResponseToSlot]] = parameter.genVec.zipWithIndex.map { case ((gen, slotVec), vfuIndex) => - // vfu 模块 - // TODO: SerializableModuleGenerator should support D/I - val vfu: VFUModule = Module(gen.module()) + + val vfus: Seq[Instance[VFUModule]] = parameter.genVec.map { case (gen, _) => + val vfu: Instance[VFUModule] = gen.instance() vfu.suggestName(gen.parameter.decodeField.name) + vfu + } + + val vfuResponse: Seq[ValidIO[VFUResponseToSlot]] = (parameter.genVec zip vfus).zipWithIndex.map { case (((gen, slotVec), vfu), vfuIndex) => // vfu request distributor val distributor: Option[Instance[Distributor[SlotRequestToVFU, VFUResponseToSlot]]] = Option.when(gen.parameter.NeedSplit)( Instantiate(new Distributor( @@ -303,6 +305,7 @@ package object rtl { data.valid := selectResponse.valid && (selectResponse.bits.tag === slotIndex.U) data.bits := selectResponse.bits } + vfus } def UIntToOH1(x: UInt, width: Int): UInt = (~((-1).S(width.W).asUInt << x)).asUInt(width-1, 0)