├── circtlib ├── capi │ ├── includeUnions.txt │ ├── includeVars.txt │ ├── linkLibraries.txt │ ├── includeTypedefs.txt │ ├── jextract-headers.h │ └── includeStructs.txt ├── src │ ├── dialect │ │ └── firrtl │ │ │ ├── AttributeAPI.scala │ │ │ ├── TypeAPI.scala │ │ │ ├── IntrinsicsAPI.scala │ │ │ ├── DeclarationAPI.scala │ │ │ ├── StatementAPI.scala │ │ │ └── StructureAPI.scala │ └── capi │ │ ├── dialect │ │ ├── emit │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── ltl │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── debug │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── verif │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── sv │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── arc │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── fsm │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── dc │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── comb │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── hwarith │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── llhd │ │ │ ├── given_DialectApi.scala │ │ │ ├── given_TypeApi.scala │ │ │ ├── given_AttributeApi.scala │ │ │ └── CAPIDefinition.scala │ │ ├── om │ │ │ ├── given_DialectApi.scala │ │ │ ├── CAPIImplementation.scala │ │ │ ├── given_AttributeApi.scala │ │ │ └── given_TypeApi.scala │ │ ├── handshake │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_DialectApi.scala │ │ ├── moore │ │ │ └── given_DialectApi.scala │ │ ├── chirrtl │ │ │ ├── given_DialectApi.scala │ │ │ ├── given_TypeApi.scala │ │ │ └── CAPIDefinition.scala │ │ ├── firrtl │ │ │ ├── given_DialectApi.scala │ │ │ └── given_UtilityApi.scala │ │ ├── seq │ │ │ ├── given_DialectApi.scala │ │ │ ├── given_TypeApi.scala │ │ │ └── CAPIDefinition.scala │ │ └── hw │ │ │ ├── given_DialectApi.scala │ │ │ ├── CAPIImplementation.scala │ │ │ └── given_InstanceGraphApi.scala │ │ ├── exportfirrtl │ │ ├── CAPIDefinition.scala │ │ └── given_ExportFirrtlApi.scala │ │ └── exportverilog │ │ ├── CAPIDefinition.scala │ │ └── given_ExportVerilogApi.scala └── package.mill ├── mlirlib ├── capi │ ├── includeUnions.txt │ ├── includeVars.txt │ ├── linkLibraries.txt │ ├── includeTypedefs.txt │ └── jextract-headers.h ├── src │ ├── dialect │ │ └── smt │ │ │ ├── AttributeAPI.scala │ │ │ └── TypeAPI.scala │ └── capi │ │ ├── affinemap │ │ └── CAPIDefinition.scala │ │ ├── affineexpr │ │ └── CAPIDefinition.scala │ │ ├── integerset │ │ └── CAPIDefinition.scala │ │ ├── sparsetensor │ │ └── CAPIDefinition.scala │ │ ├── transform │ │ └── CAPIDefinition.scala │ │ ├── interfaces │ │ └── CAPIDefinition.scala │ │ ├── support │ │ ├── given_TypeIDApi.scala │ │ ├── given_LogicalResultApi.scala │ │ ├── given_TypeIDAllocatorApi.scala │ │ ├── given_LlvmThreadPoolApi.scala │ │ ├── CAPIImplementation.scala │ │ └── given_StringRefApi.scala │ │ ├── executionengine │ │ └── CAPIDefinition.scala │ │ ├── ir │ │ ├── given_OpOperandApi.scala │ │ ├── given_SymbolTableApi.scala │ │ ├── given_DialectRegistryApi.scala │ │ ├── given_AsmStateApi.scala │ │ ├── given_IdentifierApi.scala │ │ ├── given_BytecodeWriterConfigApi.scala │ │ ├── given_TypeApi.scala │ │ ├── given_DialectApi.scala │ │ ├── given_ValueApi.scala │ │ ├── given_ModuleApi.scala │ │ ├── given_RegionApi.scala │ │ ├── given_OperationStateApi.scala │ │ ├── given_OpPrintingFlagsApi.scala │ │ └── given_ContextApi.scala │ │ ├── dialect │ │ ├── smt │ │ │ ├── given_DialectApi.scala │ │ │ ├── given_AttributeApi.scala │ │ │ └── CAPIDefinition.scala │ │ └── func │ │ │ ├── given_DialectApi.scala │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_FuncApi.scala │ │ ├── target │ │ └── exportsmtlib │ │ │ ├── CAPIDefinition.scala │ │ │ └── given_ExportSmtlibApi.scala │ │ ├── diagnostic │ │ ├── CAPIDefinition.scala │ │ └── CAPIImplementation.scala │ │ ├── rewrite │ │ └── CAPIDefinition.scala │ │ └── pass │ │ └── given_OpPassManagerApi.scala └── package.mill ├── rvdecoderdb ├── src │ ├── parser │ │ ├── Token.scala │ │ ├── Import.scala │ │ ├── PseudoOp.scala │ │ ├── RawInstructionSet.scala │ │ ├── SameValue.scala │ │ ├── BareStr.scala │ │ ├── RefInst.scala │ │ ├── BitValue.scala │ │ ├── FixedRangeValue.scala │ │ └── RawInstruction.scala │ └── Utils.scala ├── package.mill └── tests │ └── src │ └── Test.scala ├── .gitignore ├── nix ├── zaozi │ ├── default.nix │ └── zaozi.nix ├── pkgs │ ├── mlir-install.nix │ ├── circt-install.nix │ ├── espresso.nix │ └── riscv-opcodes.nix └── overlay.nix ├── zaozi ├── lit │ └── tests │ │ ├── lit.site.cfg.py.in │ │ ├── lit.cfg.py │ │ ├── ScalaCliTest.py │ │ ├── IllegalOverridenGenerator.sc │ │ ├── ExportVerilog.scala │ │ ├── OverriddenMain.scala │ │ ├── DefaultValueParam.scala │ │ └── IllegalParameterType.scala ├── stdlib │ ├── lit │ │ └── tests │ │ │ ├── lit.site.cfg.py.in │ │ │ ├── lit.cfg.py │ │ │ ├── PLADecoder.sc │ │ │ └── ScalaCliTest.py │ ├── src │ │ ├── Api.scala │ │ ├── BitSetApi.scala │ │ ├── Decoder.scala │ │ └── PLADecoder.scala │ ├── package.mill │ └── tests │ │ └── src │ │ └── BitSetSpec.scala ├── src │ ├── valuetpe │ │ ├── Bool.scala │ │ ├── Clock.scala │ │ ├── Analog.scala │ │ ├── Bits.scala │ │ ├── SInt.scala │ │ ├── UInt.scala │ │ ├── Reset.scala │ │ ├── Vec.scala │ │ ├── Data.scala │ │ ├── Probe.scala │ │ ├── Record.scala │ │ ├── ProbeRecord.scala │ │ ├── Bundle.scala │ │ └── ProbeBundle.scala │ ├── reftpe │ │ ├── Wire.scala │ │ ├── Ref.scala │ │ ├── Reg.scala │ │ ├── Const.scala │ │ ├── Node.scala │ │ ├── Interface.scala │ │ ├── Instance.scala │ │ └── Referable.scala │ ├── default │ │ ├── ProbeDefine.scala │ │ ├── MonoConnect.scala │ │ ├── Naming.scala │ │ ├── BundleApi.scala │ │ ├── RecordApi.scala │ │ └── VecApi.scala │ └── magic │ │ └── DynamicSubfield.scala └── testlib │ └── package.mill ├── omlib └── package.mill ├── decoder ├── package.mill └── src │ └── PLA.scala ├── .github └── workflows │ ├── check-format.yml │ ├── test.yml │ ├── jmh.yml │ └── bump.yml ├── .scalafmt.conf ├── smtlib ├── package.mill └── tests │ └── src │ ├── QuantifierSpec.scala │ └── ParseSpec.scala ├── README.md └── flake.nix /circtlib/capi/includeUnions.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | -------------------------------------------------------------------------------- /circtlib/capi/includeVars.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | -------------------------------------------------------------------------------- /mlirlib/capi/includeUnions.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | -------------------------------------------------------------------------------- /mlirlib/capi/includeVars.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/Token.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | trait Token 7 | -------------------------------------------------------------------------------- /mlirlib/capi/linkLibraries.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | MLIRCAPIFunc 4 | MLIRCAPISMT 5 | MLIRCAPIExportSMTLIB 6 | MLIRCAPIIR 7 | MLIRCAPIRegisterEverything 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bloop 2 | .bsp 3 | .jvm-opts 4 | .mill-jvm-opts 5 | .metals/ 6 | .vscode/ 7 | .envrc 8 | .direnv/ 9 | .idea/ 10 | .scala-build/ 11 | __pycache__/ 12 | 13 | out/ 14 | result* 15 | 16 | *.vcd 17 | *.fst 18 | *.fsdb 19 | *.log 20 | -------------------------------------------------------------------------------- /nix/zaozi/default.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | 4 | { lib, newScope, }: 5 | lib.makeScope newScope (scope: { 6 | zaozi-assembly = scope.callPackage ./zaozi.nix { }; 7 | }) 8 | 9 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/Import.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | object Import extends Token: 7 | override def toString: String = "Import" 8 | -------------------------------------------------------------------------------- /mlirlib/src/dialect/smt/AttributeAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.dialect.smt.attr 4 | 5 | class BVCmpPredicateAttr 6 | class IntPredicateAttr 7 | class BitVectorAttr 8 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/PseudoOp.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | object PseudoOp extends Token: 7 | override def toString: String = "PseudoOp" 8 | -------------------------------------------------------------------------------- /mlirlib/src/dialect/smt/TypeAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.dialect.smt.tpe 4 | 5 | class ArrayType 6 | class BitVectorType 7 | class BoolType 8 | class IntType 9 | class SMTFuncType 10 | class SortType 11 | -------------------------------------------------------------------------------- /nix/pkgs/mlir-install.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | 4 | { symlinkJoin, circt }: 5 | symlinkJoin { 6 | name = "mlir-install"; 7 | paths = [ 8 | circt.llvm.lib 9 | circt.llvm.dev 10 | ]; 11 | 12 | inherit (circt) meta; 13 | } 14 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/RawInstructionSet.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | case class RawInstructionSet(name: String, ratified: Boolean, custom: Boolean, rawInstructions: Seq[RawInstruction]) 7 | -------------------------------------------------------------------------------- /nix/pkgs/circt-install.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | 4 | { symlinkJoin, circt }: 5 | symlinkJoin { 6 | name = "circt-install"; 7 | paths = [ 8 | circt 9 | circt.lib 10 | circt.dev 11 | ]; 12 | 13 | inherit (circt) meta; 14 | } 15 | -------------------------------------------------------------------------------- /circtlib/src/dialect/firrtl/AttributeAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.dialect.firrtl.attr 4 | 5 | class AugmentedBundleTypeAttr 6 | class AugmentedGroundTypeAttr 7 | class AugmentedVectorTypeAttr 8 | class InternalPathAttr 9 | class MemoryInitAttr 10 | class ParamDeclAttr 11 | -------------------------------------------------------------------------------- /zaozi/lit/tests/lit.site.cfg.py.in: -------------------------------------------------------------------------------- 1 | import sys 2 | config.scala_version = "@SCALA_VERSION@" 3 | config.run_classpath = "@RUN_CLASSPATH@".split(",") 4 | config.java_home = "@JAVA_HOME@" 5 | config.java_library_path = "@JAVA_LIBRARY_PATH@".split(",") 6 | config.lit_dir = "@LIT_DIR@".split(",") 7 | config.test_exec_root = os.path.dirname(__file__) 8 | lit_config.load_config(config, "@LIT_DIR@/lit.cfg.py") 9 | -------------------------------------------------------------------------------- /zaozi/stdlib/lit/tests/lit.site.cfg.py.in: -------------------------------------------------------------------------------- 1 | import sys 2 | config.scala_version = "@SCALA_VERSION@" 3 | config.run_classpath = "@RUN_CLASSPATH@".split(",") 4 | config.java_home = "@JAVA_HOME@" 5 | config.java_library_path = "@JAVA_LIBRARY_PATH@".split(",") 6 | config.lit_dir = "@LIT_DIR@".split(",") 7 | config.test_exec_root = os.path.dirname(__file__) 8 | lit_config.load_config(config, "@LIT_DIR@/lit.cfg.py") 9 | -------------------------------------------------------------------------------- /mlirlib/src/capi/affinemap/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.affinemap 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.MemorySegment 8 | 9 | class AffineMap(val _segment: MemorySegment) 10 | trait AffineMapApi extends HasSegment[AffineMap] with HasSizeOf[AffineMap] 11 | -------------------------------------------------------------------------------- /mlirlib/src/capi/affineexpr/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.affineexpr 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.MemorySegment 8 | 9 | class AffineExpr(val _segment: MemorySegment) 10 | trait AffineExprApi extends HasSegment[AffineExpr] with HasSizeOf[AffineExpr] 11 | -------------------------------------------------------------------------------- /nix/pkgs/espresso.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenv, 3 | fetchFromGitHub, 4 | cmake, 5 | ninja, 6 | }: 7 | stdenv.mkDerivation rec { 8 | pname = "espresso"; 9 | version = "2.4"; 10 | nativeBuildInputs = [ 11 | cmake 12 | ninja 13 | ]; 14 | src = fetchFromGitHub { 15 | owner = "chipsalliance"; 16 | repo = "espresso"; 17 | rev = "v${version}"; 18 | sha256 = "sha256-z5By57VbmIt4sgRgvECnLbZklnDDWUA6fyvWVyXUzsI="; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /circtlib/capi/linkLibraries.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | MLIRCAPIIR 4 | CIRCTCAPIFIRRTL 5 | CIRCTCAPICHIRRTL 6 | CIRCTCAPIHW 7 | CIRCTCAPISV 8 | CIRCTCAPISeq 9 | CIRCTCAPIEmit 10 | CIRCTCAPIOM 11 | CIRCTCAPIFirtool 12 | CIRCTCAPIExportFIRRTL 13 | CIRCTCAPIExportVerilog 14 | CIRCTFIRRTL 15 | CIRCTHW 16 | CIRCTExportFIRRTL 17 | CIRCTExportVerilog 18 | MLIRCAPIRegisterEverything 19 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/SameValue.scala: -------------------------------------------------------------------------------- 1 | package org.chipsalliance.rvdecoderdb.parser 2 | import org.chipsalliance.rvdecoderdb.parser.ArgLUT 3 | 4 | object SameValue: 5 | def unapply(str: String): Option[ArgLUT] = str match 6 | case s"${attr1}=${attr2}" => ArgLUT.all.get(attr1) 7 | case _ => None 8 | 9 | class SameValue(val attr1: String, val attr2: String) extends Token: 10 | override def toString: String = s"$attr1=$attr2" 11 | -------------------------------------------------------------------------------- /mlirlib/src/capi/integerset/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.integerset 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class IntegerSet(val _segment: MemorySegment) 10 | trait IntegerSetApi extends HasSegment[IntegerSet] with HasSizeOf[IntegerSet] 11 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/BareStr.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | object BareStr: 7 | def unapply(str: String): Option[BareStr] = Some(new BareStr(str)) 8 | 9 | /** This either be Instruction or InstructionSet(only for import) */ 10 | class BareStr(val name: String) extends Token: 11 | override def toString: String = name 12 | -------------------------------------------------------------------------------- /mlirlib/src/capi/sparsetensor/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.sparsetensor 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class SparseTensorLevelType(val _segment: MemorySegment) 10 | trait SparseTensorLevelTypeApi extends HasSegment[SparseTensorLevelType] 11 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Bool.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait Bool extends Data with CanProbe: 11 | def toMlirType( 12 | using Arena, 13 | Context, 14 | TypeImpl 15 | ): Type = this.toMlirTypeImpl 16 | -------------------------------------------------------------------------------- /mlirlib/src/capi/transform/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.transform 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class TransformOptions(val _segment: MemorySegment) 10 | trait TransformOptionsApi extends HasSegment[TransformOptions] with HasSizeOf[TransformOptions] 11 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Clock.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait Clock extends Data with CanProbe: 11 | def toMlirType( 12 | using Arena, 13 | Context, 14 | TypeImpl 15 | ): Type = this.toMlirTypeImpl 16 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/emit/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.emit 4 | 5 | // circt-c/Dialect/Esi.h 6 | import org.llvm.mlir.scalalib.capi.ir.Context 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait DialectApi: 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit 15 | end DialectApi 16 | -------------------------------------------------------------------------------- /mlirlib/src/capi/interfaces/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.interfaces 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class ShapedTypeComponentsCallback(val _segment: MemorySegment) 10 | trait ShapedTypeComponentsCallbackApi extends HasSegment[ShapedTypeComponentsCallback] 11 | -------------------------------------------------------------------------------- /mlirlib/src/capi/support/given_TypeIDApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.support 4 | 5 | import org.llvm.mlir.* 6 | 7 | import java.lang.foreign.MemorySegment 8 | 9 | given TypeIDApi with 10 | extension (typeID: TypeID) 11 | inline def segment: MemorySegment = typeID._segment 12 | inline def sizeOf: Int = MlirTypeID.sizeof().toInt 13 | end given 14 | -------------------------------------------------------------------------------- /mlirlib/src/capi/executionengine/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.executionengine 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class ExecutionEngine(val _segment: MemorySegment) 10 | trait ExecutionEngineApi extends HasSegment[ExecutionEngine] with HasSizeOf[ExecutionEngine] 11 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_OpOperandApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | given OpOperandApi with 10 | extension (opOperandApi: OpOperand) 11 | inline def segment: MemorySegment = opOperandApi._segment 12 | inline def sizeOf: Int = MlirOpOperand.sizeof().toInt 13 | end given 14 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Analog.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait Analog extends Data: 11 | private[zaozi] val _width: Int 12 | 13 | def toMlirType( 14 | using Arena, 15 | Context, 16 | TypeImpl 17 | ): Type = this.toMlirTypeImpl 18 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_SymbolTableApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | 7 | import java.lang.foreign.MemorySegment 8 | 9 | given SymbolTableApi with 10 | extension (symbolTableApi: SymbolTable) 11 | inline def segment: MemorySegment = symbolTableApi._segment 12 | inline def sizeOf: Int = MlirSymbolTable.sizeof().toInt 13 | end given 14 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/RefInst.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | object RefInst: 7 | def unapply(str: String): Option[RefInst] = str match 8 | case s"$set::$instr" => Some(new RefInst(set, instr)) 9 | case _ => None 10 | 11 | class RefInst(val set: String, val inst: String) extends Token: 12 | override def toString: String = s"RefInst($set, $inst)" 13 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Bits.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait Bits extends Data with CanProbe: 11 | private[zaozi] val _width: Int 12 | 13 | def toMlirType( 14 | using Arena, 15 | Context, 16 | TypeImpl 17 | ): Type = this.toMlirTypeImpl 18 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/SInt.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait SInt extends Data with CanProbe: 11 | private[zaozi] val _width: Int 12 | 13 | def toMlirType( 14 | using Arena, 15 | Context, 16 | TypeImpl 17 | ): Type = this.toMlirTypeImpl 18 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/UInt.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait UInt extends Data with CanProbe: 11 | private[zaozi] val _width: Int 12 | 13 | final def toMlirType( 14 | using Arena, 15 | Context, 16 | TypeImpl 17 | ): Type = this.toMlirTypeImpl 18 | -------------------------------------------------------------------------------- /mlirlib/src/capi/support/given_LogicalResultApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.support 4 | 5 | import org.llvm.mlir.* 6 | 7 | import java.lang.foreign.MemorySegment 8 | 9 | given LogicalResultApi with 10 | extension (logicalResult: LogicalResult) 11 | inline def segment: MemorySegment = logicalResult._segment 12 | inline def sizeOf: Int = MlirLogicalResult.sizeof().toInt 13 | end given 14 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Reset.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait Reset extends Data with CanProbe: 11 | private[zaozi] val _isAsync: Boolean 12 | 13 | final def toMlirType( 14 | using Arena, 15 | Context, 16 | TypeImpl 17 | ): Type = this.toMlirTypeImpl 18 | -------------------------------------------------------------------------------- /mlirlib/src/capi/support/given_TypeIDAllocatorApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.support 4 | 5 | import org.llvm.mlir.* 6 | 7 | import java.lang.foreign.MemorySegment 8 | 9 | given TypeIDAllocatorApi with 10 | extension (typeIDAllocator: TypeIDAllocator) 11 | inline def segment: MemorySegment = typeIDAllocator._segment 12 | inline def sizeOf: Int = MlirTypeIDAllocator.sizeof().toInt 13 | end given 14 | -------------------------------------------------------------------------------- /circtlib/capi/includeTypedefs.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | CirctESIServiceGeneratorFunc # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/ESI.h 5 | HWInstanceGraphNodeCallback # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/HW.h 6 | CirctMSFTPlacementCallback # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/MSFT.h 7 | CirctMSFTPrimitiveType # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/MSFT.h -------------------------------------------------------------------------------- /omlib/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Yuhang Zeng 3 | package build.omlib 4 | 5 | import mill._ 6 | import mill.scalalib.TestModule.Utest 7 | import mill.scalalib._ 8 | import mill.scalalib.scalafmt._ 9 | 10 | import build.{circtlib, v, ZaoziPublishModule} 11 | 12 | object `package` extends ScalaModule with ScalafmtModule with ZaoziPublishModule { m => 13 | def scalaVersion = Task(v.scala) 14 | def mvnDeps = Seq(v.upickle) 15 | def moduleDeps = Seq(circtlib) 16 | } 17 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Vec.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait Vec[E <: Data] extends Data: 11 | private[zaozi] val _elementType: E 12 | private[zaozi] val _count: Int 13 | 14 | def toMlirType( 15 | using Arena, 16 | Context, 17 | TypeImpl 18 | ): Type = this.toMlirTypeImpl 19 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/ltl/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/LTL.h 5 | package org.llvm.circt.scalalib.capi.dialect.ltl 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Arc Dialect Api 12 | * {{{ 13 | * mlirGetDialectHandle__ltl__ 14 | * }}} 15 | */ 16 | trait DialectApi: 17 | inline def loadDialect( 18 | using arena: Arena, 19 | context: Context 20 | ): Unit 21 | end DialectApi 22 | -------------------------------------------------------------------------------- /circtlib/src/capi/exportfirrtl/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.exportfirrtl 4 | 5 | import org.llvm.mlir.scalalib.capi.support.LogicalResult 6 | import org.llvm.mlir.scalalib.capi.ir.Module 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait ExportFirrtlApi: 11 | extension (module: Module) 12 | inline def exportFIRRTL( 13 | callback: String => Unit 14 | )( 15 | using arena: Arena 16 | ): LogicalResult 17 | end ExportFirrtlApi 18 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/debug/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Debug.h 5 | package org.llvm.circt.scalalib.capi.dialect.debug 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Debug Dialect API 12 | * {{{ 13 | * mlirGetDialectHandle__debug__ 14 | * }}} 15 | */ 16 | 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | end DialectApi 23 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/verif/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Verif.h 5 | package org.llvm.circt.scalalib.capi.dialect.verif 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Arc Dialect Api 12 | * {{{ 13 | * mlirGetDialectHandle__verif__ 14 | * registerArcPasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | end DialectApi 23 | -------------------------------------------------------------------------------- /decoder/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package build.decoder 4 | 5 | import mill._ 6 | import mill.scalalib._ 7 | import mill.scalalib.TestModule.Utest 8 | import mill.scalalib.scalafmt._ 9 | 10 | import build.{v, ZaoziPublishModule} 11 | 12 | object `package` extends ScalaModule with ScalafmtModule with ZaoziPublishModule { 13 | def scalaVersion = Task(v.scala) 14 | def mvnDeps = Seq(v.mainargs, v.oslib, v.upickle) 15 | 16 | object tests extends ScalaTests with ScalafmtModule with Utest { 17 | def mvnDeps = Seq(v.utest) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/sv/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/SV.h 5 | package org.llvm.circt.scalalib.capi.dialect.sv 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** SV Dialect API 12 | * {{{ 13 | * mlirGetDialectHandle__sv__ 14 | * registerSVPasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | def registerPasses: Unit 23 | end DialectApi 24 | -------------------------------------------------------------------------------- /rvdecoderdb/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package build.rvdecoderdb 4 | 5 | import mill._ 6 | import mill.scalalib._ 7 | import mill.scalalib.TestModule.Utest 8 | import mill.scalalib.scalafmt._ 9 | 10 | import build.{v, ZaoziPublishModule} 11 | 12 | object `package` extends ScalaModule with ScalafmtModule with ZaoziPublishModule { 13 | def scalaVersion = Task(v.scala) 14 | def mvnDeps = Seq(v.mainargs, v.oslib, v.upickle) 15 | 16 | object tests extends ScalaTests with ScalafmtModule with Utest { 17 | def mvnDeps = Seq(v.utest) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/arc/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Arc.h 5 | package org.llvm.circt.scalalib.capi.dialect.arc 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Arc Dialect Api 12 | * {{{ 13 | * mlirGetDialectHandle__arc__ 14 | * registerArcPasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | def registerPasses: Unit 23 | end DialectApi 24 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/fsm/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/FSM.h 5 | package org.llvm.circt.scalalib.capi.dialect.fsm 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** FSM Dialect API 12 | * {{{ 13 | * mlirGetDialectHandle__fsm__ 14 | * registerFsmPasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | def registerPasses: Unit 23 | end DialectApi 24 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/dc/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/DC.h 5 | package org.llvm.circt.scalalib.capi.dialect.dc 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | // 12 | /** DC Dialect API 13 | * {{{ 14 | * mlirGetDialectHandle__dc__ 15 | * registerDCPasses 16 | * }}} 17 | */ 18 | trait DialectApi: 19 | inline def loadDialect( 20 | using arena: Arena, 21 | context: Context 22 | ): Unit 23 | def registerPasses: Unit 24 | end DialectApi 25 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/comb/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Comb.h 5 | package org.llvm.circt.scalalib.capi.dialect.comb 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Comb Dialect API 12 | * {{{ 13 | * mlirGetDialectHandle__comb__ 14 | * registerCombPasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | def registerPasses: Unit 23 | end DialectApi 24 | -------------------------------------------------------------------------------- /.github/workflows/check-format.yml: -------------------------------------------------------------------------------- 1 | name: Check Format 2 | on: 3 | pull_request: 4 | types: 5 | - opened 6 | - synchronize 7 | - reopened 8 | - ready_for_review 9 | - labeled 10 | 11 | # Cancel the current workflow when new commit pushed 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | check-format: 18 | name: "Check Scala Format" 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: DeterminateSystems/nix-installer-action@main 23 | - run: nix develop -c mill -i '__.checkFormat' 24 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/ltl/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.ltl 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__ltl__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/emit/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.emit 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__emit__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/hwarith/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/HWArith.h 5 | package org.llvm.circt.scalalib.capi.dialect.hwarith 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** HWArith Dialect Api 12 | * {{{ 13 | * mlirGetDialectHandle__hwarith__ 14 | * registerHWArithPasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | def registerPasses: Unit 23 | end DialectApi 24 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/llhd/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.llhd 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__llhd__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/om/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Yuhang Zeng 3 | package org.llvm.circt.scalalib.capi.dialect.om 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__om__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/dialect/firrtl/TypeAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.dialect.firrtl.tpe 4 | 5 | class AnalogType 6 | class AnyRefType 7 | class AsyncResetType 8 | class BaseTypeAliasType 9 | class BoolType 10 | class BundleType 11 | class ClassType 12 | class ClockType 13 | class DoubleType 14 | class FEnumType 15 | class FVectorType 16 | class FIntegerType 17 | class LHSType 18 | class ListType 19 | class OpenBundleType 20 | class OpenVectorType 21 | class PathType 22 | class RefType 23 | class ResetType 24 | class SIntType 25 | class StringType 26 | class UIntType 27 | -------------------------------------------------------------------------------- /zaozi/lit/tests/lit.cfg.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import lit.formats 3 | from lit.llvm import llvm_config 4 | from lit.llvm.subst import ToolSubst 5 | 6 | sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) 7 | from ScalaCliTest import ScalaCliTest 8 | 9 | config.name = 'ZAOZI' 10 | config.test_format = ScalaCliTest(True) 11 | config.suffixes = [".scala", ".sc"] 12 | config.substitutions = [ 13 | ('%SCALAVERSION', config.scala_version), 14 | ('%RUNCLASSPATH', ':'.join(config.run_classpath)), 15 | ('%JAVAHOME', config.java_home), 16 | ('%JAVALIBRARYPATH', ':'.join(config.java_library_path)) 17 | ] 18 | config.test_source_root = os.path.dirname(__file__) 19 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Wire.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.valuetpe.* 7 | import org.llvm.mlir.scalalib.capi.ir.{Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | trait Wire[T <: Data] extends Referable[T] with HasOperation: 12 | private[zaozi] val _tpe: T 13 | private[zaozi] val _operation: Operation 14 | def operation( 15 | using TypeImpl 16 | ): Operation = this.operationImpl 17 | def refer( 18 | using Arena, 19 | TypeImpl 20 | ): Value = this.referImpl 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/debug/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.debug 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__debug__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/handshake/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Handshake.h 5 | package org.llvm.circt.scalalib.capi.dialect.handshake 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.Context 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Arc Dialect Api 12 | * {{{ 13 | * mlirGetDialectHandle__handshake__ 14 | * registerHandshakePasses 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | def registerPasses: Unit 23 | end DialectApi 24 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/moore/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.moore 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__moore__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/verif/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.verif 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__verif__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /.scalafmt.conf: -------------------------------------------------------------------------------- 1 | version = "3.9.7" 2 | runner.dialect = scala3 3 | 4 | maxColumn = 120 5 | align.preset = most 6 | indent.defnSite = 2 7 | assumeStandardLibraryStripMargin = true 8 | docstrings.style = SpaceAsterisk 9 | lineEndings = preserve 10 | includeCurlyBraceInSelectChains = false 11 | danglingParentheses.preset = true 12 | 13 | align.tokens."+" = [{ 14 | code = ":" 15 | }] 16 | 17 | newlines.beforeCurlyLambdaParams = "never" 18 | newlines.alwaysBeforeMultilineDef = false 19 | newlines.implicitParamListModifierForce = [before] 20 | 21 | verticalMultiline.atDefnSite = true 22 | 23 | optIn.annotationNewlines = true 24 | 25 | rewrite.rules = [SortImports, PreferCurlyFors, AvoidInfix] 26 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/chirrtl/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.chirrtl 4 | 5 | import org.llvm.circt.CAPI.mlirGetDialectHandle__chirrtl__ as mlirGetDialectHandle 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | end given 20 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Ref.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.valuetpe.* 7 | import org.llvm.mlir.scalalib.capi.ir.{Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | trait Ref[T <: Data] extends Referable[T] with HasOperation: 12 | private[zaozi] val _tpe: T 13 | private[zaozi] val _operation: Operation 14 | 15 | def operation( 16 | using TypeImpl 17 | ): Operation = this.operationImpl 18 | 19 | def refer( 20 | using Arena, 21 | TypeImpl 22 | ): Value = this.referImpl 23 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Reg.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.valuetpe.* 7 | import org.llvm.mlir.scalalib.capi.ir.{Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | trait Reg[T <: Data] extends Referable[T] with HasOperation: 12 | private[zaozi] val _tpe: T 13 | private[zaozi] val _operation: Operation 14 | 15 | def operation( 16 | using TypeImpl 17 | ): Operation = this.operationImpl 18 | 19 | def refer( 20 | using Arena, 21 | TypeImpl 22 | ): Value = this.referImpl 23 | -------------------------------------------------------------------------------- /zaozi/stdlib/lit/tests/lit.cfg.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import lit.formats 3 | from lit.llvm import llvm_config 4 | from lit.llvm.subst import ToolSubst 5 | 6 | sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) 7 | from ScalaCliTest import ScalaCliTest 8 | 9 | config.name = 'ZAOZISTDLIB' 10 | config.test_format = ScalaCliTest(True) 11 | config.suffixes = [".scala", ".sc"] 12 | config.substitutions = [ 13 | ('%SCALAVERSION', config.scala_version), 14 | ('%RUNCLASSPATH', ':'.join(config.run_classpath)), 15 | ('%JAVAHOME', config.java_home), 16 | ('%JAVALIBRARYPATH', ':'.join(config.java_library_path)) 17 | ] 18 | config.test_source_root = os.path.dirname(__file__) 19 | -------------------------------------------------------------------------------- /mlirlib/src/capi/dialect/smt/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.capi.dialect.smt 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.mlirGetDialectHandle__smt__ 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | given DialectApi with 12 | inline def loadDialect( 13 | )( 14 | using arena: Arena, 15 | context: Context 16 | ): Unit = 17 | DialectHandle(mlirGetDialectHandle__smt__(arena)).loadDialect( 18 | using arena, 19 | context 20 | ) 21 | end given 22 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Const.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.valuetpe.* 7 | import org.llvm.mlir.scalalib.capi.ir.{Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | trait Const[T <: Data] extends Referable[T] with HasOperation: 12 | private[zaozi] val _tpe: T 13 | private[zaozi] val _operation: Operation 14 | 15 | def operation( 16 | using TypeImpl 17 | ): Operation = this.operationImpl 18 | 19 | def refer( 20 | using Arena, 21 | TypeImpl 22 | ): Value = this.referImpl 23 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Node.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.valuetpe.* 7 | import org.llvm.mlir.scalalib.capi.ir.{Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | trait Node[T <: Data] extends Referable[T] with HasOperation: 12 | private[zaozi] val _tpe: T 13 | private[zaozi] val _operation: Operation 14 | 15 | def operation( 16 | using TypeImpl 17 | ): Operation = this.operationImpl 18 | 19 | def refer( 20 | using Arena, 21 | TypeImpl 22 | ): Value = this.referImpl 23 | -------------------------------------------------------------------------------- /mlirlib/src/capi/dialect/func/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.capi.dialect.func 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.mlirGetDialectHandle__func__ 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | given DialectApi with 12 | inline def loadDialect( 13 | )( 14 | using arena: Arena, 15 | context: Context 16 | ): Unit = 17 | DialectHandle(mlirGetDialectHandle__func__(arena)).loadDialect( 18 | using arena, 19 | context 20 | ) 21 | end given 22 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/firrtl/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.firrtl 4 | 5 | import org.llvm.circt.* 6 | import org.llvm.circt.CAPI.mlirGetDialectHandle__firrtl__ as mlirGetDialectHandle 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | given DialectApi with 12 | inline def loadDialect( 13 | using arena: Arena, 14 | context: Context 15 | ): Unit = 16 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 17 | using arena, 18 | context 19 | ) 20 | end given 21 | -------------------------------------------------------------------------------- /mlirlib/src/capi/target/exportsmtlib/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.target.exportsmtlib 4 | 5 | import org.llvm.mlir.scalalib.capi.ir.{Module, Operation} 6 | 7 | import java.lang.foreign.Arena 8 | 9 | trait ExportSmtlibApi: 10 | extension (module: Module) 11 | inline def exportSMTLIB( 12 | callBack: String => Unit 13 | )( 14 | using arena: Arena 15 | ): Unit 16 | 17 | extension (operation: Operation) 18 | inline def exportSMTLIB( 19 | callBack: String => Unit 20 | )( 21 | using arena: Arena 22 | ): Unit 23 | end ExportSmtlibApi 24 | -------------------------------------------------------------------------------- /nix/pkgs/riscv-opcodes.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | 4 | { stdenv 5 | , fetchFromGitHub 6 | }: 7 | 8 | stdenv.mkDerivation { 9 | name = "riscv-opcodes"; 10 | src = fetchFromGitHub { 11 | owner = "riscv"; 12 | repo = "riscv-opcodes"; 13 | rev = "6a1be96c8238d603a50d956ff1f91defa264785b"; 14 | hash = "sha256-0pYCpkZkrFVfZHxrxsKh12aiRKGU73TF9gkm2X7aqKs="; 15 | }; 16 | 17 | buildPhase = "true"; 18 | 19 | installPhase = '' 20 | runHook preInstall 21 | mkdir -p $out 22 | 23 | cp $src/rv* $out/ 24 | cp -r $src/unratified $out/ 25 | cp $src/*.csv $out/ 26 | runHook postInstall 27 | ''; 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Zaozi Test 2 | on: 3 | pull_request: 4 | types: 5 | - opened 6 | - synchronize 7 | - reopened 8 | - ready_for_review 9 | - labeled 10 | 11 | # Cancel the current workflow when new commit pushed 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | run-test: 18 | name: "Test all mill module" 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: DeterminateSystems/nix-installer-action@main 23 | - run: nix develop -c mill -i '__.testForked' 24 | - run: nix develop -c mill -i 'zaozi.lit.tests.run' 25 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/om/CAPIImplementation.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Yuhang Zeng 3 | package org.llvm.circt.scalalib.capi.dialect.om 4 | 5 | import java.lang.foreign.MemorySegment 6 | 7 | given OMEvaluatorApi with 8 | extension (ref: OMEvaluator) 9 | inline def segment: MemorySegment = ref._segment 10 | inline def sizeOf: Int = org.llvm.circt.OMEvaluator.sizeof().toInt 11 | end given 12 | 13 | given OMEvaluatorValueApi with 14 | extension (ref: OMEvaluatorValue) 15 | inline def segment: MemorySegment = ref._segment 16 | inline def sizeOf: Int = org.llvm.circt.OMEvaluatorValue.sizeof().toInt 17 | end given 18 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/dc/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.dc 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__dc__ as mlirGetDialectHandle, registerDCPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/sv/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.sv 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__sv__ as mlirGetDialectHandle, registerSVPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/exportverilog/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.exportverilog 4 | 5 | import org.llvm.mlir.scalalib.capi.support.LogicalResult 6 | import org.llvm.mlir.scalalib.capi.ir.Module 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait ExportVerilogApi: 11 | extension (module: Module) 12 | inline def exportVerilog( 13 | callback: String => Unit 14 | )( 15 | using arena: Arena 16 | ): LogicalResult 17 | inline def exportSplitVerilog( 18 | directory: String 19 | )( 20 | using arena: Arena 21 | ): LogicalResult 22 | end ExportVerilogApi 23 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/fsm/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.fsm 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__fsm__ as mlirGetDialectHandle, registerFSMPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/seq/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.seq 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__seq__ as mlirGetDialectHandle, registerSeqPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/comb/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.comb 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__comb__ as mlirGetDialectHandle, registerCombPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/arc/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.arc 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__arc__ as mlirGetDialectHandle, registerArcPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | inline def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/hwarith/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.hwarith 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__hwarith__ as mlirGetDialectHandle, registerHWArithPasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/BitValue.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | object BitValue: 7 | def unapply(str: String): Option[BitValue] = str match 8 | case s"${bit}=${value}" => 9 | Some( 10 | new BitValue( 11 | bit.toInt, 12 | value match 13 | case s"0b$bstr" => BigInt(bstr, 2) 14 | case s"0x$xstr" => BigInt(xstr, 16) 15 | case dstr => BigInt(dstr) 16 | ) 17 | ) 18 | case _ => None 19 | 20 | class BitValue(val bit: BigInt, val value: BigInt) extends Token: 21 | override def toString: String = s"$bit=$value" 22 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Interface.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.valuetpe.* 6 | import me.jiuyang.zaozi.{DVInterface, HWInterface, Parameter, TypeImpl} 7 | import org.llvm.mlir.scalalib.capi.ir.{Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | trait Interface[T <: HWInterface[?] | DVInterface[?, ?]] extends Referable[T] with HasOperation: 12 | private[zaozi] val _tpe: T 13 | private[zaozi] val _operation: Operation 14 | def operation( 15 | using TypeImpl 16 | ): Operation = this.operationImpl 17 | def refer( 18 | using Arena, 19 | TypeImpl 20 | ): Value = this.referImpl 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/handshake/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.handshake 4 | 5 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__handshake__ as mlirGetDialectHandle, registerHandshakePasses as r} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given DialectApi with 11 | inline def loadDialect( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit = 15 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 16 | using arena, 17 | context 18 | ) 19 | def registerPasses: Unit = r() 20 | end given 21 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/hw/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.hw 4 | 5 | import org.llvm.circt.* 6 | import org.llvm.circt.CAPI.{mlirGetDialectHandle__hw__ as mlirGetDialectHandle, registerHWPasses as r} 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, DialectHandle, given} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | given DialectApi with 12 | inline def loadDialect( 13 | using arena: Arena, 14 | context: Context 15 | ): Unit = 16 | DialectHandle(mlirGetDialectHandle(arena)).loadDialect( 17 | using arena, 18 | context 19 | ) 20 | def registerPasses: Unit = r() 21 | end given 22 | -------------------------------------------------------------------------------- /zaozi/testlib/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package build.zaozi.testlib 4 | 5 | import mill._ 6 | import mill.scalalib.TestModule.Utest 7 | import mill.scalalib._ 8 | import mill.scalalib.scalafmt._ 9 | import os.Path 10 | 11 | import build.{circtlib, v, zaozi} 12 | 13 | object `package` extends ScalaModule with ScalafmtModule { m => 14 | def scalaVersion = Task(v.scala) 15 | def moduleDeps = Seq(zaozi) 16 | def mvnDeps = Seq(v.utest) 17 | 18 | override def scalacOptions: T[Seq[String]] = Task(super.scalacOptions() ++ Seq("-experimental")) 19 | 20 | override def forkArgs: T[Seq[String]] = Task( 21 | super.forkArgs() ++ circtlib.forkArgs() 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /zaozi/stdlib/src/Api.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.stdlib 4 | 5 | import me.jiuyang.decoder.* 6 | import me.jiuyang.zaozi.* 7 | import me.jiuyang.zaozi.reftpe.* 8 | import me.jiuyang.zaozi.valuetpe.* 9 | import org.llvm.mlir.scalalib.capi.ir.Block 10 | import org.llvm.mlir.scalalib.capi.ir.Context 11 | 12 | import java.lang.foreign.Arena 13 | 14 | trait BitSetApi[B <: BitSet]: 15 | extension (bs: B) 16 | def cover( 17 | signal: Referable[Bits] 18 | )( 19 | using Arena, 20 | Context, 21 | Block, 22 | sourcecode.File, 23 | sourcecode.Line, 24 | sourcecode.Name.Machine, 25 | InstanceContext 26 | ): Node[Bool] 27 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Data.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.magic.{DynamicSubfield, UntypedDynamicSubfield} 7 | 8 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 9 | 10 | import java.lang.foreign.Arena 11 | 12 | trait Data: 13 | def toMlirType( 14 | using Arena, 15 | Context, 16 | TypeImpl 17 | ): Type 18 | 19 | trait Width: 20 | val _width: Int 21 | 22 | trait Aggregate extends Data: 23 | this: DynamicSubfield | UntypedDynamicSubfield => 24 | private[zaozi] var instantiating = true 25 | private[zaozi] val _elements = collection.mutable.Buffer.empty[BundleField[?]] 26 | -------------------------------------------------------------------------------- /circtlib/src/capi/exportfirrtl/given_ExportFirrtlApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.exportfirrtl 4 | 5 | import org.llvm.circt.CAPI.mlirExportFIRRTL 6 | import org.llvm.mlir.scalalib.capi.support.{*, given} 7 | import org.llvm.mlir.scalalib.capi.ir.{Module, given} 8 | 9 | import java.lang.foreign.{Arena, MemorySegment} 10 | 11 | given ExportFirrtlApi with 12 | extension (module: Module) 13 | inline def exportFIRRTL( 14 | callback: String => Unit 15 | )( 16 | using arena: Arena 17 | ): LogicalResult = LogicalResult( 18 | mlirExportFIRRTL(arena, module.segment, callback.stringToStringCallback.segment, MemorySegment.NULL) 19 | ) 20 | end given 21 | -------------------------------------------------------------------------------- /.github/workflows/jmh.yml: -------------------------------------------------------------------------------- 1 | name: Zaozi JMH Benchmark 2 | on: 3 | pull_request: 4 | types: 5 | - opened 6 | - synchronize 7 | - reopened 8 | - ready_for_review 9 | - labeled 10 | 11 | # Cancel the current workflow when new commit pushed 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | run-jmh: 18 | name: "Run zaozi JMH benchmark" 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: DeterminateSystems/nix-installer-action@main 23 | - run: nix develop -c bash -c "mill -i --disable-prompt zaozi.benchmark.runJmh 2>&1 | sed 's/^\[[0-9]*\] //' | grep -E '^Iteration|^Benchmark|^ZaoziBenchmark' > $GITHUB_STEP_SUMMARY" 24 | -------------------------------------------------------------------------------- /rvdecoderdb/tests/src/Test.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.tests 5 | 6 | import org.chipsalliance.rvdecoderdb 7 | import utest.* 8 | import os.* 9 | 10 | object rvdecoderdbTest extends TestSuite: 11 | val tests = Tests: 12 | test("rvdecoderdb works"): 13 | val riscvOpcodesPath: Path = Path( 14 | sys.env.getOrElse( 15 | "RISCV_OPCODES_INSTALL_PATH", 16 | throw new RuntimeException("Environment variable RISCV_OPCODES_INSTALL_PATH not set") 17 | ) 18 | ) 19 | val instTable: Iterable[rvdecoderdb.Instruction] = rvdecoderdb.instructions(riscvOpcodesPath) 20 | instTable.foreach(println) 21 | -------------------------------------------------------------------------------- /mlirlib/capi/includeTypedefs.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | MlirDiagnosticHandler # header: $MLIR_INSTALL_PATH/include/mlir-c/Diagnostics.h 5 | MlirDiagnosticHandlerID # header: $MLIR_INSTALL_PATH/include/mlir-c/Diagnostics.h 6 | MlirSparseTensorLevelType # header: $MLIR_INSTALL_PATH/include/mlir-c/Dialect/SparseTensor.h 7 | MlirOperationWalkCallback # header: $MLIR_INSTALL_PATH/include/mlir-c/IR.h 8 | MlirShapedTypeComponentsCallback # header: $MLIR_INSTALL_PATH/include/mlir-c/Interfaces.h 9 | MlirTypesCallback # header: $MLIR_INSTALL_PATH/include/mlir-c/Interfaces.h 10 | MlirStringCallback # header: $MLIR_INSTALL_PATH/include/mlir-c/Support.h -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/FixedRangeValue.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | object FixedRangeValue: 7 | def unapply(str: String): Option[FixedRangeValue] = str match 8 | case s"${msb}..${lsb}=${value}" => 9 | Some( 10 | new FixedRangeValue( 11 | msb.toInt, 12 | lsb.toInt, 13 | value match 14 | case s"0b$bstr" => BigInt(bstr, 2) 15 | case s"0x$xstr" => BigInt(xstr, 16) 16 | case dstr => BigInt(dstr) 17 | ) 18 | ) 19 | case _ => None 20 | 21 | class FixedRangeValue(val msb: BigInt, val lsb: BigInt, val value: BigInt) extends Token: 22 | override def toString: String = s"$msb..$lsb=$value" 23 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/chirrtl/given_TypeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.chirrtl 4 | 5 | import org.llvm.circt.CAPI.{chirrtlTypeGetCMemory, chirrtlTypeGetCMemoryPort} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | given TypeApi with 11 | inline def getCMemory( 12 | elementType: Type, 13 | numElements: Int 14 | )( 15 | using arena: Arena, 16 | context: Context 17 | ): Type = Type(chirrtlTypeGetCMemory(arena, context.segment, elementType.segment, numElements)) 18 | inline def getCMemoryPort( 19 | using arena: Arena, 20 | context: Context 21 | ): Type = Type(chirrtlTypeGetCMemoryPort(arena, context.segment)) 22 | end given 23 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_DialectRegistryApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{mlirDialectRegistryCreate, mlirDialectRegistryDestroy} 7 | 8 | import java.lang.foreign.{Arena, MemorySegment} 9 | 10 | given DialectRegistryApi with 11 | inline def registryCreate( 12 | )( 13 | using arena: Arena 14 | ): DialectRegistry = DialectRegistry(mlirDialectRegistryCreate(arena)) 15 | 16 | extension (dialectRegistry: DialectRegistry) 17 | inline def destroy(): Unit = mlirDialectRegistryDestroy(dialectRegistry.segment) 18 | inline def segment: MemorySegment = dialectRegistry._segment 19 | inline def sizeOf: Int = MlirDialectRegistry.sizeof().toInt 20 | end given 21 | -------------------------------------------------------------------------------- /mlirlib/src/capi/support/given_LlvmThreadPoolApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.support 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{mlirLlvmThreadPoolCreate, mlirLlvmThreadPoolDestroy} 7 | 8 | import java.lang.foreign.{Arena, MemorySegment} 9 | 10 | given LlvmThreadPoolApi with 11 | inline def llvmThreadPoolCreate( 12 | )( 13 | using arena: Arena 14 | ): LlvmThreadPool = LlvmThreadPool(mlirLlvmThreadPoolCreate(arena)) 15 | extension (llvmThreadPool: LlvmThreadPool) 16 | inline def destroy(): Unit = mlirLlvmThreadPoolDestroy(llvmThreadPool.segment) 17 | inline def segment: MemorySegment = llvmThreadPool._segment 18 | inline def sizeOf: Int = MlirLlvmThreadPool.sizeof().toInt 19 | end given 20 | -------------------------------------------------------------------------------- /circtlib/src/dialect/firrtl/IntrinsicsAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.dialect.firrtl.operation 4 | 5 | import org.llvm.mlir.scalalib.capi.ir.Operation 6 | 7 | class ClockDividerIntrinsic(val _operation: Operation) 8 | class ClockGateIntrinsic(val _operation: Operation) 9 | class ClockInverterIntrinsic(val _operation: Operation) 10 | class DPICallIntrinsic(val _operation: Operation) 11 | class FPGAProbeIntrinsic(val _operation: Operation) 12 | class GenericIntrinsic(val _operation: Operation) 13 | class HasBeenResetIntrinsic(val _operation: Operation) 14 | class IsXIntrinsic(val _operation: Operation) 15 | class PlusArgsTestIntrinsic(val _operation: Operation) 16 | class PlusArgsValueIntrinsic(val _operation: Operation) 17 | class UnclockedAssumeIntrinsic(val _operation: Operation) 18 | -------------------------------------------------------------------------------- /smtlib/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package build.smtlib 4 | 5 | import mill._ 6 | import mill.scalalib.TestModule.Utest 7 | import mill.scalalib._ 8 | import mill.scalalib.scalafmt._ 9 | import os.Path 10 | 11 | import build.{circtlib, v} 12 | 13 | object `package` extends ScalaModule with ScalafmtModule { m => 14 | def scalaVersion = Task(v.scala) 15 | def mvnDeps = Seq(v.mainargs, v.oslib, v.upickle, v.sourcecode, v.fastparse) 16 | def moduleDeps = Seq(circtlib) 17 | 18 | override def scalacOptions: T[Seq[String]] = Task(super.scalacOptions() ++ Some("-Xprint-suspension")) 19 | 20 | object tests extends ScalaTests with ScalafmtModule with Utest { 21 | def mvnDeps = Seq(v.utest) 22 | 23 | override def forkArgs: T[Seq[String]] = Task( 24 | super.forkArgs() ++ circtlib.forkArgs() 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /zaozi/stdlib/src/BitSetApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.stdlib 4 | 5 | import me.jiuyang.decoder.* 6 | import me.jiuyang.zaozi.* 7 | import me.jiuyang.zaozi.reftpe.* 8 | import me.jiuyang.zaozi.valuetpe.* 9 | import me.jiuyang.zaozi.default.{*, given} 10 | import org.llvm.mlir.scalalib.capi.ir.Block 11 | import org.llvm.mlir.scalalib.capi.ir.Context 12 | 13 | import java.lang.foreign.Arena 14 | 15 | given [B <: BitSet]: BitSetApi[B] with 16 | extension (bs: B) 17 | // TODO: use QMC for minimization 18 | def cover( 19 | signal: Referable[Bits] 20 | )( 21 | using Arena, 22 | Context, 23 | Block, 24 | sourcecode.File, 25 | sourcecode.Line, 26 | sourcecode.Name.Machine, 27 | InstanceContext 28 | ): Node[Bool] = 29 | bs.terms.map(bp => bp.value.B === (signal & bp.mask.B)).reduce(_ | _) 30 | -------------------------------------------------------------------------------- /mlirlib/src/capi/diagnostic/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.diagnostic 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class Diagnostic(val _segment: MemorySegment) 10 | trait DiagnosticApi extends HasSegment[Diagnostic] with HasSizeOf[Diagnostic] 11 | 12 | class DiagnosticHandler(val _segment: MemorySegment) 13 | trait DiagnosticHandlerApi extends HasSegment[DiagnosticHandler] 14 | 15 | class DiagnosticHandlerID(val _segment: MemorySegment) 16 | trait DiagnosticHandlerIDApi extends HasSegment[DiagnosticHandlerID] 17 | 18 | enum DiagnosticSeverityEnum: 19 | case Error 20 | case Note 21 | case Remark 22 | case Warning 23 | end DiagnosticSeverityEnum 24 | trait DiagnosticEnumApi extends HasSizeOf[DiagnosticSeverityEnum] with EnumHasToNative[DiagnosticSeverityEnum] 25 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Instance.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.valuetpe.Data 7 | import org.llvm.mlir.scalalib.capi.ir.Operation 8 | import me.jiuyang.zaozi.HWInterface 9 | import me.jiuyang.zaozi.DVInterface 10 | 11 | trait Instance[IOTpe <: HWInterface[?], ProbeTpe <: DVInterface[?, ?]] extends HasOperation: 12 | private[zaozi] val _ioTpe: IOTpe 13 | private[zaozi] val _probeTpe: ProbeTpe 14 | private[zaozi] val _operation: Operation 15 | private[zaozi] val _ioWire: Wire[IOTpe] 16 | private[zaozi] val _probeWire: Wire[ProbeTpe] 17 | 18 | def operation( 19 | using TypeImpl 20 | ): Operation = this.operationImpl 21 | 22 | def io( 23 | using TypeImpl 24 | ): Wire[IOTpe] = this.ioImpl[IOTpe] 25 | 26 | def probe( 27 | using TypeImpl 28 | ): Wire[ProbeTpe] = this.probeImpl[ProbeTpe] 29 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Probe.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.{LayerTree, TypeImpl} 6 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait CanProbe 11 | 12 | // UInt is a Data type, Probe[UInt] is either a Data, 13 | // But it cannot be a UInt to avoid the UInt extension exposing to it. 14 | trait RProbe[T <: CanProbe & Data] extends Data: 15 | private[zaozi] val _baseType: T 16 | private[zaozi] val _color: LayerTree 17 | 18 | final def toMlirType( 19 | using Arena, 20 | Context, 21 | TypeImpl 22 | ): Type = this.toMlirTypeImpl 23 | 24 | trait RWProbe[T <: CanProbe & Data] extends Data: 25 | private[zaozi] val _baseType: T 26 | private[zaozi] val _color: LayerTree 27 | 28 | final def toMlirType( 29 | using Arena, 30 | Context, 31 | TypeImpl 32 | ): Type = this.toMlirTypeImpl 33 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/chirrtl/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Chirrtl.h 5 | package org.llvm.circt.scalalib.capi.dialect.chirrtl 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Chirrtl Dialect API 12 | * 13 | * {{{ 14 | * mlirGetDialectHandle__chirrtl__ 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | end DialectApi 23 | 24 | /** Chirrtl Type API 25 | * 26 | * {{{ 27 | * chirrtlTypeGetCMemory 28 | * chirrtlTypeGetCMemoryPort 29 | * }}} 30 | */ 31 | trait TypeApi: 32 | inline def getCMemory( 33 | elementType: Type, 34 | numElements: Int 35 | )( 36 | using arena: Arena, 37 | context: Context 38 | ): Type 39 | inline def getCMemoryPort( 40 | using arena: Arena, 41 | context: Context 42 | ): Type 43 | end TypeApi 44 | -------------------------------------------------------------------------------- /circtlib/src/capi/exportverilog/given_ExportVerilogApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.exportverilog 4 | 5 | import org.llvm.circt.CAPI.{mlirExportSplitVerilog, mlirExportVerilog} 6 | import org.llvm.mlir.scalalib.capi.support.{*, given} 7 | import org.llvm.mlir.scalalib.capi.ir.{Module, given} 8 | 9 | import java.lang.foreign.{Arena, MemorySegment} 10 | 11 | given ExportVerilogApi with 12 | extension (module: Module) 13 | inline def exportVerilog( 14 | callback: String => Unit 15 | )( 16 | using arena: Arena 17 | ): LogicalResult = 18 | LogicalResult( 19 | mlirExportVerilog(arena, module.segment, callback.stringToStringCallback.segment, MemorySegment.NULL) 20 | ) 21 | inline def exportSplitVerilog( 22 | directory: String 23 | )( 24 | using arena: Arena 25 | ): LogicalResult = 26 | LogicalResult(mlirExportSplitVerilog(arena, module.segment, directory.toStringRef.segment)) 27 | end given 28 | -------------------------------------------------------------------------------- /zaozi/stdlib/lit/tests/PLADecoder.sc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // DEFINE: %{test} = scala-cli --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION -O="-experimental" --java-opt="--enable-native-access=ALL-UNNAMED" --java-opt="--enable-preview" --java-opt="-Djava.library.path=%JAVALIBRARYPATH" --main-class "me.jiuyang.zaozi.stdlib.PLADecoder" -- 5 | // RUN: %{test} config %t.json --name "ALU" --tables "[alu][default][add:01,sub:10,default:00][00:add,01:sub]" 6 | // RUN: FileCheck %s -check-prefix=CONFIG --input-file=%t.json 7 | // RUN: %{test} design %t.json 8 | // RUN: firtool PLA*.mlirbc | FileCheck %s -check-prefix=VERILOG 9 | // RUN: rm %t.json *.mlirbc -f 10 | 11 | // CONFIG: {"name":"ALU","tables":["[alu][default][add:01,default:00,sub:10][00:add,01:sub]"]} 12 | // VERILOG-LABEL: module PLA_ALU 13 | // VERILOG: input [1:0] instruction 14 | // VERILOG: output [1:0] output_alu 15 | // VERILOG: assign output_alu = {instruction[0] & ~(instruction[1]), instruction == 2'h0} -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/firrtl/given_UtilityApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.firrtl 4 | 5 | import org.llvm.circt.* 6 | import org.llvm.circt.CAPI.{firrtlImportAnnotationsFromJSONRaw, firrtlValueFoldFlow} 7 | import org.llvm.mlir.scalalib.capi.support.{*, given} 8 | import org.llvm.mlir.scalalib.capi.ir.{Attribute, AttributeApi as MlirAttributeApi, Context, Value, given} 9 | 10 | import java.lang.foreign.Arena 11 | 12 | given UtilityApi with 13 | inline def importAnnotationsFromJSONRaw( 14 | annotationsStr: String 15 | )( 16 | using arena: Arena, 17 | context: Context 18 | ): Attribute = 19 | val attribute = summon[MlirAttributeApi].allocateAttribute 20 | firrtlImportAnnotationsFromJSONRaw( 21 | context.segment, 22 | annotationsStr.toStringRef.segment, 23 | attribute.segment 24 | ) 25 | attribute 26 | inline def valueFoldFlow(value: Value, flow: FirrtlValueFlow): FirrtlValueFlow = 27 | firrtlValueFoldFlow(value.segment, flow.toNative).fromNative 28 | end given 29 | -------------------------------------------------------------------------------- /nix/overlay.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | { extraNixpkgsSrc }: 4 | 5 | final: prev: 6 | 7 | let 8 | extraNixpkgs = import extraNixpkgsSrc { inherit (final) system; }; 9 | in 10 | { 11 | mill = let jre = final.jdk21; in 12 | (prev.mill.override { inherit jre; }).overrideAttrs rec { 13 | version = "1.0.0"; 14 | src = final.fetchurl { 15 | url = "https://repo1.maven.org/maven2/com/lihaoyi/mill-dist/${version}/mill-dist-${version}.exe"; 16 | hash = "sha256-pgkwME2xs4ezfWS1HGFS2uPIqqvECTOAILWmCqci2Aw="; 17 | }; 18 | propagatedBuildInputs = with prev; [ which ]; 19 | doInstallCheck = false; 20 | passthru = { inherit jre; }; 21 | }; 22 | 23 | circt = extraNixpkgs.circt; 24 | 25 | circt-install = final.callPackage ./pkgs/circt-install.nix { }; 26 | 27 | mlir-install = final.callPackage ./pkgs/mlir-install.nix { }; 28 | 29 | riscv-opcodes = final.callPackage ./pkgs/riscv-opcodes.nix { }; 30 | 31 | espresso = final.callPackage ./pkgs/espresso.nix { }; 32 | 33 | zaozi = final.callPackage ./zaozi { }; 34 | } 35 | -------------------------------------------------------------------------------- /zaozi/lit/tests/ScalaCliTest.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import override 3 | import lit 4 | from lit.formats import ShTest 5 | 6 | 7 | class ScalaCliTest(ShTest): 8 | 9 | def __init__(self, execute_external=False, extra_substitutions=None, preamble_commands=None): 10 | super().__init__() 11 | self.execute_external = execute_external 12 | self.extra_substitutions = extra_substitutions if extra_substitutions is not None else [] 13 | self.preamble_commands = preamble_commands if preamble_commands is not None else [] 14 | 15 | @override 16 | def getTestsForPath(self, testSuite, path_in_suite, litConfig, localConfig): 17 | filename = path_in_suite[-1] 18 | 19 | # Ignore dot files, excluded tests, and paths with a dir starting with '.'. 20 | if filename.startswith(".") or filename in localConfig.excludes: 21 | return 22 | if any(p.startswith('.') for p in path_in_suite[:-1]): 23 | return 24 | 25 | base, ext = os.path.splitext(filename) 26 | if ext in localConfig.suffixes: 27 | yield lit.Test.Test(testSuite, path_in_suite, localConfig) 28 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/seq/given_TypeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.seq 4 | 5 | import org.llvm.circt.CAPI.{ 6 | seqClockTypeGet, 7 | seqImmutableTypeGet, 8 | seqImmutableTypeGetInnerType, 9 | seqTypeIsAClock, 10 | seqTypeIsAImmutable 11 | } 12 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type, given} 13 | 14 | import java.lang.foreign.Arena 15 | 16 | given TypeApi with 17 | def clockTypeGet( 18 | using arena: Arena, 19 | context: Context 20 | ): Type = Type(seqClockTypeGet(arena, context.segment)) 21 | def immutableTypeGet( 22 | tpe: Type 23 | )( 24 | using arena: Arena 25 | ): Type = Type(seqImmutableTypeGet(arena, tpe.segment)) 26 | def immutableTypeGetInnerType( 27 | tpe: Type 28 | )( 29 | using arena: Arena 30 | ): Type = Type(seqImmutableTypeGetInnerType(arena, tpe.segment)) 31 | extension (tpe: Type) 32 | def isClock: Boolean = seqTypeIsAClock(tpe.segment) 33 | def isImmutable: Boolean = seqTypeIsAImmutable(tpe.segment) 34 | end given 35 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_AsmStateApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{mlirAsmStateCreateForOperation, mlirAsmStateCreateForValue, mlirAsmStateDestroy} 7 | 8 | import java.lang.foreign.{Arena, MemorySegment} 9 | 10 | given AsmStateApi with 11 | inline def asmStateCreateForOperation( 12 | op: Operation, 13 | flags: OpPrintingFlags 14 | )( 15 | using arena: Arena 16 | ): MemorySegment = mlirAsmStateCreateForOperation(arena, op.segment, flags.segment) 17 | inline def asmStateCreateForValue( 18 | value: Value, 19 | flags: OpPrintingFlags 20 | )( 21 | using arena: Arena 22 | ): MemorySegment = mlirAsmStateCreateForValue(arena, value.segment, flags.segment) 23 | extension (asmState: AsmState) 24 | inline def destroy(): Unit = mlirAsmStateDestroy(asmState.segment) 25 | inline def segment: MemorySegment = asmState._segment 26 | inline def sizeOf: Int = MlirAsmState.sizeof().toInt 27 | end given 28 | -------------------------------------------------------------------------------- /zaozi/stdlib/lit/tests/ScalaCliTest.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import override 3 | import lit 4 | from lit.formats import ShTest 5 | 6 | 7 | class ScalaCliTest(ShTest): 8 | 9 | def __init__(self, execute_external=False, extra_substitutions=None, preamble_commands=None): 10 | super().__init__() 11 | self.execute_external = execute_external 12 | self.extra_substitutions = extra_substitutions if extra_substitutions is not None else [] 13 | self.preamble_commands = preamble_commands if preamble_commands is not None else [] 14 | 15 | @override 16 | def getTestsForPath(self, testSuite, path_in_suite, litConfig, localConfig): 17 | filename = path_in_suite[-1] 18 | 19 | # Ignore dot files, excluded tests, and paths with a dir starting with '.'. 20 | if filename.startswith(".") or filename in localConfig.excludes: 21 | return 22 | if any(p.startswith('.') for p in path_in_suite[:-1]): 23 | return 24 | 25 | base, ext = os.path.splitext(filename) 26 | if ext in localConfig.suffixes: 27 | yield lit.Test.Test(testSuite, path_in_suite, localConfig) 28 | -------------------------------------------------------------------------------- /mlirlib/src/capi/rewrite/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.rewrite 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | 7 | import java.lang.foreign.{Arena, MemorySegment} 8 | 9 | class FrozenRewritePatternSet(val _segment: MemorySegment) 10 | trait FrozenRewritePatternSetApi extends HasSegment[FrozenRewritePatternSet] with HasSizeOf[FrozenRewritePatternSet] 11 | 12 | class GreedyRewriteDriverConfig(val _segment: MemorySegment) 13 | trait GreedyRewriteDriverConfigApi 14 | extends HasSegment[GreedyRewriteDriverConfig] 15 | with HasSizeOf[GreedyRewriteDriverConfig] 16 | 17 | class PDLPatternModule(val _segment: MemorySegment) 18 | trait PDLPatternModuleApi extends HasSegment[PDLPatternModule] with HasSizeOf[PDLPatternModule] 19 | 20 | class RewritePatternSet(val _segment: MemorySegment) 21 | trait RewritePatternSetApi extends HasSegment[RewritePatternSet] with HasSizeOf[RewritePatternSet] 22 | 23 | class RewriterBase(val _segment: MemorySegment) 24 | trait RewriterBaseApi extends HasSegment[RewriterBase] with HasSizeOf[RewriterBase] 25 | -------------------------------------------------------------------------------- /mlirlib/src/capi/dialect/func/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.capi.dialect.func 4 | 5 | import org.llvm.mlir.scalalib.capi.support.{*, given} 6 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Module, Operation, given} 7 | 8 | import java.lang.foreign.Arena 9 | 10 | trait DialectApi: 11 | inline def loadDialect( 12 | )( 13 | using arena: Arena, 14 | context: Context 15 | ): Unit 16 | end DialectApi 17 | 18 | class Func(val _operation: Operation) 19 | trait FuncApi extends HasOperation[Func]: 20 | inline def op( 21 | symName: String 22 | // funcType: Type, 23 | // symVisibility: String, 24 | // argAttrs: Seq[NamedAttribute], 25 | // resAttrs: Seq[NamedAttribute], 26 | // noInline: Boolean, 27 | )( 28 | using arena: Arena, 29 | context: Context 30 | ): Func 31 | 32 | extension (c: Func) 33 | inline def block( 34 | using Arena 35 | ): Block 36 | inline def appendToModule( 37 | )( 38 | using arena: Arena, 39 | module: Module 40 | ): Unit 41 | end FuncApi 42 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_IdentifierApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{mlirIdentifierGet, mlirIdentifierGetContext, mlirIdentifierStr} 7 | import org.llvm.mlir.scalalib.capi.support.{*, given} 8 | 9 | import java.lang.foreign.{Arena, MemorySegment} 10 | 11 | given IdentifierApi with 12 | extension (identifierString: String) 13 | inline def identifierGet( 14 | using arena: Arena, 15 | context: Context 16 | ): Identifier = 17 | Identifier(mlirIdentifierGet(arena, context._segment, identifierString.toStringRef.segment)) 18 | extension (identifier: Identifier) 19 | inline def getContext( 20 | using arena: Arena 21 | ): Context = Context(mlirIdentifierGetContext(arena, identifier.segment)) 22 | inline def str( 23 | using arena: Arena 24 | ): String = StringRef(mlirIdentifierStr(arena, identifier.segment)).toScalaString 25 | inline def segment: MemorySegment = identifier._segment 26 | inline def sizeOf: Int = MlirIdentifier.sizeof().toInt 27 | end given 28 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_BytecodeWriterConfigApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirBytecodeWriterConfigCreate, 8 | mlirBytecodeWriterConfigDesiredEmitVersion, 9 | mlirBytecodeWriterConfigDestroy 10 | } 11 | 12 | import java.lang.foreign.{Arena, MemorySegment} 13 | 14 | given BytecodeWriterConfigApi with 15 | inline def bytecodeWriterConfigCreate( 16 | )( 17 | using arena: Arena 18 | ) = BytecodeWriterConfig(mlirBytecodeWriterConfigCreate(arena)) 19 | extension (bytecodeWriterConfig: BytecodeWriterConfig) 20 | inline def destroy(): Unit = mlirBytecodeWriterConfigDestroy(bytecodeWriterConfig.segment) 21 | inline def desiredEmitVersion(version: Long): Unit = 22 | mlirBytecodeWriterConfigDesiredEmitVersion(bytecodeWriterConfig.segment, version) 23 | inline def segment: MemorySegment = bytecodeWriterConfig._segment 24 | inline def sizeOf: Int = MlirBytecodeWriterConfig.sizeof().toInt 25 | end given 26 | -------------------------------------------------------------------------------- /circtlib/capi/jextract-headers.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | #ifndef JEXTRACT_HEADERS_H 4 | #define JEXTRACT_HEADERS_H 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #endif // JEXTRACT_HEADERS_H 34 | -------------------------------------------------------------------------------- /zaozi/src/default/ProbeDefine.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.default 4 | 5 | import me.jiuyang.zaozi.ProbeDefine 6 | import me.jiuyang.zaozi.reftpe.Referable 7 | import me.jiuyang.zaozi.valuetpe.{CanProbe, Data, RProbe, RWProbe} 8 | 9 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{RefDefineApi, RefSendApi, given} 10 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, given} 11 | 12 | import java.lang.foreign.Arena 13 | 14 | given [D <: Data & CanProbe, P <: RWProbe[D] | RProbe[D], SRC <: Referable[D], SINK <: Referable[P]] 15 | : ProbeDefine[D, P, SRC, SINK] with 16 | extension (ref: SINK) 17 | def <==( 18 | that: SRC 19 | )( 20 | using Arena, 21 | Context, 22 | Block, 23 | sourcecode.File, 24 | sourcecode.Line 25 | ): Unit = 26 | val refSendOp = summon[RefSendApi] 27 | .op( 28 | that.refer, 29 | locate 30 | ) 31 | val refDefineOp = summon[RefDefineApi] 32 | .op( 33 | ref.refer, 34 | refSendOp.result, 35 | locate 36 | ) 37 | refSendOp.operation.appendToBlock() 38 | refDefineOp.operation.appendToBlock() 39 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Record.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.magic.UntypedDynamicSubfield 7 | import me.jiuyang.zaozi.reftpe.Ref 8 | 9 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Type, Value} 10 | 11 | import java.lang.foreign.Arena 12 | 13 | trait Record extends Aggregate with UntypedDynamicSubfield: 14 | def Flipped[T <: Data]( 15 | name: String, 16 | tpe: T 17 | )( 18 | using TypeImpl 19 | ): BundleField[T] = this.FlippedImpl(name, tpe) 20 | 21 | def Aligned[T <: Data]( 22 | name: String, 23 | tpe: T 24 | )( 25 | using TypeImpl 26 | ): BundleField[T] = this.AlignedImpl(name, tpe) 27 | 28 | def getUntypedRefViaFieldValName( 29 | refer: Value, 30 | fieldValName: String 31 | )( 32 | using Arena, 33 | Block, 34 | Context, 35 | sourcecode.File, 36 | sourcecode.Line, 37 | sourcecode.Name.Machine 38 | )( 39 | using TypeImpl 40 | ): Ref[Data] = this.getUntypedRefViaFieldValNameImpl( 41 | refer, 42 | fieldValName 43 | ) 44 | 45 | def toMlirType( 46 | using Arena, 47 | Context, 48 | TypeImpl 49 | ): Type = this.toMlirTypeImpl 50 | -------------------------------------------------------------------------------- /decoder/src/PLA.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.decoder 4 | 5 | object PLA: 6 | def apply(str: String): PLA = 7 | str match 8 | case s"[$default][$tableStr]" => 9 | PLA( 10 | tableStr 11 | .split(",") 12 | .map { part => 13 | val Array(input, output) = part.split(":").map(_.trim) 14 | (BitSet.bitpat(input), BitSet.bitpat(output)) 15 | } 16 | .toSeq, 17 | BitSet.bitpat(default) 18 | ) 19 | case _ => 20 | throw new IllegalArgumentException(s"Invalid PLA format: $str") 21 | 22 | case class PLA(table: Seq[(BitPat, BitPat)], default: BitPat): 23 | def inputWidth: Int = table.head._1.width 24 | def outputWidth: Int = table.head._2.width 25 | table.map(_._1).foreach(bp => require(bp.width == inputWidth, "input width not match")) 26 | (table.map(_._2) :+ default).foreach(bp => require(bp.width == outputWidth, "output width not match")) 27 | override def toString: String = s"[$default][" + table.map((k, v) => s"$k:$v").mkString(",") + "]" 28 | 29 | given upickle.default.ReadWriter[PLA] = upickle.default.readwriter[String].bimap[PLA](_.toString, PLA.apply) 30 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/seq/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/Seq.h 5 | package org.llvm.circt.scalalib.capi.dialect.seq 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, Type} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** Seq Dialect Api 12 | * 13 | * {{{ 14 | * mlirGetDialectHandle__seq__ 15 | * registerSeqPasses 16 | * }}} 17 | */ 18 | trait DialectApi: 19 | inline def loadDialect( 20 | using arena: Arena, 21 | context: Context 22 | ): Unit 23 | def registerPasses: Unit 24 | end DialectApi 25 | 26 | /** Seq Type API 27 | * 28 | * {{{ 29 | * seqClockTypeGet 30 | * seqImmutableTypeGet 31 | * seqImmutableTypeGetInnerType 32 | * seqTypeIsAClock 33 | * seqTypeIsAImmutable 34 | * }}} 35 | */ 36 | trait TypeApi: 37 | def clockTypeGet( 38 | using arena: Arena, 39 | context: Context 40 | ): Type 41 | def immutableTypeGet( 42 | tpe: Type 43 | )( 44 | using arena: Arena 45 | ): Type 46 | def immutableTypeGetInnerType( 47 | tpe: Type 48 | )( 49 | using arena: Arena 50 | ): Type 51 | extension (tpe: Type) 52 | def isClock: Boolean 53 | def isImmutable: Boolean 54 | end TypeApi 55 | -------------------------------------------------------------------------------- /smtlib/tests/src/QuantifierSpec.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package me.jiuyang.smtlib.tests 4 | 5 | import me.jiuyang.smtlib.default.{*, given} 6 | import me.jiuyang.smtlib.* 7 | import utest.* 8 | 9 | import java.lang.foreign.Arena 10 | 11 | object QuantifierSpec extends TestSuite: 12 | val tests = Tests: 13 | test("Exist"): 14 | smtTest( 15 | "(declare-const x Int)", 16 | "(assert (let ((tmp (exists ()", 17 | " ( ! (let ((tmp_0 (= x 1)))", 18 | " tmp_0) :weight 1))))", 19 | " tmp))" 20 | ): 21 | solver { 22 | smtAssert(smtExists(1, false, Seq.empty) { 23 | val x = smtValue(SInt) 24 | smtYield(x === 1.S) 25 | }) 26 | } 27 | test("Forall"): 28 | smtTest( 29 | "(declare-const x Int)", 30 | "(assert (let ((tmp (forall ()", 31 | " ( ! (let ((tmp_0 (= x 1)))", 32 | " tmp_0) :weight 1))))", 33 | " tmp))" 34 | ): 35 | solver { 36 | smtAssert(smtForall(1, false, Seq.empty) { 37 | val x = smtValue(SInt) 38 | smtYield(x === 1.S) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /zaozi/src/reftpe/Referable.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.reftpe 4 | 5 | import me.jiuyang.zaozi.* 6 | import me.jiuyang.zaozi.valuetpe.* 7 | import me.jiuyang.zaozi.magic.macros.{referableApplyDynamic, referableApplyDynamicNamed, referableSelectDynamic} 8 | import org.llvm.circt.scalalib.dialect.firrtl.operation.Module as CirctModule 9 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Operation, Type, Value} 10 | 11 | import java.lang.foreign.Arena 12 | import scala.language.dynamics 13 | 14 | trait Referable[T <: Data] extends Dynamic: 15 | private[zaozi] val _tpe: T 16 | def refer( 17 | using Arena, 18 | TypeImpl 19 | ): Value 20 | 21 | /** macro to call [[DynamicSubfield.getRefViaFieldValName]] */ 22 | transparent inline def selectDynamic(name: String): Any = ${ referableSelectDynamic('this, 'name) } 23 | transparent inline def applyDynamic(name: String)(inline args: Any*): Any = ${ 24 | referableApplyDynamic('this, 'name, 'args) 25 | } 26 | transparent inline def applyDynamicNamed(name: String)(inline args: (String, Any)*): Any = ${ 27 | referableApplyDynamicNamed('this, 'name, 'args) 28 | } 29 | 30 | trait HasOperation: 31 | def operation( 32 | using TypeImpl 33 | ): Operation 34 | -------------------------------------------------------------------------------- /mlirlib/src/capi/target/exportsmtlib/given_ExportSmtlibApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.target.exportsmtlib 4 | 5 | import org.llvm.mlir.CAPI.{mlirTranslateModuleToSMTLIB, mlirTranslateOperationToSMTLIB} 6 | import org.llvm.mlir.scalalib.capi.support.{*, given} 7 | import org.llvm.mlir.scalalib.capi.ir.{Module, Operation, given} 8 | 9 | import java.lang.foreign.{Arena, MemorySegment} 10 | 11 | given ExportSmtlibApi with 12 | extension (module: Module) 13 | inline def exportSMTLIB( 14 | callback: String => Unit 15 | )( 16 | using arena: Arena 17 | ): Unit = 18 | LogicalResult( 19 | mlirTranslateModuleToSMTLIB( 20 | arena, 21 | module.segment, 22 | callback.stringToStringCallback.segment, 23 | MemorySegment.NULL, 24 | false, 25 | false 26 | ) 27 | ) 28 | 29 | extension (operation: Operation) 30 | inline def exportSMTLIB( 31 | callback: String => Unit 32 | )( 33 | using arena: Arena 34 | ): Unit = 35 | LogicalResult( 36 | mlirTranslateModuleToSMTLIB( 37 | arena, 38 | operation.segment, 39 | callback.stringToStringCallback.segment, 40 | MemorySegment.NULL, 41 | false, 42 | false 43 | ) 44 | ) 45 | end given 46 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/llhd/given_TypeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.llhd 4 | 5 | import org.llvm.circt.CAPI.{ 6 | llhdPointerTypeGet, 7 | llhdPointerTypeGetElementType, 8 | llhdSignalTypeGet, 9 | llhdSignalTypeGetElementType, 10 | llhdTypeIsAPointerType, 11 | llhdTypeIsASignalType, 12 | llhdTypeIsATimeType 13 | } 14 | import org.llvm.mlir.scalalib.capi.ir.{Type, given} 15 | 16 | import java.lang.foreign.Arena 17 | 18 | given TypeApi with 19 | inline def pointerTypeGet( 20 | element: Type 21 | )( 22 | using arena: Arena 23 | ): Type = Type(llhdPointerTypeGet(arena, element.segment)) 24 | extension (tpe: Type) 25 | inline def pointerTypeGetElementType( 26 | )( 27 | using arena: Arena 28 | ): Type = Type(llhdPointerTypeGetElementType(arena, tpe.segment)) 29 | inline def signalTypeGet( 30 | )( 31 | using arena: Arena 32 | ): Type = Type(llhdSignalTypeGet(arena, tpe.segment)) 33 | inline def signalTypeGetElementType( 34 | )( 35 | using arena: Arena 36 | ): Type = Type(llhdSignalTypeGetElementType(arena, tpe.segment)) 37 | inline def isPointerType: Boolean = llhdTypeIsAPointerType(tpe.segment) 38 | inline def isSignalType: Boolean = llhdTypeIsASignalType(tpe.segment) 39 | inline def isTimeType: Boolean = llhdTypeIsATimeType(tpe.segment) 40 | end given 41 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/ProbeRecord.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.magic.UntypedDynamicSubfield 6 | import me.jiuyang.zaozi.reftpe.Ref 7 | import me.jiuyang.zaozi.{LayerTree, TypeImpl} 8 | 9 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Type, Value} 10 | 11 | import java.lang.foreign.Arena 12 | 13 | trait ProbeRecord extends Aggregate with UntypedDynamicSubfield: 14 | def ProbeRead[T <: Data & CanProbe]( 15 | name: String, 16 | tpe: T, 17 | layer: LayerTree 18 | )( 19 | using TypeImpl 20 | ): BundleField[RProbe[T]] = 21 | this.ReadProbeImpl(name, tpe, layer) 22 | 23 | def ProbeReadWrite[T <: Data & CanProbe]( 24 | name: String, 25 | tpe: T, 26 | layer: LayerTree 27 | )( 28 | using TypeImpl 29 | ): BundleField[RWProbe[T]] = 30 | this.ReadWriteProbeImpl(name, tpe, layer) 31 | 32 | def getUntypedRefViaFieldValName( 33 | refer: Value, 34 | fieldValName: String 35 | )( 36 | using Arena, 37 | Block, 38 | Context, 39 | sourcecode.File, 40 | sourcecode.Line, 41 | sourcecode.Name.Machine 42 | )( 43 | using TypeImpl 44 | ): Ref[Data] = this.getUntypedRefViaFieldValNameImpl( 45 | refer, 46 | fieldValName 47 | ) 48 | 49 | def toMlirType( 50 | using Arena, 51 | Context, 52 | TypeImpl 53 | ): Type = this.toMlirTypeImpl 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zaozi 2 | 3 | Zaozi is an experimental project aimed at rewriting Chisel in pure Scala 3. 4 | It will not replace Chisel, but provide a minimized solution to create an plugable eDSL in Scala 3. 5 | The goal of this project is providing an eDSL frontend framework for hardware designs. 6 | 7 | ## Project Structure 8 | 9 | - **mlirlib**: 10 | A Java module that maintains all MLIR C-API definitions. 11 | It can be a generic layer for any MLIR infrastructure in Scala 3. 12 | 13 | - **circtlib**: 14 | A Java module that maintains all CIRCT C-API definitions, currently mainly for Firrtl. 15 | Developers adding new dialects to Zaozi should expose them in CIRCT and include them here. 16 | 17 | - **zaozi**: 18 | The core DSL implementation, encompassing the type system and build entries. 19 | It focuses on module-level construction, allowing modules to implement specific interfaces without extending from a base class. 20 | 21 | ## Design Philosophy 22 | 23 | Zaozi emphasizes a modular and minimalistic approach, delegating build processes to MLIR via C-API. 24 | 25 | This strategy reduces JVM memory usage by avoiding local AST storage and eliminates serialization overhead by directly binding MLIR values to Scala values via the MLIR C-API. 26 | 27 | Additionally, Zaozi separates the eDSL API declaration with Scala 3 `given` pattern, supporting swap APIs implementation through `given` a type class. 28 | 29 | ## Licensing 30 | 31 | The project is licensed under the Apache License 2.0. 32 | 33 | © Jiuyang Liu . All Rights Reserved. 34 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/llhd/given_AttributeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.llhd 4 | 5 | import org.llvm.circt.CAPI.{ 6 | llhdAttrIsATimeAttr, 7 | llhdTimeAttrGet, 8 | llhdTimeAttrGetDelta, 9 | llhdTimeAttrGetEpsilon, 10 | llhdTimeAttrGetSeconds, 11 | llhdTimeAttrGetTimeUnit 12 | } 13 | import org.llvm.mlir.scalalib.capi.support.{*, given} 14 | import org.llvm.mlir.scalalib.capi.ir.{Attribute, Context, given} 15 | 16 | import java.lang.foreign.Arena 17 | 18 | given AttributeApi with 19 | extension (attribute: Attribute) def isTimeAttr(): Boolean = llhdAttrIsATimeAttr(attribute.segment) 20 | def TimeAttrGet( 21 | timeUnit: String, 22 | seconds: BigInt, 23 | delta: BigInt, 24 | epsilon: BigInt 25 | )( 26 | using arena: Arena, 27 | context: Context 28 | ): Attribute = Attribute( 29 | llhdTimeAttrGet(arena, context.segment, timeUnit.toStringRef.segment, seconds.toLong, delta.toLong, epsilon.toLong) 30 | ) 31 | extension (attribute: Attribute) 32 | def TimeAttrGetDelta(): BigInt = llhdTimeAttrGetDelta(attribute.segment) 33 | def TimeAttrGetEpsilon(): BigInt = llhdTimeAttrGetEpsilon(attribute.segment) 34 | def TimeAttrGetSeconds(): BigInt = llhdTimeAttrGetSeconds(attribute.segment) 35 | def TimeAttrGetTimeUnit( 36 | )( 37 | using arena: Arena 38 | ): String = StringRef(llhdTimeAttrGetTimeUnit(arena, attribute.segment)).toScalaString 39 | end given 40 | -------------------------------------------------------------------------------- /circtlib/capi/includeStructs.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | CirctESIAppIDIndex # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/ESI.h 5 | CirctESIBundleTypeBundleChannel # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/ESI.h 6 | FIRRTLBundleField # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/FIRRTL.h 7 | FIRRTLClassElement # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/FIRRTL.h 8 | HWInstanceGraph # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/HW.h 9 | HWInstanceGraphNode # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/HW.h 10 | HWModulePort # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/HW.h 11 | HWStructFieldInfo # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/HW.h 12 | CirctMSFTPlacementDB # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/MSFT.h 13 | CirctMSFTPrimitiveDB # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/MSFT.h 14 | CirctMSFTWalkOrder # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/MSFT.h 15 | OMEvaluator # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/OM.h 16 | OMEvaluatorValue # header: $CIRCT_INSTALL_PATH/include/circt-c/Dialect/OM.h 17 | CirctFirtoolFirtoolOptions # header: $CIRCT_INSTALL_PATH/include/circt-c/Firtool/Firtool.h -------------------------------------------------------------------------------- /mlirlib/src/capi/diagnostic/CAPIImplementation.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.diagnostic 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{MlirDiagnosticError, MlirDiagnosticNote, MlirDiagnosticRemark, MlirDiagnosticWarning} 7 | 8 | import java.lang.foreign.MemorySegment 9 | 10 | given DiagnosticHandlerApi with 11 | extension (diagnosticHandler: DiagnosticHandler) inline def segment: MemorySegment = diagnosticHandler._segment 12 | end given 13 | 14 | given DiagnosticHandlerIDApi with 15 | extension (diagnosticHandlerID: DiagnosticHandlerID) inline def segment: MemorySegment = diagnosticHandlerID._segment 16 | end given 17 | 18 | given DiagnosticEnumApi with 19 | extension (int: Int) 20 | inline def fromNative: DiagnosticSeverityEnum = int match 21 | case i if i == MlirDiagnosticError() => DiagnosticSeverityEnum.Error 22 | case i if i == MlirDiagnosticNote() => DiagnosticSeverityEnum.Note 23 | case i if i == MlirDiagnosticRemark() => DiagnosticSeverityEnum.Remark 24 | case i if i == MlirDiagnosticWarning() => DiagnosticSeverityEnum.Warning 25 | extension (ref: DiagnosticSeverityEnum) 26 | inline def toNative: Int = ref match 27 | case DiagnosticSeverityEnum.Error => MlirDiagnosticError() 28 | case DiagnosticSeverityEnum.Note => MlirDiagnosticNote() 29 | case DiagnosticSeverityEnum.Remark => MlirDiagnosticRemark() 30 | case DiagnosticSeverityEnum.Warning => MlirDiagnosticWarning() 31 | inline def sizeOf: Int = 4 32 | end given 33 | -------------------------------------------------------------------------------- /zaozi/src/default/MonoConnect.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.default 4 | 5 | import me.jiuyang.zaozi.MonoConnect 6 | import me.jiuyang.zaozi.reftpe.Referable 7 | import me.jiuyang.zaozi.valuetpe.Data 8 | 9 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{ConnectApi, InvalidValueApi, given} 10 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, given} 11 | 12 | import java.lang.foreign.Arena 13 | 14 | // TODO: split LHS & RHS into two different trait? this might help for Vec static accessing assignment. 15 | given [D <: Data, SRC <: Referable[D], SINK <: Referable[D]]: MonoConnect[D, SRC, SINK] with 16 | extension (ref: SINK) 17 | def :=( 18 | that: SRC 19 | )( 20 | using Arena, 21 | Context, 22 | Block, 23 | sourcecode.File, 24 | sourcecode.Line 25 | ): Unit = 26 | summon[ConnectApi] 27 | .op( 28 | that.refer, 29 | ref.refer, 30 | locate 31 | ) 32 | .operation 33 | .appendToBlock() 34 | def dontCare( 35 | )( 36 | using Arena, 37 | Context, 38 | Block, 39 | sourcecode.File, 40 | sourcecode.Line 41 | ): Unit = 42 | val invalidOp = summon[InvalidValueApi] 43 | .op( 44 | ref.refer.getType, 45 | locate 46 | ) 47 | invalidOp.operation.appendToBlock() 48 | summon[ConnectApi] 49 | .op( 50 | invalidOp.result, 51 | ref.refer, 52 | locate 53 | ) 54 | .operation 55 | .appendToBlock() 56 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_TypeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirF64TypeGet, 8 | mlirIntegerTypeGet, 9 | mlirIntegerTypeGetWidth, 10 | mlirIntegerTypeSignedGet, 11 | mlirIntegerTypeUnsignedGet, 12 | mlirNoneTypeGet 13 | } 14 | 15 | import java.lang.foreign.{Arena, MemorySegment} 16 | 17 | given TypeApi with 18 | inline def f64TypeGet( 19 | using arena: Arena, 20 | context: Context 21 | ): Type = Type(mlirF64TypeGet(arena, context.segment)) 22 | 23 | inline def noneTypeGet( 24 | using arena: Arena, 25 | context: Context 26 | ) = Type(mlirNoneTypeGet(arena, context.segment)) 27 | 28 | extension (width: Int) 29 | inline def integerTypeSignedGet( 30 | using arena: Arena, 31 | context: Context 32 | ): Type = Type(mlirIntegerTypeSignedGet(arena, context.segment, width)) 33 | inline def integerTypeUnsignedGet( 34 | using arena: Arena, 35 | context: Context 36 | ): Type = Type(mlirIntegerTypeUnsignedGet(arena, context.segment, width)) 37 | inline def integerTypeGet( 38 | using arena: Arena, 39 | context: Context 40 | ): Type = Type(mlirIntegerTypeGet(arena, context.segment, width)) 41 | extension (tpe: Type) 42 | inline def integerTypeGetWidth: Int = 43 | mlirIntegerTypeGetWidth(tpe.segment) 44 | inline def segment: MemorySegment = tpe._segment 45 | inline def sizeOf: Int = MlirType.sizeof().toInt 46 | end given 47 | -------------------------------------------------------------------------------- /rvdecoderdb/src/Utils.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb 5 | 6 | object Utils: 7 | def isR(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("rd", "rs1", "rs2") 8 | 9 | def isI(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("rd", "rs1", "imm12") 10 | 11 | def isS(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("imm12lo", "rs1", "rs2", "imm12hi") 12 | 13 | def isB(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("bimm12lo", "rs1", "rs2", "bimm12hi") 14 | 15 | def isU(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("rd", "imm20") 16 | 17 | def isJ(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("rd", "jimm20") 18 | 19 | def isR4(instruction: Instruction): Boolean = instruction.args.map(_.name) == Seq("rd", "rs1", "rs2", "rs3") 20 | 21 | // some general helper to sort instruction out 22 | def isFP(instruction: Instruction): Boolean = Seq( 23 | "rv_d", 24 | "rv_f", 25 | "rv_q", 26 | "rv64_zfh", 27 | "rv_d_zfh", 28 | "rv_q_zfh", 29 | "rv_zfh", 30 | // unratified 31 | "rv_zfh_zfa" 32 | ).exists(instruction.instructionSets.map(_.name).contains) 33 | 34 | def readRs1(instruction: Instruction): Boolean = instruction.args.map(_.name).contains("rs1") 35 | 36 | def readRs2(instruction: Instruction): Boolean = instruction.args.map(_.name).contains("rs2") 37 | 38 | def writeRd(instruction: Instruction): Boolean = instruction.args.map(_.name).contains("rd") 39 | -------------------------------------------------------------------------------- /zaozi/src/default/Naming.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.default 4 | 5 | import org.llvm.mlir.scalalib.capi.ir.{given_LocationApi, Context, Location, LocationApi} 6 | 7 | import java.lang.foreign.Arena 8 | import me.jiuyang.zaozi.Parameter 9 | import me.jiuyang.zaozi.HWInterface 10 | import me.jiuyang.zaozi.DVInterface 11 | import org.llvm.mlir.scalalib.capi.ir.Block 12 | import me.jiuyang.zaozi.reftpe.Interface 13 | import me.jiuyang.zaozi.ConstructorApi 14 | import me.jiuyang.zaozi.InstanceContext 15 | import javax.naming.NameNotFoundException 16 | 17 | private inline def locate( 18 | using Arena, 19 | Context, 20 | sourcecode.File, 21 | sourcecode.Line 22 | ): Location = 23 | summon[LocationApi].locationFileLineColGet( 24 | summon[sourcecode.File].value, 25 | summon[sourcecode.Line].value, 26 | 0 27 | ) 28 | 29 | private inline def valName( 30 | using sourcecode.Name.Machine, 31 | InstanceContext 32 | ): String = summon[sourcecode.Name.Machine].value match 33 | case actualName if !sourcecode.Util.isSyntheticName(actualName) => actualName 34 | case _ => s"_GEN_${summon[InstanceContext].anonSignalCounter.inc()}" 35 | 36 | private inline def bundleFieldName( 37 | using sourcecode.Name.Machine 38 | ): String = summon[sourcecode.Name.Machine].value match 39 | case actualName if !sourcecode.Util.isSyntheticName(actualName) => actualName 40 | case anonName => throw NameNotFoundException(s"Cannot find name for BundleField ${anonName}") 41 | -------------------------------------------------------------------------------- /zaozi/lit/tests/IllegalOverridenGenerator.sc: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // RUN: not scala-cli compile %s --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION -O="-experimental" 2>&1 >/dev/null | FileCheck %s -check-prefix=ERROR 5 | 6 | import me.jiuyang.zaozi.default.{*, given} 7 | import me.jiuyang.zaozi.* 8 | import me.jiuyang.zaozi.reftpe.* 9 | import me.jiuyang.zaozi.valuetpe.* 10 | import org.llvm.circt.scalalib.capi.dialect.firrtl.DialectApi as FirrtlDialectApi 11 | import org.llvm.circt.scalalib.capi.dialect.firrtl.given_DialectApi 12 | 13 | import java.lang.foreign.Arena 14 | 15 | case class PassthroughParameter(width: Int) extends Parameter 16 | given upickle.default.ReadWriter[PassthroughParameter] = upickle.default.macroRW 17 | 18 | class PassthroughLayers(parameter: PassthroughParameter) extends LayerInterface(parameter): 19 | def layers = Seq.empty 20 | 21 | class PassthroughIO(parameter: PassthroughParameter) extends HWBundle(parameter): 22 | val i = Flipped(UInt(parameter.width.W)) 23 | val o = Aligned(UInt(parameter.width.W)) 24 | 25 | class PassthroughProbe(parameter: PassthroughParameter) 26 | extends DVBundle[PassthroughParameter, PassthroughLayers](parameter) 27 | 28 | @generator 29 | object PassthroughModule extends Generator[PassthroughParameter, PassthroughLayers, PassthroughIO, PassthroughProbe]: 30 | def architecture(parameter: PassthroughParameter) = 31 | val io = summon[Interface[PassthroughIO]] 32 | io.o := io.i 33 | 34 | // ERROR: Overriding interface is forbidden 35 | def interface(parameter: PassthroughParameter) = new PassthroughIO(new PassthroughParameter(32)) 36 | -------------------------------------------------------------------------------- /zaozi/src/default/BundleApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.default 4 | 5 | import me.jiuyang.zaozi.* 6 | import me.jiuyang.zaozi.default.{*, given} 7 | import me.jiuyang.zaozi.magic.UntypedDynamicSubfield 8 | import me.jiuyang.zaozi.reftpe.Node 9 | import me.jiuyang.zaozi.reftpe.{Ref, Referable} 10 | import me.jiuyang.zaozi.valuetpe.Bits 11 | import me.jiuyang.zaozi.valuetpe.Bundle 12 | import me.jiuyang.zaozi.valuetpe.ProbeBundle 13 | import me.jiuyang.zaozi.valuetpe.{Data, ProbeRecord, Record} 14 | import org.llvm.circt.scalalib.capi.dialect.firrtl.{*, given} 15 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{given_BitCastApi, BitCastApi} 16 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{given_WireApi, WireApi} 17 | import org.llvm.mlir.scalalib.capi.ir.{*, given} 18 | 19 | import java.lang.foreign.Arena 20 | 21 | given [T <: Bundle | ProbeBundle, R <: Referable[T]]: BundleApi[T, R] with 22 | extension (ref: R) 23 | def asBits( 24 | using Arena, 25 | Context, 26 | Block, 27 | sourcecode.File, 28 | sourcecode.Line, 29 | sourcecode.Name.Machine, 30 | InstanceContext 31 | ): Node[Bits] = 32 | val bitcastOp = summon[BitCastApi].op( 33 | input = ref.refer, 34 | tpe = Bits(ref.refer.getType.getBitWidth(true).toInt.W).toMlirType, 35 | location = locate 36 | ) 37 | bitcastOp.operation.appendToBlock() 38 | new Node[Bits]: 39 | val _tpe: Bits = new Bits: 40 | private[zaozi] val _width = bitcastOp.operation.getResult(0).getType.getBitWidth(true).toInt 41 | val _operation: Operation = bitcastOp.operation 42 | end given 43 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_DialectApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirDialectHandleGetNamespace, 8 | mlirDialectHandleInsertDialect, 9 | mlirDialectHandleLoadDialect, 10 | mlirDialectHandleRegisterDialect, 11 | mlirGetDialectHandle__func__ 12 | } 13 | import org.llvm.mlir.scalalib.capi.support.{*, given} 14 | 15 | import java.lang.foreign.{Arena, MemorySegment} 16 | 17 | given DialectApi with 18 | extension (dialect: Dialect) 19 | inline def segment: MemorySegment = dialect._segment 20 | inline def sizeOf: Int = MlirDialect.sizeof().toInt 21 | end given 22 | 23 | given DialectHandleApi with 24 | extension (dialectHandle: DialectHandle) 25 | inline def getNamespace( 26 | using arena: Arena 27 | ): String = StringRef(mlirDialectHandleGetNamespace(arena, dialectHandle.segment)).toScalaString 28 | inline def loadDialect( 29 | using arena: Arena, 30 | context: Context 31 | ): Unit = mlirDialectHandleLoadDialect(arena, dialectHandle.segment, context.segment) 32 | inline def insertDialect(dialectRegistry: DialectRegistry): Unit = 33 | mlirDialectHandleInsertDialect(dialectHandle.segment, dialectRegistry.segment) 34 | inline def insertDialect( 35 | )( 36 | using context: Context 37 | ): Unit = 38 | mlirDialectHandleRegisterDialect(dialectHandle.segment, context.segment) 39 | inline def segment: MemorySegment = dialectHandle._segment 40 | inline def sizeOf: Int = MlirDialectHandle.sizeof().toInt 41 | end given 42 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/om/given_AttributeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Yuhang Zeng 3 | package org.llvm.circt.scalalib.capi.dialect.om 4 | 5 | import org.llvm.circt.CAPI.{ 6 | omAttrIsAIntegerAttr, 7 | omAttrIsAListAttr, 8 | omAttrIsAReferenceAttr, 9 | omIntegerAttrGet, 10 | omIntegerAttrGetInt, 11 | omIntegerAttrToString, 12 | omListAttrGetElement, 13 | omListAttrGetNumElements, 14 | omReferenceAttrGetInnerRef 15 | } 16 | import org.llvm.mlir.scalalib.capi.ir.{Attribute, Identifier, given} 17 | 18 | import java.lang.foreign.Arena 19 | 20 | given AttributeApi with 21 | extension (attr: Attribute) 22 | inline def isIntegerAttr: Boolean = omAttrIsAIntegerAttr(attr.segment) 23 | inline def isListAttr: Boolean = omAttrIsAListAttr(attr.segment) 24 | inline def isReferenceAttr: Boolean = omAttrIsAReferenceAttr(attr.segment) 25 | inline def integerAttrGet( 26 | using arena: Arena 27 | ): Attribute = Attribute(omIntegerAttrGet(arena, attr.segment)) 28 | inline def integerAttrGetInt( 29 | using arena: Arena 30 | ): Attribute = Attribute(omIntegerAttrGetInt(arena, attr.segment)) 31 | inline def integerAttrToString( 32 | using arena: Arena 33 | ): String = omIntegerAttrToString(arena, attr.segment).toString 34 | inline def listAttrGetElement( 35 | pos: Int 36 | )( 37 | using arena: Arena 38 | ): Attribute = Attribute(omListAttrGetElement(arena, attr.segment, pos)) 39 | inline def listAttrGetNumElements: Int = omListAttrGetNumElements(attr.segment).toInt 40 | inline def referenceAttrGetInnerRef( 41 | using arena: Arena 42 | ): Attribute = Attribute(omReferenceAttrGetInnerRef(arena, attr.segment)) 43 | end given 44 | -------------------------------------------------------------------------------- /circtlib/src/dialect/firrtl/DeclarationAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.dialect.firrtl.operation 4 | 5 | import org.llvm.circt.scalalib.capi.dialect.firrtl.{FirrtlBundleField, FirrtlNameKind} 6 | import org.llvm.mlir.scalalib.capi.support.{*, given} 7 | import org.llvm.mlir.scalalib.capi.ir.{Context, Location, Operation, Type, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | class InstanceChoice(val _operation: Operation) 12 | class Instance(val _operation: Operation) 13 | trait InstanceApi extends HasOperation[Instance]: 14 | inline def op( 15 | moduleName: String, 16 | instanceName: String, 17 | nameKind: FirrtlNameKind, 18 | location: Location, 19 | interface: Seq[FirrtlBundleField], 20 | layers: Seq[Seq[String]] 21 | )( 22 | using arena: Arena, 23 | context: Context 24 | ): Instance 25 | end InstanceApi 26 | class Mem(val _operation: Operation) 27 | class Node(val _operation: Operation) 28 | trait NodeApi extends HasOperation[Node]: 29 | end NodeApi 30 | class Object(val _operation: Operation) 31 | class Reg(val _operation: Operation) 32 | trait RegApi extends HasOperation[Reg]: 33 | end RegApi 34 | class RegReset(val _operation: Operation) 35 | trait RegResetApi extends HasOperation[RegReset]: 36 | end RegResetApi 37 | class Wire(val _operation: Operation) 38 | trait WireApi extends HasOperation[Wire]: 39 | def op( 40 | name: String, 41 | location: Location, 42 | nameKind: FirrtlNameKind, 43 | tpe: Type 44 | )( 45 | using arena: Arena, 46 | context: Context 47 | ): Wire 48 | extension (ref: Wire) 49 | def result( 50 | using Arena 51 | ): Value 52 | end WireApi 53 | -------------------------------------------------------------------------------- /smtlib/tests/src/ParseSpec.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package me.jiuyang.smtlib.tests 4 | 5 | import me.jiuyang.smtlib.parser.{parseSExpr, parseSMT, parseZ3Output, Z3Result, Z3Status} 6 | import me.jiuyang.smtlib.parser.SMTCommand.* 7 | import utest.* 8 | 9 | object ParseSpec extends TestSuite: 10 | val tests = Tests: 11 | test("simple parser"): 12 | parseSExpr( 13 | """(set-logic QF_UF) 14 | |(declare-fun x () Int) 15 | |(assert (> x 5)) 16 | |(check-sat) 17 | |""".stripMargin 18 | ).isSuccess ==> true 19 | test("convert to SMT IR"): 20 | parseSMT( 21 | """(set-logic QF_UF) 22 | |(declare-fun x () Int) 23 | |(assert (> x 5)) 24 | |(check-sat) 25 | |""".stripMargin 26 | ) ==> List( 27 | SetLogic("QF_UF"), 28 | DeclareFun("x", List(), "Int"), 29 | Assert(IntCmp(">", Variable("x"), IntConstant(5))), 30 | Check 31 | ) 32 | test("parse SMT Output"): 33 | parseSMT( 34 | """( 35 | | (define-fun x () Bool true) 36 | | (define-fun y () Bool false) 37 | |)""".stripMargin.stripPrefix("(").stripSuffix(")") 38 | ) ==> List( 39 | DefineFun("x", List(), "Bool", BoolConstant(true)), 40 | DefineFun("y", List(), "Bool", BoolConstant(false)) 41 | ) 42 | test("parse Z3 Result"): 43 | parseZ3Output( 44 | """sat 45 | |( 46 | | (define-fun x () Bool 47 | | true) 48 | | (define-fun y () Bool 49 | | false) 50 | | (define-fun z () Int 51 | | 1) 52 | |)""".stripMargin 53 | ) ==> Z3Result(Z3Status.Sat, Seq(("x", true), ("y", false), ("z", 1))) 54 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/Bundle.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.TypeImpl 6 | import me.jiuyang.zaozi.magic.DynamicSubfield 7 | import me.jiuyang.zaozi.reftpe.Ref 8 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Type, Value} 9 | 10 | import java.lang.foreign.Arena 11 | 12 | trait Bundle extends Aggregate with DynamicSubfield: 13 | def Flipped[T <: Data]( 14 | tpe: T 15 | )( 16 | using TypeImpl, 17 | sourcecode.Name.Machine 18 | ): BundleField[T] = this.FlippedImpl(tpe) 19 | 20 | def Aligned[T <: Data]( 21 | tpe: T 22 | )( 23 | using TypeImpl, 24 | sourcecode.Name.Machine 25 | ): BundleField[T] = this.AlignedImpl(tpe) 26 | 27 | def getRefViaFieldValName[E <: Data]( 28 | refer: Value, 29 | fieldValName: String 30 | )( 31 | using Arena, 32 | Block, 33 | Context, 34 | sourcecode.File, 35 | sourcecode.Line, 36 | sourcecode.Name.Machine 37 | )( 38 | using TypeImpl 39 | ): Ref[E] = this.getRefViaFieldValNameImpl( 40 | refer, 41 | fieldValName 42 | ) 43 | 44 | def getOptionRefViaFieldValName[E <: Data]( 45 | refer: Value, 46 | fieldValName: String 47 | )( 48 | using Arena, 49 | Block, 50 | Context, 51 | sourcecode.File, 52 | sourcecode.Line, 53 | sourcecode.Name.Machine 54 | )( 55 | using TypeImpl 56 | ): Option[Ref[E]] = this.getOptionRefViaFieldValNameImpl( 57 | refer, 58 | fieldValName 59 | ) 60 | 61 | def toMlirType( 62 | using Arena, 63 | Context, 64 | TypeImpl 65 | ): Type = this.toMlirTypeImpl 66 | 67 | trait BundleField[T <: Data]: 68 | private[zaozi] val _name: String 69 | private[zaozi] val _isFlip: Boolean 70 | private[zaozi] val _tpe: T 71 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_ValueApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirValueDump, 8 | mlirValueGetFirstUse, 9 | mlirValueGetType, 10 | mlirValuePrint, 11 | mlirValuePrintAsOperand, 12 | mlirValueReplaceAllUsesOfWith, 13 | mlirValueSetType 14 | } 15 | import org.llvm.mlir.scalalib.capi.support.{*, given} 16 | 17 | import java.lang.foreign.{Arena, MemorySegment} 18 | 19 | given ValueApi with 20 | extension (value: Value) 21 | inline def getType( 22 | using arena: Arena 23 | ): Type = Type(mlirValueGetType(arena, value.segment)) 24 | inline def getFirstUse( 25 | using arena: Arena 26 | ): Type = Type(mlirValueGetFirstUse(arena, value.segment)) 27 | inline def setType(tpe: Type): Unit = mlirValueSetType(value.segment, tpe.segment) 28 | inline def dump(): Unit = mlirValueDump(value.segment) 29 | inline def print( 30 | callback: String => Unit 31 | )( 32 | using arena: Arena 33 | ): Unit = mlirValuePrint(value.segment, callback.stringToStringCallback.segment, MemorySegment.NULL) 34 | inline def printAsOperand( 35 | state: AsmState, 36 | callback: String => Unit 37 | )( 38 | using arena: Arena 39 | ): Unit = 40 | mlirValuePrintAsOperand(value.segment, state.segment, callback.stringToStringCallback.segment, MemorySegment.NULL) 41 | inline def replaceAllUsesOfWith(w: Value): Unit = mlirValueReplaceAllUsesOfWith(value.segment, w.segment) 42 | inline def segment: MemorySegment = value._segment 43 | inline def sizeOf: Int = MlirValue.sizeof().toInt 44 | end given 45 | -------------------------------------------------------------------------------- /zaozi/lit/tests/ExportVerilog.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // DEFINE: %{test} = scala-cli --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION -O="-experimental" --java-opt="--enable-native-access=ALL-UNNAMED" --java-opt="--enable-preview" --java-opt="-Djava.library.path=%JAVALIBRARYPATH" %s -- 5 | // RUN: %{test} config %t.json --width 32 6 | // RUN: %{test} design %t.json 7 | // RUN: firtool Passthrough*.mlirbc | FileCheck %s -check-prefix=VERILOG 8 | // RUN: rm %t.json *.mlirbc -f 9 | 10 | import me.jiuyang.zaozi.* 11 | import me.jiuyang.zaozi.reftpe.* 12 | import me.jiuyang.zaozi.valuetpe.* 13 | import me.jiuyang.zaozi.default.{*, given} 14 | 15 | import java.lang.foreign.Arena 16 | 17 | case class PassthroughParameter(width: Int) extends Parameter 18 | given upickle.default.ReadWriter[PassthroughParameter] = upickle.default.macroRW 19 | 20 | class PassthroughLayers(parameter: PassthroughParameter) extends LayerInterface(parameter): 21 | def layers = Seq.empty 22 | 23 | class PassthroughIO(parameter: PassthroughParameter) extends HWBundle(parameter): 24 | val i = Flipped(UInt(parameter.width.W)) 25 | val o = Aligned(UInt(parameter.width.W)) 26 | 27 | class PassthroughProbe(parameter: PassthroughParameter) 28 | extends DVBundle[PassthroughParameter, PassthroughLayers](parameter) 29 | 30 | @generator 31 | object PassthroughModule extends Generator[PassthroughParameter, PassthroughLayers, PassthroughIO, PassthroughProbe]: 32 | // VERILOG-LABEL: module PassthroughModule_e88425e0( 33 | def architecture(parameter: PassthroughParameter) = 34 | // VERILOG-NEXT: input [31:0] i, 35 | // VERILOG-NEXT: output [31:0] o 36 | // VERILOG-NEXT: ); 37 | // VERILOG: assign o = i; 38 | val io = summon[Interface[PassthroughIO]] 39 | io.o := io.i 40 | // VERILOG: endmodule 41 | -------------------------------------------------------------------------------- /zaozi/src/magic/DynamicSubfield.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.magic 4 | 5 | import me.jiuyang.zaozi.reftpe.Ref 6 | import me.jiuyang.zaozi.valuetpe.Data 7 | import me.jiuyang.zaozi.TypeImpl 8 | import org.llvm.circt.scalalib.dialect.firrtl.operation.Module as CirctModule 9 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Operation, Type, Value} 10 | 11 | import java.lang.foreign.Arena 12 | import scala.language.dynamics 13 | 14 | /** Due to Scala not allowing deferred macro call(calling user defined macro from outer macro). Any implementation to 15 | * [[DynamicSubfield]] should make sure the dynamic access is to a val that has a return type of [[BundleField]]. For 16 | * now jiuyang cannot come up with better solution to let user define their own macro, however they can still implement 17 | * their own [[Bundle]]. 18 | */ 19 | trait DynamicSubfield: 20 | def getRefViaFieldValName[E <: Data]( 21 | refer: Value, 22 | fieldValName: String 23 | )( 24 | using Arena, 25 | Block, 26 | Context, 27 | sourcecode.File, 28 | sourcecode.Line, 29 | sourcecode.Name.Machine 30 | )( 31 | using TypeImpl 32 | ): Ref[E] 33 | 34 | def getOptionRefViaFieldValName[E <: Data]( 35 | refer: Value, 36 | fieldValName: String 37 | )( 38 | using Arena, 39 | Block, 40 | Context, 41 | sourcecode.File, 42 | sourcecode.Line, 43 | sourcecode.Name.Machine 44 | )( 45 | using TypeImpl 46 | ): Option[Ref[E]] 47 | 48 | trait UntypedDynamicSubfield: 49 | def getUntypedRefViaFieldValName( 50 | refer: Value, 51 | fieldValName: String 52 | )( 53 | using Arena, 54 | Block, 55 | Context, 56 | sourcecode.File, 57 | sourcecode.Line, 58 | sourcecode.Name.Machine 59 | )( 60 | using TypeImpl 61 | ): Ref[Data] 62 | -------------------------------------------------------------------------------- /zaozi/src/valuetpe/ProbeBundle.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.valuetpe 4 | 5 | import me.jiuyang.zaozi.{LayerTree, TypeImpl} 6 | import me.jiuyang.zaozi.magic.DynamicSubfield 7 | import me.jiuyang.zaozi.reftpe.Ref 8 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Type, Value} 9 | 10 | import java.lang.foreign.Arena 11 | 12 | // The ProbeBundle is only defined at the interface of a module 13 | trait ProbeBundle extends Aggregate with DynamicSubfield: 14 | def ProbeRead[T <: Data & CanProbe]( 15 | tpe: T, 16 | layer: LayerTree 17 | )( 18 | using TypeImpl, 19 | sourcecode.Name.Machine 20 | ): BundleField[RProbe[T]] = 21 | this.ReadProbeImpl(tpe, layer) 22 | 23 | def ProbeReadWrite[T <: Data & CanProbe]( 24 | tpe: T, 25 | layer: LayerTree 26 | )( 27 | using TypeImpl, 28 | sourcecode.Name.Machine 29 | ): BundleField[RWProbe[T]] = 30 | this.ReadWriteProbeImpl(tpe, layer) 31 | 32 | def getRefViaFieldValName[E <: Data]( 33 | refer: Value, 34 | fieldValName: String 35 | )( 36 | using Arena, 37 | Block, 38 | Context, 39 | sourcecode.File, 40 | sourcecode.Line, 41 | sourcecode.Name.Machine 42 | )( 43 | using TypeImpl 44 | ): Ref[E] = this.getRefViaFieldValNameImpl( 45 | refer, 46 | fieldValName 47 | ) 48 | 49 | def getOptionRefViaFieldValName[E <: Data]( 50 | refer: Value, 51 | fieldValName: String 52 | )( 53 | using Arena, 54 | Block, 55 | Context, 56 | sourcecode.File, 57 | sourcecode.Line, 58 | sourcecode.Name.Machine 59 | )( 60 | using TypeImpl 61 | ): Option[Ref[E]] = this.getOptionRefViaFieldValNameImpl( 62 | refer, 63 | fieldValName 64 | ) 65 | 66 | def toMlirType( 67 | using Arena, 68 | Context, 69 | TypeImpl 70 | ): Type = this.toMlirTypeImpl 71 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/hw/CAPIImplementation.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.hw 4 | 5 | import java.lang.foreign.{Arena, MemorySegment} 6 | 7 | given HWModulePortApi with 8 | extension (ref: HWModulePort) 9 | inline def segment: MemorySegment = ref._segment 10 | inline def sizeOf: Int = org.llvm.circt.HWModulePort.sizeof().toInt 11 | end given 12 | 13 | given HWStructFieldInfoApi with 14 | extension (ref: HWStructFieldInfo) 15 | inline def segment: MemorySegment = ref._segment 16 | inline def sizeOf: Int = org.llvm.circt.HWStructFieldInfo.sizeof().toInt 17 | end given 18 | 19 | given HWInstanceGraphNodeCallbackApi with 20 | extension (hwInstanceGraphNodeCallback: HWInstanceGraphNode => Unit) 21 | inline def toHWInstanceGraphNodeCallback( 22 | using arena: Arena 23 | ): InstanceGraphNodeCallback = 24 | InstanceGraphNodeCallback( 25 | org.llvm.circt.HWInstanceGraphNodeCallback.allocate( 26 | (hwInstanceGraphNode: MemorySegment, userData: MemorySegment) => 27 | hwInstanceGraphNodeCallback(HWInstanceGraphNode(hwInstanceGraphNode)), 28 | arena 29 | ) 30 | ) 31 | extension (hwInstanceGraphNodeCallback: InstanceGraphNodeCallback) 32 | inline def segment: MemorySegment = hwInstanceGraphNodeCallback._segment 33 | end given 34 | 35 | given HWInstanceGraphApi with 36 | extension (ref: HWInstanceGraph) 37 | inline def segment: MemorySegment = ref._segment 38 | inline def sizeOf: Int = org.llvm.circt.HWInstanceGraph.sizeof().toInt 39 | end given 40 | 41 | given HWInstanceGraphNodeApi with 42 | extension (ref: HWInstanceGraphNode) 43 | inline def segment: MemorySegment = ref._segment 44 | inline def sizeOf: Int = org.llvm.circt.HWInstanceGraphNode.sizeof().toInt 45 | end given 46 | -------------------------------------------------------------------------------- /mlirlib/capi/jextract-headers.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | #ifndef JEXTRACT_HEADERS_H 4 | #define JEXTRACT_HEADERS_H 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | //fatal error: 'inttypes.h' file not found 46 | //#include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | #endif // JEXTRACT_HEADERS_H 54 | -------------------------------------------------------------------------------- /mlirlib/src/capi/dialect/smt/given_AttributeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.capi.dialect.smt 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirSMTAttrCheckBVCmpPredicate, 8 | mlirSMTAttrCheckIntPredicate, 9 | mlirSMTAttrGetBVCmpPredicate, 10 | mlirSMTAttrGetBitVector, 11 | mlirSMTAttrGetIntPredicate, 12 | mlirSMTAttrIsASMTAttribute 13 | } 14 | import org.llvm.mlir.scalalib.capi.support.{*, given} 15 | import org.llvm.mlir.scalalib.capi.ir.{Attribute, Context, given} 16 | 17 | import java.lang.foreign.Arena 18 | 19 | given AttributeApi with 20 | extension (str: String) 21 | inline def getBVCmpPredicateAttribute( 22 | using arena: Arena, 23 | context: Context 24 | ): Attribute = Attribute(mlirSMTAttrGetBVCmpPredicate(arena, context.segment, str.toStringRef.segment)) 25 | inline def getIntPredicateAttribute( 26 | using arena: Arena, 27 | context: Context 28 | ): Attribute = Attribute(mlirSMTAttrGetIntPredicate(arena, context.segment, str.toStringRef.segment)) 29 | extension (value: Int) 30 | inline def getBitVectorAttribute( 31 | width: Int 32 | )( 33 | using arena: Arena, 34 | context: Context 35 | ): Attribute = Attribute(mlirSMTAttrGetBitVector(arena, context.segment, value, width)) 36 | extension (attr: Attribute) inline def isSMTAttribute: Boolean = mlirSMTAttrIsASMTAttribute(attr.segment) 37 | 38 | extension (str: String) 39 | inline def checkBVCmpPredicateAttribute( 40 | using arena: Arena, 41 | context: Context 42 | ): Boolean = mlirSMTAttrCheckBVCmpPredicate(context.segment, str.toStringRef.segment) 43 | inline def checkIntPredicateAttribute( 44 | using arena: Arena, 45 | context: Context 46 | ): Boolean = mlirSMTAttrCheckIntPredicate(context.segment, str.toStringRef.segment) 47 | end given 48 | -------------------------------------------------------------------------------- /zaozi/src/default/RecordApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.default 4 | 5 | import me.jiuyang.zaozi.* 6 | import me.jiuyang.zaozi.default.{*, given} 7 | import me.jiuyang.zaozi.magic.UntypedDynamicSubfield 8 | import me.jiuyang.zaozi.reftpe.Node 9 | import me.jiuyang.zaozi.reftpe.{Ref, Referable} 10 | import me.jiuyang.zaozi.valuetpe.Bits 11 | import me.jiuyang.zaozi.valuetpe.{Data, ProbeRecord, Record} 12 | import org.llvm.circt.scalalib.capi.dialect.firrtl.{*, given} 13 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{given_BitCastApi, BitCast, BitCastApi} 14 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{given_NodeApi, NodeApi} 15 | import org.llvm.mlir.scalalib.capi.ir.{*, given} 16 | 17 | import java.lang.foreign.Arena 18 | 19 | given [T <: Record | ProbeRecord, R <: Referable[T]]: RecordApi[T, R] with 20 | extension (ref: R) 21 | def asBits( 22 | using Arena, 23 | Context, 24 | Block, 25 | sourcecode.File, 26 | sourcecode.Line, 27 | sourcecode.Name.Machine, 28 | InstanceContext 29 | ): Node[Bits] = 30 | val bitcastOp = summon[BitCastApi].op( 31 | input = ref.refer, 32 | tpe = Bits(ref.refer.getType.getBitWidth(true).toInt.W).toMlirType, 33 | location = locate 34 | ) 35 | bitcastOp.operation.appendToBlock() 36 | new Node[Bits]: 37 | val _tpe: Bits = new Bits: 38 | private[zaozi] val _width = bitcastOp.operation.getResult(0).getType.getBitWidth(true).toInt 39 | val _operation: Operation = bitcastOp.operation 40 | 41 | def field[T <: Data]( 42 | fieldName: String 43 | )( 44 | using Arena, 45 | Block, 46 | Context, 47 | sourcecode.File, 48 | sourcecode.Line, 49 | sourcecode.Name.Machine 50 | ): Ref[T] = ref._tpe.getUntypedRefViaFieldValName(ref.refer, fieldName).asInstanceOf[Ref[T]] 51 | 52 | end given 53 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/hw/given_InstanceGraphApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.capi.dialect.hw 4 | 5 | import org.llvm.circt.CAPI.{ 6 | hwInstanceGraphDestroy, 7 | hwInstanceGraphForEachNode, 8 | hwInstanceGraphGet, 9 | hwInstanceGraphGetTopLevelNode, 10 | hwInstanceGraphNodeEqual, 11 | hwInstanceGraphNodeGetModule, 12 | hwInstanceGraphNodeGetModuleOp 13 | } 14 | import org.llvm.mlir.scalalib.capi.ir.{Module, Operation, given} 15 | 16 | import java.lang.foreign.{Arena, MemorySegment} 17 | 18 | given InstanceGraphApi with 19 | extension (hwInstanceGraph: HWInstanceGraph) 20 | inline def destroy: Unit = hwInstanceGraphDestroy(hwInstanceGraph.segment) 21 | inline def getTopLevelNode( 22 | using arena: Arena 23 | ): HWInstanceGraphNode = HWInstanceGraphNode(hwInstanceGraphGetTopLevelNode(arena, hwInstanceGraph.segment)) 24 | inline def forEachNode( 25 | callback: HWInstanceGraphNode => Unit 26 | )( 27 | using arena: Arena 28 | ): Unit = 29 | hwInstanceGraphForEachNode( 30 | hwInstanceGraph.segment, 31 | callback.toHWInstanceGraphNodeCallback.segment, 32 | MemorySegment.NULL 33 | ) 34 | extension (operation: Operation) 35 | inline def instanceGraphGet( 36 | using arena: Arena 37 | ): HWInstanceGraph = HWInstanceGraph(hwInstanceGraphGet(arena, operation.segment)) 38 | extension (hwInstanceGraphNode: HWInstanceGraphNode) 39 | inline def equal(that: HWInstanceGraphNode): Boolean = 40 | hwInstanceGraphNodeEqual(hwInstanceGraphNode.segment, that.segment) 41 | inline def getModule( 42 | using arena: Arena 43 | ): Module = new Module(hwInstanceGraphNodeGetModule(arena, hwInstanceGraphNode.segment)) 44 | inline def getModuleOp( 45 | using arena: Arena 46 | ): Operation = Operation(hwInstanceGraphNodeGetModuleOp(arena, hwInstanceGraphNode.segment)) 47 | end given 48 | -------------------------------------------------------------------------------- /circtlib/src/dialect/firrtl/StatementAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.dialect.firrtl.operation 4 | 5 | import org.llvm.mlir.scalalib.capi.support.HasOperation 6 | import org.llvm.mlir.scalalib.capi.ir.Operation 7 | 8 | class Assert(val _operation: Operation) 9 | class Assume(val _operation: Operation) 10 | class Attach(val _operation: Operation) 11 | class Connect(val _operation: Operation) 12 | trait ConnectApi extends HasOperation[Connect]: 13 | end ConnectApi 14 | 15 | class Cover(val _operation: Operation) 16 | class Force(val _operation: Operation) 17 | class LayerBlock(val _operation: Operation) 18 | trait LayerBlockApi extends HasOperation[LayerBlock]: 19 | end LayerBlockApi 20 | class Match(val _operation: Operation) 21 | class MatchingConnect(val _operation: Operation) 22 | class Printf(val _operation: Operation) 23 | class Propassign(val _operation: Operation) 24 | class RefDefine(val _operation: Operation) 25 | trait RefDefineApi extends HasOperation[RefDefine]: 26 | end RefDefineApi 27 | class RefForceInitial(val _operation: Operation) 28 | trait RefForceInitialApi extends HasOperation[RefForceInitial]: 29 | end RefForceInitialApi 30 | class RefForce(val _operation: Operation) 31 | trait RefForceApi extends HasOperation[RefForce]: 32 | end RefForceApi 33 | class RefReleaseInitial(val _operation: Operation) 34 | trait RefReleaseInitialApi extends HasOperation[RefReleaseInitial]: 35 | end RefReleaseInitialApi 36 | class RefRelease(val _operation: Operation) 37 | trait RefReleaseApi extends HasOperation[RefRelease]: 38 | end RefReleaseApi 39 | class Skip(val _operation: Operation) 40 | class Stop(val _operation: Operation) 41 | class IntVerifAssert(val _operation: Operation) 42 | class IntVerifAssume(val _operation: Operation) 43 | class IntVerifCover(val _operation: Operation) 44 | class When(val _operation: Operation) 45 | trait WhenApi extends HasOperation[When]: 46 | end WhenApi 47 | -------------------------------------------------------------------------------- /zaozi/stdlib/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package build.zaozi.stdlib 4 | 5 | import mill._ 6 | import mill.scalalib.TestModule.Utest 7 | import mill.scalalib._ 8 | import mill.scalalib.scalafmt._ 9 | import os.Path 10 | 11 | import build.{circtlib, decoder, v, zaozi, LitModule} 12 | import build.zaozi.testlib 13 | 14 | object `package` extends ScalaModule with ScalafmtModule { m => 15 | def scalaVersion = Task(v.scala) 16 | def moduleDeps = Seq(zaozi, decoder) 17 | 18 | override def scalacOptions: T[Seq[String]] = Task(super.scalacOptions() ++ Seq("-experimental")) 19 | 20 | override def forkArgs: T[Seq[String]] = Task( 21 | super.forkArgs() ++ circtlib.forkArgs() 22 | ) 23 | 24 | object lit extends ScalaModule with ScalafmtModule { 25 | def scalaVersion = Task(v.scala) 26 | def moduleDeps = Seq(m) 27 | override def forkArgs: T[Seq[String]] = Task( 28 | super.forkArgs() ++ circtlib.forkArgs() 29 | ) 30 | object tests extends LitModule { 31 | def scalaVersion: T[String] = Task(m.scalaVersion()) 32 | def runClasspath: T[Seq[os.Path]] = Task(lit.runClasspath().map(_.path)) 33 | def javaLibraryPath: T[Seq[os.Path]] = Task( 34 | (circtlib.libraryPaths()).map(_.path) 35 | ) 36 | def javaHome: T[os.Path] = Task(os.Path(sys.props("java.home"))) 37 | def litDir: T[os.Path] = Task(moduleDir) 38 | def litConfigIn: T[PathRef] = Task.Source(moduleDir / "lit.site.cfg.py.in") 39 | } 40 | } 41 | 42 | object tests extends ScalaTests with ScalafmtModule with Utest { 43 | override def scalacOptions: T[Seq[String]] = Task(super.scalacOptions().filterNot(_ == "-Xcheck-macros")) 44 | 45 | def mvnDeps = Seq(v.utest) 46 | 47 | override def moduleDeps: Seq[JavaModule] = Seq(m, testlib) 48 | 49 | override def forkArgs: T[Seq[String]] = Task( 50 | super.forkArgs() ++ circtlib.forkArgs() 51 | ) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_ModuleApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirModuleCreateEmpty, 8 | mlirModuleCreateParse, 9 | mlirModuleDestroy, 10 | mlirModuleFromOperation, 11 | mlirModuleGetBody, 12 | mlirModuleGetContext, 13 | mlirModuleGetOperation 14 | } 15 | import org.llvm.mlir.scalalib.capi.support.{*, given} 16 | 17 | import java.lang.foreign.{Arena, MemorySegment} 18 | 19 | given ModuleApi with 20 | inline def moduleCreateEmpty( 21 | location: Location 22 | )( 23 | using arena: Arena 24 | ): Module = new Module(mlirModuleCreateEmpty(arena, location.segment)) 25 | 26 | inline def moduleCreateParse( 27 | module: String | Array[Byte] 28 | )( 29 | using arena: Arena, 30 | context: Context 31 | ): Module = new Module( 32 | mlirModuleCreateParse( 33 | arena, 34 | context.segment, 35 | (module match 36 | case string: String => string.toStringRef 37 | case bytes: Array[Byte] => bytes.toStringRef 38 | ).segment 39 | ) 40 | ) 41 | 42 | inline def moduleFromOperation( 43 | op: Operation 44 | )( 45 | using arena: Arena 46 | ): Module = new Module(mlirModuleFromOperation(arena, op.segment)) 47 | 48 | extension (module: Module) 49 | inline def getContext( 50 | using arena: Arena 51 | ): Context = Context(mlirModuleGetContext(arena, module.segment)) 52 | inline def getBody( 53 | using arena: Arena 54 | ) = Block(mlirModuleGetBody(arena, segment)) 55 | inline def getOperation( 56 | using arena: Arena 57 | ): Operation = Operation(mlirModuleGetOperation(arena, module.segment)) 58 | inline def destroy(): Unit = mlirModuleDestroy(module.segment) 59 | inline def segment: MemorySegment = module._segment 60 | inline def sizeOf: Int = MlirModule.sizeof().toInt 61 | end given 62 | -------------------------------------------------------------------------------- /zaozi/lit/tests/OverriddenMain.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // DEFINE: %{test} = scala-cli --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION -O="-experimental" --java-opt="--enable-native-access=ALL-UNNAMED" --java-opt="--enable-preview" --java-opt="-Djava.library.path=%JAVALIBRARYPATH" %s -- 5 | // RUN: not %{test} config %t.json --width 32 | FileCheck %s 6 | 7 | import me.jiuyang.zaozi.* 8 | import me.jiuyang.zaozi.reftpe.* 9 | import me.jiuyang.zaozi.valuetpe.* 10 | import me.jiuyang.zaozi.default.{*, given} 11 | 12 | import java.lang.foreign.Arena 13 | 14 | case class PassthroughParameter(width: Int) extends Parameter 15 | given upickle.default.ReadWriter[PassthroughParameter] = upickle.default.macroRW 16 | 17 | class PassthroughLayers(parameter: PassthroughParameter) extends LayerInterface(parameter): 18 | def layers = Seq.empty 19 | 20 | class PassthroughIO(parameter: PassthroughParameter) extends HWBundle(parameter): 21 | val i = Flipped(UInt(parameter.width.W)) 22 | val o = Aligned(UInt(parameter.width.W)) 23 | 24 | class PassthroughProbe(parameter: PassthroughParameter) 25 | extends DVBundle[PassthroughParameter, PassthroughLayers](parameter) 26 | 27 | @generator 28 | object PassthroughModule extends Generator[PassthroughParameter, PassthroughLayers, PassthroughIO, PassthroughProbe]: 29 | def architecture(parameter: PassthroughParameter) = 30 | val io = summon[Interface[PassthroughIO]] 31 | io.o := io.i 32 | 33 | def main(args: Array[String]): Unit = 34 | // CHECK: you can override method `main` and `parseParameter` in generator 35 | println("you can override method `main` and `parseParameter` in generator") 36 | this.mainImpl(args) 37 | 38 | def parseParameter(args: Seq[String]): PassthroughParameter = 39 | // CHECK: This module does not support to construct from command-line 40 | println("This module does not support to construct from command-line") 41 | sys.exit(1) 42 | -------------------------------------------------------------------------------- /zaozi/lit/tests/DefaultValueParam.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // DEFINE: %{test} = scala-cli --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION -O="-experimental" --java-opt="--enable-native-access=ALL-UNNAMED" --java-opt="--enable-preview" --java-opt="-Djava.library.path=%JAVALIBRARYPATH" %s -- 5 | // RUN: %{test} config %t.json --input-width 32 6 | // RUN: FileCheck %s -check-prefix=CONFIG --input-file=%t.json 7 | // RUN: %{test} design %t.json 8 | // RUN: firtool Truncate*.mlirbc | FileCheck %s -check-prefix=VERILOG 9 | // RUN: rm %t.json *.mlirbc -f 10 | 11 | import me.jiuyang.zaozi.* 12 | import me.jiuyang.zaozi.reftpe.* 13 | import me.jiuyang.zaozi.valuetpe.* 14 | import me.jiuyang.zaozi.default.{*, given} 15 | 16 | import java.lang.foreign.Arena 17 | 18 | // CONFIG: {"inputWidth":32} 19 | case class TruncateParameter(inputWidth: Int, outputWidth: Int = 16) extends Parameter: 20 | require(outputWidth <= inputWidth) 21 | given upickle.default.ReadWriter[TruncateParameter] = upickle.default.macroRW 22 | 23 | class TruncateLayers(parameter: TruncateParameter) extends LayerInterface(parameter): 24 | def layers = Seq.empty 25 | 26 | class TruncateIO(parameter: TruncateParameter) extends HWBundle(parameter): 27 | val i = Flipped(UInt(parameter.inputWidth.W)) 28 | val o = Aligned(UInt(parameter.outputWidth.W)) 29 | 30 | class TruncateProbe(parameter: TruncateParameter) extends DVBundle[TruncateParameter, TruncateLayers](parameter) 31 | 32 | @generator 33 | object Truncate extends Generator[TruncateParameter, TruncateLayers, TruncateIO, TruncateProbe]: 34 | // VERILOG-LABEL: module Truncate_90db6580( 35 | def architecture(parameter: TruncateParameter) = 36 | // VERILOG-NEXT: input [31:0] i, 37 | // VERILOG-NEXT: output [15:0] o 38 | // VERILOG-NEXT: ); 39 | // VERILOG: assign o = i[15:0]; 40 | val io = summon[Interface[TruncateIO]] 41 | io.o := io.i.asBits.tail(parameter.outputWidth).asUInt 42 | // VERILOG: endmodule 43 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_RegionApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirRegionAppendOwnedBlock, 8 | mlirRegionCreate, 9 | mlirRegionDestroy, 10 | mlirRegionGetFirstBlock, 11 | mlirRegionGetNextInOperation, 12 | mlirRegionInsertOwnedBlock, 13 | mlirRegionInsertOwnedBlockAfter, 14 | mlirRegionInsertOwnedBlockBefore 15 | } 16 | 17 | import java.lang.foreign.{Arena, MemorySegment} 18 | 19 | given RegionApi with 20 | inline def regionCreate( 21 | using arena: Arena 22 | ): Region = 23 | Region(mlirRegionCreate(arena)) 24 | 25 | extension (region: Region) 26 | inline def getFirstBlock( 27 | using arena: Arena 28 | ): Block = Block(mlirRegionGetFirstBlock(arena, region.segment)) 29 | inline def getNextInOperation( 30 | using arena: Arena 31 | ): Region = Region(mlirRegionGetNextInOperation(arena, region.segment)) 32 | inline def destroy( 33 | )( 34 | using arena: Arena 35 | ): Unit = mlirRegionDestroy(region.segment) 36 | inline def appendOwnedBlock(block: Block): Unit = 37 | mlirRegionAppendOwnedBlock(region.segment, block.segment) 38 | inline def insertOwnedBlock(pos: Long, block: Block): Unit = 39 | mlirRegionInsertOwnedBlock(region.segment, pos, block.segment) 40 | inline def insertOwnedBlockAfter(reference: Block, block: Block): Unit = 41 | mlirRegionInsertOwnedBlockAfter(region.segment, reference.segment, block.segment) 42 | inline def insertOwnedBlockBefore(reference: Block, block: Block): Unit = 43 | mlirRegionInsertOwnedBlockBefore(region.segment, reference.segment, block.segment) 44 | inline def segment: MemorySegment = region._segment 45 | inline def sizeOf: Int = MlirRegion.sizeof().toInt 46 | 47 | end given 48 | -------------------------------------------------------------------------------- /zaozi/lit/tests/IllegalParameterType.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // RUN: not scala-cli compile %s --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION -O="-experimental" 2>&1 >/dev/null | FileCheck %s -check-prefix=ERROR 5 | 6 | import me.jiuyang.zaozi.* 7 | import me.jiuyang.zaozi.reftpe.* 8 | import me.jiuyang.zaozi.valuetpe.* 9 | import me.jiuyang.zaozi.default.{*, given} 10 | 11 | import java.lang.foreign.Arena 12 | 13 | // ERROR: PassthroughParameterA should be a case class 14 | class PassthroughParameterA(val width: Int) extends Parameter 15 | 16 | class PassthroughLayersA(parameter: PassthroughParameterA) extends LayerInterface(parameter): 17 | def layers = Seq.empty 18 | 19 | class PassthroughIOA(parameter: PassthroughParameterA) extends HWBundle(parameter): 20 | val i = Flipped(UInt(parameter.width.W)) 21 | val o = Aligned(UInt(parameter.width.W)) 22 | 23 | class PassthroughProbeA(parameter: PassthroughParameterA) 24 | extends DVBundle[PassthroughParameterA, PassthroughLayersA](parameter) 25 | 26 | @generator 27 | object PassthroughA extends Generator[PassthroughParameterA, PassthroughLayersA, PassthroughIOA, PassthroughProbeA]: 28 | def architecture(parameter: PassthroughParameterA) = () 29 | 30 | // ERROR: Multiple parameter lists not supported 31 | case class PassthroughParameterB(width: Int)() extends Parameter 32 | 33 | class PassthroughLayersB(parameter: PassthroughParameterB) extends LayerInterface(parameter) 34 | 35 | class PassthroughIOB(parameter: PassthroughParameterB) extends HWBundle(parameter): 36 | val i = Flipped(UInt(parameter.width.W)) 37 | val o = Aligned(UInt(parameter.width.W)) 38 | 39 | class PassthroughProbeB(parameter: PassthroughParameterB) 40 | extends DVBundle[PassthroughParameterB, PassthroughLayersB](parameter) 41 | 42 | @generator 43 | object PassthroughB extends Generator[PassthroughParameterB, PassthroughLayersB, PassthroughIOB, PassthroughProbeB]: 44 | def architecture(parameter: PassthroughParameterB) = () 45 | -------------------------------------------------------------------------------- /zaozi/stdlib/tests/src/BitSetSpec.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.stdlib 4 | 5 | import mainargs.TokensReader 6 | 7 | import me.jiuyang.zaozi.* 8 | import me.jiuyang.decoder.* 9 | import me.jiuyang.zaozi.reftpe.* 10 | import me.jiuyang.zaozi.valuetpe.* 11 | import me.jiuyang.zaozi.default.{*, given} 12 | import me.jiuyang.zaozi.testlib.* 13 | import me.jiuyang.decoder.given_ReadWriter_BitSet 14 | import utest.* 15 | 16 | case class BitSetSpecParameter(bs: BitSet) extends Parameter: 17 | def width = bs.width 18 | given upickle.default.ReadWriter[BitSetSpecParameter] = upickle.default.macroRW 19 | given TokensReader.Simple[BitSet]: 20 | def shortName = "bitset" 21 | def read(strs: Seq[String]): Right[Nothing, BitSet] = Right(BitSet.bitset(strs.head)) 22 | 23 | class BitSetSpecLayers(parameter: BitSetSpecParameter) extends LayerInterface(parameter): 24 | def layers = Seq.empty 25 | 26 | class BitSetSpecIO(parameter: BitSetSpecParameter) extends HWBundle(parameter): 27 | val i = Flipped(Bits(parameter.width.W)) 28 | val o = Aligned(Bool()) 29 | 30 | class BitSetSpecProbe(parameter: BitSetSpecParameter) extends DVBundle[BitSetSpecParameter, BitSetSpecLayers](parameter) 31 | 32 | object BitSetSpec extends TestSuite: 33 | val tests = Tests: 34 | test("BitSetApi"): 35 | test("cover"): 36 | @generator 37 | object Cover 38 | extends Generator[BitSetSpecParameter, BitSetSpecLayers, BitSetSpecIO, BitSetSpecProbe] 39 | with HasVerilogTest: 40 | def architecture(parameter: BitSetSpecParameter) = 41 | val io = summon[Interface[BitSetSpecIO]] 42 | io.o := parameter.bs.cover(io.i) 43 | Cover.verilogTest( 44 | BitSetSpecParameter( 45 | BitSet( 46 | Set( 47 | BitSet.bitpat("101"), 48 | BitSet.bitpat("?01") 49 | ) 50 | ) 51 | ) 52 | )( 53 | "assign o = i == 3'h5 | i[1:0] == 2'h1" 54 | ) 55 | -------------------------------------------------------------------------------- /zaozi/stdlib/src/Decoder.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.stdlib 4 | 5 | import mainargs.TokensReader 6 | import me.jiuyang.zaozi.* 7 | import me.jiuyang.zaozi.reftpe.* 8 | import me.jiuyang.zaozi.valuetpe.* 9 | import me.jiuyang.zaozi.default.{*, given} 10 | import me.jiuyang.decoder.* 11 | import org.llvm.mlir.scalalib.capi.ir.Block 12 | import org.llvm.mlir.scalalib.capi.ir.Context 13 | 14 | import java.lang.foreign.Arena 15 | 16 | case class DecoderParameter(name: String, tables: Seq[TruthTable]) extends Parameter: 17 | lazy val pla: PLA = espresso(tables) 18 | 19 | // json 20 | given upickle.default.ReadWriter[DecoderParameter] = 21 | upickle.default 22 | .readwriter[ujson.Value] 23 | .bimap[DecoderParameter]( 24 | decoder => 25 | ujson.Obj( 26 | "name" -> decoder.name, 27 | "tables" -> ujson.Arr(decoder.tables.map(_.toString).map(ujson.Str.apply)*) 28 | ), 29 | json => 30 | DecoderParameter( 31 | json.obj("name").str, 32 | json.obj("tables").arr.map(v => TruthTable(v.str)).toSeq 33 | ) 34 | ) 35 | 36 | // cli 37 | given TokensReader.Simple[TruthTable]: 38 | def shortName = "truth-table" 39 | def read(strs: Seq[String]): Right[Nothing, TruthTable] = Right(TruthTable(strs.head)) 40 | 41 | class DecoderLayers(parameter: DecoderParameter) extends LayerInterface(parameter): 42 | def layers = Seq.empty 43 | 44 | class DecoderOutput(tables: Seq[TruthTable]) extends Record: 45 | tables.map(t => Aligned(t.name, Bits(t.outputBits.W))) 46 | 47 | class DecoderIO(parameter: DecoderParameter) extends HWRecord(parameter): 48 | Flipped("instruction", Bits(parameter.pla.inputWidth.W)) 49 | Aligned("output", new DecoderOutput(parameter.tables)) 50 | 51 | extension (decoderIO: Interface[DecoderIO]) 52 | def instruction( 53 | using Arena, 54 | Block, 55 | Context 56 | ) = decoderIO.field[Bits]("instruction") 57 | def output( 58 | using Arena, 59 | Block, 60 | Context 61 | ) = decoderIO.field[DecoderOutput]("output") 62 | 63 | class DecoderProbe(parameter: DecoderParameter) extends DVBundle[DecoderParameter, DecoderLayers](parameter) 64 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/om/given_TypeApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Yuhang Zeng 3 | package org.llvm.circt.scalalib.capi.dialect.om 4 | 5 | import org.llvm.circt.* 6 | import org.llvm.circt.CAPI.{ 7 | omAnyTypeGetTypeID, 8 | omClassTypeGetName, 9 | omClassTypeGetTypeID, 10 | omFrozenBasePathTypeGetTypeID, 11 | omFrozenPathTypeGetTypeID, 12 | omListTypeGetElementType, 13 | omListTypeGetTypeID, 14 | omTypeIsAAnyType, 15 | omTypeIsAClassType, 16 | omTypeIsAFrozenBasePathType, 17 | omTypeIsAFrozenPathType, 18 | omTypeIsAListType, 19 | omTypeIsAStringType 20 | } 21 | 22 | import org.llvm.mlir.scalalib.capi.support.{*, given} 23 | import org.llvm.mlir.scalalib.capi.ir.{Identifier, Type, given} 24 | 25 | import java.lang.foreign.Arena 26 | 27 | given TypeApi with 28 | inline def anyTypeGetTypeID( 29 | using arena: Arena 30 | ): TypeID = TypeID(omAnyTypeGetTypeID(arena)) 31 | extension (tpe: Type) 32 | inline def classTypeGetName( 33 | using arena: Arena 34 | ): Identifier = Identifier(omClassTypeGetName(arena, tpe.segment)) 35 | inline def classTypeGetTypeID( 36 | using arena: Arena 37 | ): TypeID = TypeID(omClassTypeGetTypeID(arena)) 38 | inline def frozenBasePathTypeGetTypeID( 39 | using arena: Arena 40 | ): TypeID = TypeID(omFrozenBasePathTypeGetTypeID(arena)) 41 | inline def frozenPathTypeGetTypeID( 42 | using arena: Arena 43 | ): TypeID = TypeID(omFrozenPathTypeGetTypeID(arena)) 44 | extension (tpe: Type) 45 | inline def listTypeGetElementType( 46 | using arena: Arena 47 | ): Type = Type(omListTypeGetElementType(arena, tpe.segment)) 48 | inline def listTypeGetTypeID( 49 | using arena: Arena 50 | ): TypeID = TypeID(omListTypeGetTypeID(arena)) 51 | extension (tpe: Type) 52 | inline def isAnyType: Boolean = omTypeIsAAnyType(tpe.segment) 53 | inline def isClassType: Boolean = omTypeIsAClassType(tpe.segment) 54 | inline def isFrozenBasePathType: Boolean = omTypeIsAFrozenBasePathType(tpe.segment) 55 | inline def isFrozenPathType: Boolean = omTypeIsAFrozenPathType(tpe.segment) 56 | inline def isListType: Boolean = omTypeIsAListType(tpe.segment) 57 | inline def isStringType: Boolean = omTypeIsAStringType(tpe.segment) 58 | end given 59 | -------------------------------------------------------------------------------- /rvdecoderdb/src/parser/RawInstruction.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2023 Jiuyang Liu 3 | 4 | package org.chipsalliance.rvdecoderdb.parser 5 | 6 | import org.chipsalliance.rvdecoderdb.Encoding 7 | 8 | class RawInstruction(tokens: Seq[Token]): 9 | def importInstruction: Option[(String, String)] = Option 10 | .when(tokens.head == Import && tokens.exists(t => t.isInstanceOf[RefInst]))(tokens.collectFirst { case r: RefInst => 11 | (r.set, r.inst) 12 | }.get) 13 | 14 | def importInstructionSet: Option[String] = Option 15 | .when(tokens.head == Import && importInstruction.isEmpty)(tokens.collectFirst { case str: BareStr => 16 | str.name 17 | }) 18 | .flatten 19 | 20 | def pseudoInstruction: Option[(String, String)] = Option 21 | .when(tokens.head == PseudoOp)(tokens.collectFirst { case r: RefInst => 22 | (r.set, r.inst) 23 | }.get) 24 | 25 | def isNormal: Boolean = 26 | importInstruction.isEmpty && 27 | importInstructionSet.isEmpty && 28 | pseudoInstruction.isEmpty 29 | 30 | def nameOpt: Option[String] = Option 31 | .when(importInstruction.isEmpty && importInstructionSet.isEmpty)(tokens.collectFirst { case str: BareStr => 32 | str.name 33 | }) 34 | .flatten 35 | 36 | def name: String = nameOpt.getOrElse(throw new Exception(s"error at token: ${tokens.mkString(",")}")) 37 | 38 | def args: Seq[ArgLUT] = tokens.flatMap { 39 | case a: ArgLUT => Some(a) 40 | case _ => None 41 | } 42 | 43 | def encoding: Encoding = tokens.flatMap { 44 | case b: BitValue => Some(Encoding(b.value << b.bit.toInt, BigInt(1) << b.bit.toInt)) 45 | case b: FixedRangeValue => 46 | Some(Encoding(b.value << b.lsb.toInt, (b.lsb.toInt to b.msb.toInt).map(BigInt(1) << _).sum)) 47 | case _ => None 48 | }.reduce((l, r) => Encoding(l.value + r.value, l.mask + r.mask)) 49 | 50 | override def toString: String = 51 | if importInstruction.nonEmpty then 52 | s"import instruction: ${importInstruction.get._2} from ${importInstruction.get._1}" 53 | else if importInstructionSet.nonEmpty then s"import set: ${importInstructionSet.get}" 54 | else if pseudoInstruction.nonEmpty then 55 | s"$name(pseudo ${pseudoInstruction.get._2} from ${pseudoInstruction.get._1})" 56 | else s"$name:$encoding" 57 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | { 4 | description = "Chisel Nix"; 5 | 6 | inputs = { 7 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small"; 8 | nixpkgs4circt.url = "github:NixOS/nixpkgs/nixos-unstable-small"; 9 | flake-utils.url = "github:numtide/flake-utils"; 10 | mill-ivy-fetcher.url = "github:Avimitin/mill-ivy-fetcher"; 11 | }; 12 | 13 | outputs = inputs@{ self, nixpkgs, nixpkgs4circt, flake-utils, mill-ivy-fetcher }: 14 | let overlay = (import ./nix/overlay.nix) { extraNixpkgsSrc = nixpkgs4circt; }; 15 | in { 16 | # System-independent attr 17 | inherit inputs; 18 | overlays.default = overlay; 19 | } // flake-utils.lib.eachDefaultSystem (system: 20 | let 21 | pkgs = import nixpkgs { 22 | overlays = [ overlay mill-ivy-fetcher.overlays.default ]; 23 | inherit system; 24 | }; 25 | in 26 | { 27 | formatter = pkgs.nixpkgs-fmt; 28 | legacyPackages = pkgs; 29 | packages = { 30 | default = pkgs.zaozi.zaozi-assembly; 31 | zaozi-assembly = pkgs.zaozi.zaozi-assembly; 32 | }; 33 | devShells.default = pkgs.mkShell { 34 | inputsFrom = [ pkgs.zaozi.zaozi-assembly ]; 35 | nativeBuildInputs = with pkgs; [ nixd ]; 36 | env = with pkgs; 37 | { 38 | CIRCT_INSTALL_PATH = circt-install; 39 | MLIR_INSTALL_PATH = mlir-install; 40 | JEXTRACT_INSTALL_PATH = jextract-21; 41 | LIT_INSTALL_PATH = lit; 42 | SCALA_CLI_INSTALL_PATH = scala-cli; 43 | RISCV_OPCODES_INSTALL_PATH = riscv-opcodes; 44 | # pass to jextract 45 | # Jextract splits the header class into multiple classes, which are combined via extending 46 | # Due to https://github.com/scala/bug/issues/9272 we cannot access static fields in superclass headers, we work around this by not splitting the header 47 | # https://github.com/openjdk/jextract/blob/8730fcf05c229d035b0db52ee6bd82622e9d03e9/src/main/java/org/openjdk/jextract/impl/ToplevelBuilder.java#L54 48 | JAVA_TOOL_OPTIONS = "--enable-preview -Djextract.decls.per.header=65535"; 49 | }; 50 | }; 51 | }); 52 | } 53 | -------------------------------------------------------------------------------- /mlirlib/src/capi/pass/given_OpPassManagerApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.pass 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirOpPassManagerAddOwnedPass, 8 | mlirOpPassManagerAddPipeline, 9 | mlirOpPassManagerGetNestedUnder, 10 | mlirParsePassPipeline, 11 | mlirPrintPassPipeline 12 | } 13 | import org.llvm.mlir.scalalib.capi.support.{*, given} 14 | 15 | import java.lang.foreign.{Arena, MemorySegment} 16 | 17 | given OpPassManagerApi with 18 | extension (opPassManager: OpPassManager) 19 | inline def getNestedUnder( 20 | passManager: PassManager, 21 | operationName: String 22 | )( 23 | using arena: Arena 24 | ): OpPassManager = 25 | OpPassManager(mlirOpPassManagerGetNestedUnder(arena, passManager.segment, operationName.toStringRef.segment)) 26 | inline def addPipeline( 27 | pipelineElements: String, 28 | callback: String => Unit 29 | )( 30 | using arena: Arena 31 | ): LogicalResult = 32 | LogicalResult( 33 | mlirOpPassManagerAddPipeline( 34 | arena, 35 | opPassManager.segment, 36 | pipelineElements.toStringRef.segment, 37 | callback.stringToStringCallback.segment, 38 | MemorySegment.NULL 39 | ) 40 | ) 41 | inline def parsePassPipeline( 42 | pipeline: String, 43 | callback: String => Unit 44 | )( 45 | using arena: Arena 46 | ): LogicalResult = LogicalResult( 47 | mlirParsePassPipeline( 48 | arena, 49 | opPassManager.segment, 50 | pipeline.toStringRef.segment, 51 | callback.stringToStringCallback.segment, 52 | MemorySegment.NULL 53 | ) 54 | ) 55 | inline def addOwnedPass( 56 | pass: Pass 57 | ): Unit = mlirOpPassManagerAddOwnedPass(opPassManager.segment, pass.segment) 58 | inline def printPassPipeline( 59 | callback: String => Unit 60 | )( 61 | using arena: Arena 62 | ): Unit = mlirPrintPassPipeline(opPassManager.segment, callback.stringToStringCallback.segment, MemorySegment.NULL) 63 | inline def segment: MemorySegment = opPassManager._segment 64 | inline def sizeOf: Int = MlirOpPassManager.sizeof().toInt 65 | end given 66 | -------------------------------------------------------------------------------- /nix/zaozi/zaozi.nix: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # SPDX-FileCopyrightText: 2024 Jiuyang Liu 3 | 4 | { lib 5 | , stdenv 6 | , makeWrapper 7 | , mill 8 | , circt-install 9 | , mlir-install 10 | , jextract-21 11 | , lit 12 | , scala-cli 13 | , add-determinism 14 | , z3 15 | , espresso 16 | , mill-ivy-fetcher 17 | , ivy-gather 18 | , writeShellApplication 19 | , mill-ivy-env-shell-hook 20 | 21 | }: 22 | 23 | let 24 | self = stdenv.mkDerivation rec { 25 | name = "zaozi"; 26 | 27 | src = with lib.fileset; 28 | toSource { 29 | root = ./../..; 30 | fileset = unions [ 31 | ./../../build.mill 32 | ./../../circtlib 33 | ./../../mlirlib 34 | ./../../decoder 35 | ./../../zaozi 36 | ./../../smtlib 37 | ./../../rvdecoderdb 38 | ./../../omlib 39 | ]; 40 | }; 41 | 42 | passthru.bump = writeShellApplication { 43 | name = "bump-zaozi-mill-lock"; 44 | runtimeInputs = [ 45 | mill 46 | mill-ivy-fetcher 47 | ]; 48 | text = '' 49 | mif run -p "${src}" -o ./nix/zaozi/zaozi-lock.nix "$@" 50 | ''; 51 | }; 52 | 53 | buildInputs = [ (ivy-gather ./zaozi-lock.nix) ]; 54 | 55 | nativeBuildInputs = [ 56 | mill 57 | mill.jre 58 | circt-install 59 | mlir-install 60 | jextract-21 61 | lit 62 | scala-cli 63 | add-determinism 64 | makeWrapper 65 | z3 66 | espresso 67 | ]; 68 | 69 | shellHook = '' 70 | ${mill-ivy-env-shell-hook} 71 | 72 | mill -i mill.bsp.BSP/install 73 | # other commands 74 | ''; 75 | 76 | env.CIRCT_INSTALL_PATH = circt-install; 77 | env.MLIR_INSTALL_PATH = mlir-install; 78 | env.JEXTRACT_INSTALL_PATH = jextract-21; 79 | env.LIT_INSTALL_PATH = lit; 80 | env.JAVA_TOOL_OPTIONS = "--enable-preview -Djextract.decls.per.header=65535"; 81 | 82 | outputs = [ "out" ]; 83 | 84 | # FIXME: wait https://github.com/com-lihaoyi/mill/pull/5521 85 | buildPhase = '' 86 | mill -i --offline '__.assembly' 87 | ''; 88 | 89 | installPhase = '' 90 | mkdir -p $out/share/java 91 | 92 | add-determinism -j $NIX_BUILD_CORES out/zaozi/assembly.dest/out.jar 93 | 94 | mv out/zaozi/assembly.dest/out.jar $out/share/java/elaborator.jar 95 | ''; 96 | }; 97 | in 98 | self 99 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_OperationStateApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirOperationStateAddAttributes, 8 | mlirOperationStateAddOperands, 9 | mlirOperationStateAddOwnedRegions, 10 | mlirOperationStateAddResults, 11 | mlirOperationStateAddSuccessors, 12 | mlirOperationStateEnableResultTypeInference, 13 | mlirOperationStateGet 14 | } 15 | import org.llvm.mlir.scalalib.capi.support.{*, given} 16 | 17 | import java.lang.foreign.{Arena, MemorySegment} 18 | 19 | given OperationStateApi with 20 | inline def operationStateGet( 21 | name: String, 22 | loc: Location 23 | )( 24 | using arena: Arena 25 | ): OperationState = 26 | OperationState(mlirOperationStateGet(arena, name.toStringRef.segment, loc.segment)) 27 | 28 | extension (operationState: OperationState) 29 | inline def addResults( 30 | results: Seq[Type] 31 | )( 32 | using arena: Arena 33 | ): Unit = 34 | mlirOperationStateAddResults(operationState.segment, results.size, results.toMlirArray) 35 | inline def addOperands( 36 | operands: Seq[Value] 37 | )( 38 | using arena: Arena 39 | ): Unit = 40 | mlirOperationStateAddOperands(operationState.segment, operands.size, operands.toMlirArray) 41 | inline def addOwnedRegions( 42 | regions: Seq[Region] 43 | )( 44 | using arena: Arena 45 | ): Unit = 46 | mlirOperationStateAddOwnedRegions(operationState.segment, regions.size, regions.toMlirArray) 47 | inline def addSuccessors( 48 | blocks: Seq[Block] 49 | )( 50 | using arena: Arena 51 | ): Unit = 52 | mlirOperationStateAddSuccessors(operationState.segment, blocks.size, blocks.toMlirArray) 53 | inline def addAttributes( 54 | attrs: Seq[NamedAttribute] 55 | )( 56 | using arena: Arena 57 | ): Unit = 58 | mlirOperationStateAddAttributes(operationState.segment, attrs.size, attrs.toMlirArray) 59 | inline def enableResultTypeInference(): Unit = 60 | mlirOperationStateEnableResultTypeInference(operationState.segment) 61 | inline def segment: MemorySegment = operationState._segment 62 | inline def sizeOf: Int = MlirOperationState.sizeof().toInt 63 | end given 64 | -------------------------------------------------------------------------------- /circtlib/src/capi/dialect/llhd/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | 4 | // circt-c/Dialect/LLHD.h 5 | package org.llvm.circt.scalalib.capi.dialect.llhd 6 | 7 | import org.llvm.mlir.scalalib.capi.ir.{Attribute, Context, Type, given} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | /** LLHD Dialect Api 12 | * 13 | * {{{ 14 | * mlirGetDialectHandle__llhd__ 15 | * }}} 16 | */ 17 | trait DialectApi: 18 | inline def loadDialect( 19 | using arena: Arena, 20 | context: Context 21 | ): Unit 22 | end DialectApi 23 | 24 | /** LLHD Attribute API 25 | * 26 | * {{{ 27 | * llhdAttrIsATimeAttr 28 | * llhdTimeAttrGet 29 | * llhdTimeAttrGetDelta 30 | * llhdTimeAttrGetEpsilon 31 | * llhdTimeAttrGetSeconds 32 | * llhdTimeAttrGetTimeUnit 33 | * }}} 34 | */ 35 | trait AttributeApi: 36 | extension (attribute: Attribute) def isTimeAttr(): Boolean 37 | def TimeAttrGet( 38 | timeUnit: String, 39 | seconds: BigInt, 40 | delta: BigInt, 41 | epsilon: BigInt 42 | )( 43 | using arena: Arena, 44 | context: Context 45 | ): Attribute 46 | extension (attribute: Attribute) 47 | def TimeAttrGetDelta(): BigInt 48 | def TimeAttrGetEpsilon(): BigInt 49 | def TimeAttrGetSeconds(): BigInt 50 | def TimeAttrGetTimeUnit( 51 | )( 52 | using arena: Arena 53 | ): String 54 | end AttributeApi 55 | 56 | /** LLHD Type API 57 | * 58 | * {{{ 59 | * llhdPointerTypeGet 60 | * llhdPointerTypeGetElementType 61 | * llhdSignalTypeGet 62 | * llhdSignalTypeGetElementType 63 | * llhdTypeIsAPointerType 64 | * llhdTypeIsASignalType 65 | * llhdTypeIsATimeType 66 | * }}} 67 | */ 68 | trait TypeApi: 69 | inline def pointerTypeGet( 70 | element: Type 71 | )( 72 | using arena: Arena 73 | ): Type 74 | extension (tpe: Type) 75 | inline def pointerTypeGetElementType( 76 | )( 77 | using arena: Arena 78 | ): Type 79 | inline def signalTypeGet( 80 | )( 81 | using arena: Arena 82 | ): Type 83 | inline def signalTypeGetElementType( 84 | )( 85 | using arena: Arena 86 | ): Type 87 | inline def isPointerType: Boolean 88 | inline def isSignalType: Boolean 89 | inline def isTimeType: Boolean 90 | end TypeApi 91 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_OpPrintingFlagsApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirOpPrintingFlagsAssumeVerified, 8 | mlirOpPrintingFlagsCreate, 9 | mlirOpPrintingFlagsDestroy, 10 | mlirOpPrintingFlagsElideLargeElementsAttrs, 11 | mlirOpPrintingFlagsElideLargeResourceString, 12 | mlirOpPrintingFlagsEnableDebugInfo, 13 | mlirOpPrintingFlagsPrintGenericOpForm, 14 | mlirOpPrintingFlagsSkipRegions, 15 | mlirOpPrintingFlagsUseLocalScope 16 | } 17 | 18 | import java.lang.foreign.{Arena, MemorySegment} 19 | 20 | given OpPrintingFlagsApi with 21 | inline def opPrintingFlagsCreate( 22 | )( 23 | using arena: Arena 24 | ): OpPrintingFlags = OpPrintingFlags(mlirOpPrintingFlagsCreate(arena)) 25 | 26 | extension (opPrintingFlags: OpPrintingFlags) 27 | inline def flagsDestroy(): Unit = mlirOpPrintingFlagsDestroy(opPrintingFlags.segment) 28 | inline def flagsElideLargeElementsAttrs(largeElementLimit: Long): Unit = 29 | mlirOpPrintingFlagsElideLargeElementsAttrs(opPrintingFlags.segment, largeElementLimit) 30 | inline def flagsElideLargeResourceString(largeResourceLimit: Long): Unit = 31 | mlirOpPrintingFlagsElideLargeResourceString(opPrintingFlags.segment, largeResourceLimit) 32 | inline def flagsEnableDebugInfo(enable: Boolean, prettyForm: Boolean): Unit = 33 | mlirOpPrintingFlagsEnableDebugInfo(opPrintingFlags.segment, enable, prettyForm) 34 | inline def flagsPrintGenericOpForm(): Unit = mlirOpPrintingFlagsPrintGenericOpForm(opPrintingFlags.segment) 35 | inline def flagsUseLocalScope(): Unit = mlirOpPrintingFlagsUseLocalScope(opPrintingFlags.segment) 36 | inline def flagsAssumeVerified(): Unit = mlirOpPrintingFlagsAssumeVerified(opPrintingFlags.segment) 37 | inline def flagsSkipRegions(): Unit = mlirOpPrintingFlagsSkipRegions(opPrintingFlags.segment) 38 | inline def segment: MemorySegment = opPrintingFlags._segment 39 | inline def sizeOf: Int = MlirOpPrintingFlags.sizeof().toInt 40 | end given 41 | -------------------------------------------------------------------------------- /mlirlib/src/capi/dialect/func/given_FuncApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.capi.dialect.func 4 | 5 | import org.llvm.mlir.scalalib.capi.ir.{ 6 | Block, 7 | Context, 8 | LocationApi, 9 | Module, 10 | NamedAttributeApi, 11 | Operation, 12 | OperationApi, 13 | given 14 | } 15 | 16 | import java.lang.foreign.Arena 17 | 18 | // Structure 19 | given FuncApi with 20 | inline def op( 21 | symName: String 22 | // funcType: Type, 23 | // symVisibility: String, 24 | // argAttrs: Seq[NamedAttribute], 25 | // resAttrs: Seq[NamedAttribute], 26 | // noInline: Boolean, 27 | )( 28 | using arena: Arena, 29 | context: Context 30 | ): Func = Func( 31 | summon[OperationApi].operationCreate( 32 | name = "func.func", 33 | location = summon[LocationApi].locationUnknownGet, 34 | regionBlockTypeLocations = Seq( 35 | Seq( 36 | (Seq.empty, Seq.empty) 37 | ) 38 | ), 39 | namedAttributes = 40 | val namedAttributeApi = summon[NamedAttributeApi] 41 | // val noInlineAttr = noInline match 42 | // case true => 43 | // Seq( 44 | // // ::mlir::UnitAttr 45 | // namedAttributeApi.namedAttributeGet("noInline".identifierGet, summon[AttributeApi].unitAttrGet) 46 | // ) 47 | // case false => Seq.empty 48 | Seq( 49 | // ::mlir::StringAttr 50 | namedAttributeApi.namedAttributeGet("symName".identifierGet, symName.stringAttrGet) 51 | // ::mlir::TypeAttr 52 | // namedAttributeApi.namedAttributeGet("funcType".identifierGet, ???), 53 | // ::mlir::StringAttr 54 | // namedAttributeApi.namedAttributeGet("symVisibility".identifierGet, ???), 55 | // ::mlir::ArrayAttr 56 | // namedAttributeApi.namedAttributeGet("argAttrs".identifierGet, ???), 57 | // ::mlir::ArrayAttr 58 | // namedAttributeApi.namedAttributeGet("resAttrs".identifierGet, ???), 59 | ) 60 | // ++ noInlineAttr 61 | ) 62 | ) 63 | extension (c: Func) 64 | inline def block( 65 | using Arena 66 | ): Block = c.operation.getFirstRegion.getFirstBlock 67 | inline def appendToModule( 68 | )( 69 | using arena: Arena, 70 | module: Module 71 | ): Unit = 72 | module.getBody.appendOwnedOperation(c.operation) 73 | extension (ref: Func) def operation: Operation = ref._operation 74 | end given 75 | -------------------------------------------------------------------------------- /circtlib/src/dialect/firrtl/StructureAPI.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.circt.scalalib.dialect.firrtl.operation 4 | 5 | import org.llvm.circt.scalalib.capi.dialect.firrtl.{FirrtlBundleField, FirrtlConvention, FirrtlLayerConvention} 6 | import org.llvm.mlir.scalalib.capi.support.{*, given} 7 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, Location, Module as MlirModule, Operation, Value} 8 | 9 | import java.lang.foreign.Arena 10 | 11 | class Circuit(val _operation: Operation) 12 | trait CircuitApi extends HasOperation[Circuit]: 13 | inline def op( 14 | circuitName: String 15 | )( 16 | using arena: Arena, 17 | context: Context 18 | ): Circuit 19 | 20 | extension (c: Circuit) 21 | inline def block( 22 | using Arena 23 | ): Block 24 | inline def appendToModule( 25 | )( 26 | using arena: Arena, 27 | module: MlirModule 28 | ): Unit 29 | end CircuitApi 30 | 31 | class Class(val _operation: Operation) 32 | class ExtClass(val _operation: Operation) 33 | class ExtModule(val _operation: Operation) 34 | trait ExtModuleApi extends HasOperation[ExtModule]: 35 | end ExtModuleApi 36 | 37 | class IntModule(val _operation: Operation) 38 | class MemModule(val _operation: Operation) 39 | class Module(val _operation: Operation) 40 | trait ModuleApi extends HasOperation[Module]: 41 | inline def op( 42 | name: String, 43 | location: Location, 44 | firrtlConvention: FirrtlConvention, 45 | interface: Seq[(FirrtlBundleField, Location)], 46 | layers: Seq[Seq[String]] 47 | )( 48 | using arena: Arena, 49 | context: Context 50 | ): Module 51 | 52 | extension (m: Module) 53 | inline def block( 54 | using Arena 55 | ): Block 56 | inline def appendToCircuit( 57 | )( 58 | using arena: Arena, 59 | circuit: Circuit 60 | ): Unit 61 | inline def getIO( 62 | idx: Long 63 | )( 64 | using Arena 65 | ): Value 66 | end ModuleApi 67 | 68 | class Formal(val _operation: Operation) 69 | class Layer(val _operation: Operation) 70 | trait LayerApi extends HasOperation[Layer]: 71 | inline def op( 72 | name: String, 73 | location: Location, 74 | layerConvention: FirrtlLayerConvention 75 | )( 76 | using arena: Arena, 77 | context: Context 78 | ): Layer 79 | end LayerApi 80 | class OptionCase(val _operation: Operation) 81 | class Option(val _operation: Operation) 82 | -------------------------------------------------------------------------------- /mlirlib/src/capi/support/CAPIImplementation.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.support 4 | 5 | import org.llvm.mlir.* 6 | 7 | import java.lang.foreign.{Arena, MemoryLayout, MemorySegment} 8 | 9 | given [T <: Int | Long | Float | Double]: ScalaTpeToMlirArray[T] with 10 | extension (xs: Seq[T]) 11 | inline def toMlirArray( 12 | using arena: Arena 13 | ) = 14 | if (xs.nonEmpty) 15 | val buffer = arena.allocate(xs.head match 16 | case int: Int => MemoryLayout.sequenceLayout(xs.size, CAPI.C_INT) 17 | case long: Long => MemoryLayout.sequenceLayout(xs.size, CAPI.C_LONG) 18 | case float: Float => MemoryLayout.sequenceLayout(xs.size, CAPI.C_FLOAT) 19 | case double: Double => MemoryLayout.sequenceLayout(xs.size, CAPI.C_DOUBLE)) 20 | xs.zipWithIndex.foreach: 21 | case (int: Int, i: Int) => buffer.setAtIndex(CAPI.C_INT, i, int) 22 | case (long: Long, i: Int) => buffer.setAtIndex(CAPI.C_LONG, i, long) 23 | case (float: Float, i: Int) => buffer.setAtIndex(CAPI.C_FLOAT, i, float) 24 | case (double: Double, i: Int) => buffer.setAtIndex(CAPI.C_DOUBLE, i, double) 25 | buffer 26 | else MemorySegment.NULL 27 | 28 | end given 29 | 30 | given [E]: ToMlirArray[E] with 31 | extension (xs: Seq[E]) 32 | inline def toMlirArray( 33 | using arena: Arena, 34 | api: HasSizeOf[E] & (HasSegment[E] | EnumHasToNative[E]) 35 | ): MemorySegment = 36 | if (xs.nonEmpty) 37 | val sizeOfT: Int = xs.head.sizeOf 38 | val buffer = arena.allocate(sizeOfT * xs.length) 39 | xs.zipWithIndex.foreach: (x, i) => 40 | scala.compiletime.summonFrom: 41 | case hasSeg: HasSegment[E] => 42 | buffer.asSlice(sizeOfT * i, sizeOfT).copyFrom(x.segment) 43 | case hasNative: EnumHasToNative[E] => 44 | buffer.setAtIndex(CAPI.C_INT, i, x.toNative) 45 | case int: Int => 46 | buffer.setAtIndex(CAPI.C_INT, i, int) 47 | case long: Long => 48 | buffer.setAtIndex(CAPI.C_LONG, i, long) 49 | case float: Float => 50 | buffer.setAtIndex(CAPI.C_FLOAT, i, float) 51 | case double: Double => 52 | buffer.setAtIndex(CAPI.C_DOUBLE, i, double) 53 | 54 | buffer 55 | else MemorySegment.NULL 56 | end given 57 | -------------------------------------------------------------------------------- /zaozi/stdlib/src/PLADecoder.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.stdlib 4 | 5 | import mainargs.TokensReader 6 | import me.jiuyang.zaozi.* 7 | import me.jiuyang.zaozi.reftpe.* 8 | import me.jiuyang.zaozi.valuetpe.* 9 | import me.jiuyang.zaozi.default.{*, given} 10 | import me.jiuyang.decoder.* 11 | 12 | import java.lang.foreign.Arena 13 | 14 | @generator 15 | object PLADecoder extends Generator[DecoderParameter, DecoderLayers, DecoderIO, DecoderProbe]: 16 | override def moduleName(parameter: DecoderParameter): String = 17 | "PLA" + "_" + parameter.name + "_" + parameter.hashCode.toHexString 18 | def architecture(parameter: DecoderParameter) = 19 | val io = summon[Interface[DecoderIO]] 20 | val (inputTerms, outputTerms) = parameter.pla.table.unzip 21 | val numberOfInputs = inputTerms.head.width 22 | val numberOfOutputs = outputTerms.head.width 23 | val inverterMask = parameter.pla.default.value & parameter.pla.default.mask 24 | val invInputs = ~io.instruction 25 | val andMatrixOutputs = inputTerms 26 | .map: t => 27 | val andMatrixInput = Seq 28 | .tabulate(numberOfInputs): i => 29 | if (t.mask.testBit(i)) 30 | Some( 31 | if (t.value.testBit(i)) io.field[Bits]("instruction")(i) 32 | else invInputs(i) 33 | ) 34 | else 35 | None 36 | .flatten 37 | if (andMatrixInput.nonEmpty) 38 | t.toString -> andMatrixInput.reduce(_ & _) 39 | else t.toString -> true.B 40 | .toMap 41 | val orMatrixOutputs = 42 | Seq 43 | .tabulate(numberOfOutputs): i => 44 | val andMatrixLines = parameter.pla.table 45 | .filter: (_, or) => 46 | or.mask.testBit(i) && or.value.testBit(i) 47 | .map: (inputTerm, _) => 48 | andMatrixOutputs(inputTerm.toString) 49 | if (andMatrixLines.isEmpty) false.B 50 | else andMatrixLines.reduce(_ | _) 51 | .reverse 52 | .map(_.asBits) 53 | .reduce(_ ## _) 54 | val invMatrixOutputs = 55 | Seq 56 | .tabulate(numberOfOutputs): i => 57 | if (inverterMask.testBit(i)) !orMatrixOutputs(i) 58 | else orMatrixOutputs(i) 59 | .reverse 60 | .map(_.asBits) 61 | .reduce(_ ## _) 62 | io.output := invMatrixOutputs.asRecord(new DecoderOutput(parameter.tables)) 63 | -------------------------------------------------------------------------------- /mlirlib/src/capi/ir/given_ContextApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.ir 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.{ 7 | mlirContextAppendDialectRegistry, 8 | mlirContextCreate, 9 | mlirContextCreateWithRegistry, 10 | mlirContextCreateWithThreading, 11 | mlirContextDestroy, 12 | mlirContextEnableMultithreading, 13 | mlirContextGetOrLoadDialect, 14 | mlirContextLoadAllAvailableDialects, 15 | mlirContextSetAllowUnregisteredDialects, 16 | mlirContextSetThreadPool 17 | } 18 | import org.llvm.mlir.scalalib.capi.support.{*, given} 19 | 20 | import java.lang.foreign.{Arena, MemorySegment} 21 | 22 | given ContextApi with 23 | inline def contextCreate( 24 | using arena: Arena 25 | ): Context = 26 | Context(mlirContextCreate(arena)) 27 | 28 | inline def contextCreateWithThreading( 29 | threadingEnabled: Boolean 30 | )( 31 | using arena: Arena 32 | ): Context = 33 | Context(mlirContextCreateWithThreading(arena, threadingEnabled)) 34 | 35 | inline def contextCreateWithRegistry( 36 | registry: DialectRegistry, 37 | threadingEnabled: Boolean 38 | )( 39 | using arena: Arena 40 | ): Context = 41 | Context(mlirContextCreateWithRegistry(arena, registry.segment, threadingEnabled)) 42 | 43 | extension (context: Context) 44 | inline def getOrLoadDialect( 45 | name: String 46 | )( 47 | using arena: Arena 48 | ): Dialect = Dialect(mlirContextGetOrLoadDialect(arena, context.segment, name.toStringRef.segment)) 49 | inline def destroy(): Unit = mlirContextDestroy(context.segment) 50 | inline def allowUnregisteredDialects(allow: Boolean): Unit = 51 | mlirContextSetAllowUnregisteredDialects(context.segment, allow) 52 | inline def appendDialectRegistry(registry: DialectRegistry): Unit = 53 | mlirContextAppendDialectRegistry(context.segment, registry.segment) 54 | inline def enableMultithreading(enable: Boolean): Unit = 55 | mlirContextEnableMultithreading(context.segment, enable) 56 | inline def loadAllAvailableDialects(): Unit = 57 | mlirContextLoadAllAvailableDialects(context.segment) 58 | inline def setThreadPool(threadPool: LlvmThreadPool): Unit = 59 | mlirContextSetThreadPool(context.segment, threadPool.segment) 60 | 61 | inline def segment: MemorySegment = context._segment 62 | inline def sizeOf: Int = MlirContext.sizeof().toInt 63 | 64 | end given 65 | -------------------------------------------------------------------------------- /mlirlib/src/capi/support/given_StringRefApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package org.llvm.mlir.scalalib.capi.support 4 | 5 | import org.llvm.mlir.* 6 | import org.llvm.mlir.CAPI.mlirStringRefCreateFromCString 7 | 8 | import java.lang.foreign.{Arena, MemorySegment} 9 | 10 | given StringRefApi with 11 | extension (stringRef: StringRef) 12 | inline def segment: MemorySegment = stringRef._segment 13 | inline def sizeOf: Int = MlirStringRef.sizeof().toInt 14 | inline def toBytes: Array[Byte] = 15 | MlirStringRef 16 | .data$get(stringRef.segment) 17 | .asSlice(0, MlirStringRef.length$get(stringRef.segment)) 18 | .toArray(java.lang.foreign.ValueLayout.JAVA_BYTE) 19 | inline def toScalaString: String = String(toBytes) 20 | extension (string: String) 21 | inline def toStringRef( 22 | using arena: Arena 23 | ): StringRef = 24 | val bytes = string.getBytes() 25 | val buffer = arena.allocate(bytes.length + 1) 26 | buffer.copyFrom(MemorySegment.ofArray(bytes)) 27 | StringRef(mlirStringRefCreateFromCString(arena, buffer)) 28 | 29 | extension (bytes: Array[Byte]) 30 | inline def toStringRef( 31 | using arena: Arena 32 | ): StringRef = 33 | val buffer = arena.allocate(bytes.length) 34 | buffer.copyFrom(MemorySegment.ofArray(bytes)) 35 | StringRef(mlirStringRefCreateFromCString(arena, buffer)) 36 | val stringRef = MlirStringRef.allocate(arena) 37 | MlirStringRef.data$set(stringRef, buffer) 38 | MlirStringRef.length$set(stringRef, bytes.length) 39 | StringRef(stringRef) 40 | end given 41 | 42 | given StringCallbackApi with 43 | extension (stringCallBack: String => Unit) 44 | inline def stringToStringCallback( 45 | using arena: Arena 46 | ): StringCallback = 47 | StringCallback( 48 | MlirStringCallback.allocate( 49 | (message: MemorySegment, userData: MemorySegment) => stringCallBack(StringRef(message).toScalaString), 50 | arena 51 | ) 52 | ) 53 | extension (bytesCallBack: Array[Byte] => Unit) 54 | inline def bytesToStringCallback( 55 | using arena: Arena 56 | ): StringCallback = 57 | StringCallback( 58 | MlirStringCallback.allocate( 59 | (message: MemorySegment, userData: MemorySegment) => bytesCallBack(StringRef(message).toBytes), 60 | arena 61 | ) 62 | ) 63 | extension (stringCallBack: StringCallback) inline def segment: MemorySegment = stringCallBack._segment 64 | end given 65 | -------------------------------------------------------------------------------- /mlirlib/src/capi/dialect/smt/CAPIDefinition.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jianhao Ye 3 | package org.llvm.mlir.scalalib.capi.dialect.smt 4 | 5 | import org.llvm.mlir.scalalib.capi.ir.{Attribute, Context, Type, given} 6 | 7 | import java.lang.foreign.Arena 8 | 9 | trait DialectApi: 10 | inline def loadDialect( 11 | )( 12 | using arena: Arena, 13 | context: Context 14 | ): Unit 15 | end DialectApi 16 | 17 | trait TypeApi: 18 | inline def getArray( 19 | domainType: Type, 20 | rangeType: Type 21 | )( 22 | using arena: Arena, 23 | context: Context 24 | ): Type 25 | inline def getBitVector( 26 | width: Int 27 | )( 28 | using arena: Arena, 29 | context: Context 30 | ): Type 31 | inline def getBool( 32 | using arena: Arena, 33 | context: Context 34 | ): Type 35 | inline def getInt( 36 | using arena: Arena, 37 | context: Context 38 | ): Type 39 | inline def getSMTFunc( 40 | domainTypes: Seq[Type], 41 | rangeType: Type 42 | )( 43 | using arena: Arena, 44 | context: Context 45 | ): Type 46 | inline def getSort( 47 | identifier: String, 48 | sortParams: Seq[Type] 49 | )( 50 | using arena: Arena, 51 | context: Context 52 | ): Type 53 | extension (tpe: Type) 54 | inline def isAnyNonFuncSMTValueType: Boolean 55 | inline def isAnySMTValueType: Boolean 56 | inline def isArray: Boolean 57 | inline def isBitVector: Boolean 58 | inline def isBool: Boolean 59 | inline def isInt: Boolean 60 | inline def isSMTFunc: Boolean 61 | inline def isSort: Boolean 62 | end TypeApi 63 | 64 | trait AttributeApi: 65 | extension (str: String) 66 | inline def getBVCmpPredicateAttribute( 67 | using arena: Arena, 68 | context: Context 69 | ): Attribute 70 | inline def getIntPredicateAttribute( 71 | using arena: Arena, 72 | context: Context 73 | ): Attribute 74 | extension (value: Int) 75 | inline def getBitVectorAttribute( 76 | width: Int 77 | )( 78 | using arena: Arena, 79 | context: Context 80 | ): Attribute 81 | extension (attr: Attribute) inline def isSMTAttribute: Boolean 82 | extension (str: String) 83 | inline def checkBVCmpPredicateAttribute( 84 | using arena: Arena, 85 | context: Context 86 | ): Boolean 87 | inline def checkIntPredicateAttribute( 88 | using arena: Arena, 89 | context: Context 90 | ): Boolean 91 | end AttributeApi 92 | -------------------------------------------------------------------------------- /mlirlib/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package build.mlirlib 4 | 5 | import mill._ 6 | import mill.scalalib._ 7 | import mill.scalalib.TestModule.Utest 8 | import mill.scalalib.scalafmt._ 9 | 10 | import build.{v, PanamaModule, ZaoziPublishModule} 11 | 12 | object `package` extends ScalaModule with ScalafmtModule with PanamaModule with ZaoziPublishModule { 13 | def scalaVersion = Task(v.scala) 14 | 15 | override def dumpIncludes() = Task.Command { 16 | super.dumpIncludes()() 17 | includeFiles().foreach { file => 18 | val lines = 19 | os.read 20 | .lines(file.path) 21 | .filter(str => str.contains(mlirInstallPath().toString)) 22 | // to eliminte error cause by a jextract bug 23 | .filter(str => !str.contains("mlirTypeIDAllocatorAllocateTypeID")) 24 | .map(_.replaceAll(mlirInstallPath().toString, "\\$MLIR_INSTALL_PATH").trim) 25 | os.write.over(file.path, (license ++ lines).mkString("\n")) 26 | } 27 | } 28 | 29 | def includeConstantsFile = Task.Source(moduleDir / "capi" / "includeConstants.txt") 30 | 31 | def includeFunctionsFile = Task.Source(moduleDir / "capi" / "includeFunctions.txt") 32 | 33 | def includeStructsFile = Task.Source(moduleDir / "capi" / "includeStructs.txt") 34 | 35 | def includeTypedefsFile = Task.Source(moduleDir / "capi" / "includeTypedefs.txt") 36 | 37 | def includeUnionsFile = Task.Source(moduleDir / "capi" / "includeUnions.txt") 38 | 39 | def includeVarsFile = Task.Source(moduleDir / "capi" / "includeVars.txt") 40 | 41 | def linkLibrariesFile = Task.Source(moduleDir / "capi" / "linkLibraries.txt") 42 | 43 | def target = Task("org.llvm.mlir") 44 | 45 | def headerClassName = Task("CAPI") 46 | 47 | def header = Task.Source(moduleDir / "capi" / "jextract-headers.h") 48 | 49 | def mlirInstallPath = Task.Input( 50 | os.Path(Task.env.getOrElse("MLIR_INSTALL_PATH", "MLIR_INSTALL_PATH not found, you are not in the nix env?")) 51 | ) 52 | 53 | def jextractBinary = Task( 54 | os.Path( 55 | Task.env.getOrElse("JEXTRACT_INSTALL_PATH", "JEXTRACT_INSTALL_PATH not found, you are not in the nix env?") 56 | ) / "bin" / "jextract" 57 | ) 58 | 59 | def includePaths = Task(Seq(PathRef(mlirInstallPath() / "include"))) 60 | 61 | def libraryPaths = Task(Seq(PathRef(mlirInstallPath() / "lib"))) 62 | 63 | object tests extends ScalaTests with ScalafmtModule with Utest { 64 | def mvnDeps = Seq(v.utest) 65 | 66 | override def forkArgs: T[Seq[String]] = Task( 67 | super.forkArgs() ++ Seq("--enable-native-access=ALL-UNNAMED", "--enable-preview") 68 | ++ libraryPaths().map(p => s"-Djava.library.path=${p.path}") 69 | ) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /circtlib/package.mill: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package build.circtlib 4 | 5 | import mill._ 6 | import mill.scalalib._ 7 | import mill.scalalib.TestModule.Utest 8 | import mill.scalalib.scalafmt._ 9 | 10 | import build.{mlirlib, v, PanamaModule, ZaoziPublishModule} 11 | 12 | object `package` extends ScalaModule with ScalafmtModule with PanamaModule with ZaoziPublishModule { 13 | outer => 14 | def scalaVersion = Task(v.scala) 15 | def moduleDeps = Seq(mlirlib) 16 | def mvnDeps = Seq(v.pprint) 17 | 18 | override def dumpIncludes() = Task.Command { 19 | super.dumpIncludes()() 20 | includeFiles().foreach { file => 21 | val lines = 22 | os.read 23 | .lines(file.path) 24 | .filter(str => str.contains(circtInstallPath().toString)) 25 | .map(_.replaceAll(circtInstallPath().toString, "\\$CIRCT_INSTALL_PATH").trim) 26 | os.write.over(file.path, (license ++ lines).mkString("\n")) 27 | } 28 | } 29 | 30 | def includeConstantsFile = Task.Source(moduleDir / "capi" / "includeConstants.txt") 31 | 32 | def includeFunctionsFile = Task.Source(moduleDir / "capi" / "includeFunctions.txt") 33 | 34 | def includeStructsFile = Task.Source(moduleDir / "capi" / "includeStructs.txt") 35 | 36 | def includeTypedefsFile = Task.Source(moduleDir / "capi" / "includeTypedefs.txt") 37 | 38 | def includeUnionsFile = Task.Source(moduleDir / "capi" / "includeUnions.txt") 39 | 40 | def includeVarsFile = Task.Source(moduleDir / "capi" / "includeVars.txt") 41 | 42 | def linkLibrariesFile = Task.Source(moduleDir / "capi" / "linkLibraries.txt") 43 | 44 | def target = Task("org.llvm.circt") 45 | 46 | def headerClassName = Task("CAPI") 47 | 48 | def header = Task.Source(moduleDir / "capi" / "jextract-headers.h") 49 | 50 | def circtInstallPath = Task( 51 | os.Path(Task.env.getOrElse("CIRCT_INSTALL_PATH", "CIRCT_INSTALL_PATH not found, you are not in the nix env?")) 52 | ) 53 | 54 | def jextractBinary = Task( 55 | os.Path( 56 | Task.env.getOrElse("JEXTRACT_INSTALL_PATH", "JEXTRACT_INSTALL_PATH not found, you are not in the nix env?") 57 | ) / "bin" / "jextract" 58 | ) 59 | 60 | def includePaths = Task(Seq(mlirlib.mlirInstallPath() / "include", circtInstallPath() / "include").map(PathRef(_))) 61 | 62 | def libraryPaths = Task(Seq(mlirlib.mlirInstallPath() / "lib", circtInstallPath() / "lib").map(PathRef(_))) 63 | 64 | object tests extends ScalaModule with ScalafmtModule with Utest { 65 | override def forkArgs: T[Seq[String]] = outer.forkArgs 66 | 67 | override def moduleDeps = Seq(outer, mlirlib) 68 | 69 | def mvnDeps = Seq(v.utest, v.oslib, v.upickle) 70 | 71 | override def scalaVersion = outer.scalaVersion 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /zaozi/src/default/VecApi.scala: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // SPDX-FileCopyrightText: 2025 Jiuyang Liu 3 | package me.jiuyang.zaozi.default 4 | 5 | import me.jiuyang.zaozi.VecApi 6 | import me.jiuyang.zaozi.InstanceContext 7 | import me.jiuyang.zaozi.reftpe.* 8 | import me.jiuyang.zaozi.valuetpe.* 9 | 10 | import org.llvm.circt.scalalib.capi.dialect.firrtl.{given_FirrtlBundleFieldApi, given_TypeApi, FirrtlNameKind} 11 | import org.llvm.circt.scalalib.dialect.firrtl.operation.{NodeApi, SubaccessApi, SubindexApi, given} 12 | import org.llvm.mlir.scalalib.capi.ir.{Block, Context, LocationApi, Operation, given} 13 | 14 | import java.lang.foreign.Arena 15 | 16 | given [E <: Data, V <: Vec[E], R <: Referable[V]]: VecApi[E, V, R] with 17 | extension (ref: R) 18 | def asBits( 19 | using Arena, 20 | Context, 21 | Block, 22 | sourcecode.File, 23 | sourcecode.Line, 24 | sourcecode.Name.Machine, 25 | InstanceContext 26 | ): Node[Bits] = 27 | val nodeOp = summon[NodeApi].op( 28 | name = valName, 29 | location = locate, 30 | nameKind = FirrtlNameKind.Interesting, 31 | input = ref.refer 32 | ) 33 | nodeOp.operation.appendToBlock() 34 | new Node[Bits]: 35 | val _tpe: Bits = new Bits: 36 | private[zaozi] val _width = nodeOp.operation.getResult(0).getType.getBitWidth(true).toInt 37 | val _operation: Operation = nodeOp.operation 38 | def bit( 39 | idx: Referable[UInt] | Int 40 | )( 41 | using Arena, 42 | Context, 43 | Block, 44 | sourcecode.File, 45 | sourcecode.Line, 46 | sourcecode.Name.Machine, 47 | InstanceContext 48 | ): Node[E] = 49 | val nodeOp = summon[NodeApi].op( 50 | name = valName, 51 | location = locate, 52 | nameKind = FirrtlNameKind.Interesting, 53 | input = idx match 54 | case that: Referable[UInt] => 55 | val op0 = summon[SubaccessApi].op(ref.refer, that.refer, locate) 56 | op0.operation.appendToBlock() 57 | op0.result 58 | case that: Int => 59 | val op0 = summon[SubindexApi].op(ref.refer, that, locate) 60 | op0.operation.appendToBlock() 61 | op0.result 62 | ) 63 | nodeOp.operation.appendToBlock() 64 | new Node[E]: 65 | val _tpe: E = ref._tpe._elementType 66 | val _operation: Operation = nodeOp.operation 67 | 68 | // sugars 69 | def apply( 70 | idx: Referable[UInt] | Int 71 | )( 72 | using Arena, 73 | Context, 74 | Block, 75 | sourcecode.File, 76 | sourcecode.Line, 77 | sourcecode.Name.Machine, 78 | InstanceContext 79 | ): Node[E] = bit(idx) 80 | 81 | end given 82 | -------------------------------------------------------------------------------- /.github/workflows/bump.yml: -------------------------------------------------------------------------------- 1 | name: CIRCT Bump 2 | on: 3 | schedule: 4 | # Run this job everyday at 5:30 AM UTC+8 5 | - cron: '30 21 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | bump-deps: 10 | name: "Bump CIRCT" 11 | if: ${{ !cancelled() }} 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: DeterminateSystems/nix-installer-action@main 18 | - name: Bump circt 19 | run: | 20 | oldFirtool="$(nix build '.#circt' --no-link --print-out-paths)/bin/firtool" 21 | nix flake update nixpkgs4circt 22 | newFirtool="$(nix build '.#circt' --no-link --print-out-paths)/bin/firtool" 23 | diff_bin="$(nix build '.#diffutils' --no-link --print-out-paths)/bin/diff" 24 | if "$diff_bin" -u <($oldFirtool --version) <($newFirtool --version); then 25 | # if circt version is not changed, abort this bump process 26 | git restore flake.lock 27 | fi 28 | - name: Bump all mill deps 29 | run: | 30 | oldHash=$(nix derivation show '.#zaozi.zaozi-assembly.millDeps' | jq -r 'to_entries[0].value.env.outputHash') 31 | nix build '.#zaozi.zaozi-assembly.millDeps' --rebuild -L > milldeps-log.txt 2>&1 || true 32 | newHash=$(cat milldeps-log.txt \ 33 | | grep -P '^\s+got:\s+sha256-.*$' \ 34 | | cut -d':' -f2 \ 35 | | xargs) 36 | if [ -z "$newHash" ] || [ "$newHash" = "$oldHash" ]; then 37 | echo "Original build logs for debug: " 38 | cat milldeps-log.txt 39 | echo "Hash unchanged, exit" 40 | exit 0 41 | fi 42 | echo "Updating hash $oldHash to $newHash" 43 | sed -i "s|$oldHash|$newHash|" nix/zaozi/zaozi.nix 44 | - name: Regenerate CAPI includes 45 | run: nix develop -c mill -i '__.dumpIncludes' 46 | - name: Commit changes 47 | env: 48 | GITHUB_TOKEN: ${{ secrets.PR_PAT }} 49 | run: | 50 | git config user.name Avimitin 51 | git config user.email dev@avimit.in 52 | 53 | currentDate=$(date +%F) 54 | branch="dependencies-bumping-$currentDate" 55 | git checkout -b "$branch" 56 | 57 | git add 'nix/zaozi' 58 | git add 'flake.lock' 59 | git add 'circtlib/capi' 60 | git add 'mlirlib/capi' 61 | 62 | if ! git diff --quiet --cached --exit-code; then 63 | updatedFiles=$(git diff --cached --name-only) 64 | echo "File changed" 65 | git commit -m "[deps] Bump zaozi dependencies" 66 | git push origin "$branch" --force-with-lease 67 | nix run '.#gh' -- \ 68 | pr create --title "Bump zaozi dependencies" --body "Updated: $updatedFiles" 69 | fi 70 | --------------------------------------------------------------------------------