Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9838bb9
refactor: Rename VarDymTyped to VarDynamic and update related usages
doofin Nov 20, 2025
573bd04
feat: Add BoolProp for formal verification in sequentialCommands and …
doofin Nov 20, 2025
39fe02c
feat: Implement AST transformation methods in chiselModules and add t…
doofin Nov 20, 2025
0a0a948
chore: Update CI workflow to rename job and improve Java setup steps
doofin Nov 20, 2025
ec99a32
feat: Enhance AST transformation by adding BoolProp handling and refa…
doofin Nov 20, 2025
cd015bb
feat: Add global settings and custom pprint method; update tests to u…
doofin Nov 20, 2025
a615610
feat: Refactor imports to replace varDecls with circuitDecls and remo…
doofin Nov 20, 2025
a0e1575
feat: Refactor imports to use monadicSyntax and enhance code organiza…
doofin Dec 13, 2025
4d922ec
feat: Enhance MonotoneFramework and related components with transfer …
doofin Jan 15, 2026
533bdf1
feat: Refactor domainMapT type definition and update checkUnInitAnaly…
doofin Jan 15, 2026
430f6ea
feat: Rename initMap to botMap in MonoFramework and update related re…
doofin Jan 19, 2026
c1fea95
feat: Refactor checkUnInitAnalysis and remove checkUnInitLattice, int…
doofin Jan 19, 2026
92442fa
feat: Implement unInitAnalysis and associated test suite for variable…
doofin Jan 20, 2026
20ac238
feat: Refactor domainMapT to VarMap for consistency across MonotoneFr…
doofin Jan 31, 2026
47315ef
feat: Refactor MonoFrameworkT to use baseLattice directly and update …
doofin Jan 31, 2026
9dd87a2
refactor: Remove unused type alias and streamline unInitAnalysis imports
doofin Jan 31, 2026
724613f
feat: Update Scala version and enhance static analysis with live vari…
doofin Jan 31, 2026
b4bc666
feat: Enhance worklist algorithm and live variable analysis with entr…
doofin Jan 31, 2026
6eac0c1
feat: Introduce reaching definition analysis and related test suite
doofin Feb 2, 2026
0e915c3
refactor: Simplify worklist algorithm and update monoFramework signat…
doofin Feb 2, 2026
17df062
liveVarAnalysisSuite ok, Update MonoFrameworkT
doofin Feb 2, 2026
3d7652a
feat: Add live variable and reaching definition analysis test suites
doofin Feb 3, 2026
b282cb9
fix: Update assertions in unInitAnalysisSuite for expected initializa…
doofin Feb 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ env:

jobs:
run:
name: Compile
name: unit test
strategy:
matrix:
java-version: [17]
Expand All @@ -19,16 +19,14 @@ jobs:
with:
fetch-depth: 0

- name: Setup Java
- name: Setup Java and SBT
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{ matrix.java-version }}
cache: sbt

# cache sbt dependencies
- uses: coursier/cache-action@v6

- uses: sbt/setup-sbt@v1

- name: unit test
Expand Down
2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version = "3.10.1"
runner.dialect = scala3
maxColumn = 100 # For my wide 30" display.
runner.dialectOverride.allowSignificantIndentation = false
# runner.dialectOverride.allowSignificantIndentation = false
runner.dialectOverride.allowQuietSyntax = true
9 changes: 6 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ resolvers ++= Seq(
"jitpack" at "https://jitpack.io",
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
)
val mScala3Version = "3.3.3" // "3.3.1-RC1-bin-SNAPSHOT" 3.3.0-RC3
val mScala3Version = "3.3.7" // "3.3.1-RC1-bin-SNAPSHOT" 3.3.0-RC3

/* To print the code as it is transformed through the compiler, use the compiler flag -Xprint:all
trace the code that generated the error by adding the -Ydebug-error compiler flag,
Expand All @@ -19,13 +19,16 @@ lazy val root = project
scalaVersion := mScala3Version,
scalacOptions ++= mScalacOptions,
libraryDependencies ++= Seq(
// typelevel
"org.typelevel" %% "cats-core" % catsV,
"org.typelevel" %% "cats-free" % catsV,
"dev.optics" %% "monocle-core" % "3.3.0",
// debugging and printing
"com.lihaoyi" %% "pprint" % "0.8.1", // print,debug
"org.scalameta" %% "munit" % "0.7.29" % Test,
// https://mvnrepository.com/artifact/org.scalatest/scalatest
"org.scalatest" %% "scalatest" % "3.2.14" % Test,
"io.bullet" %% "macrolizer" % "0.6.2" % "compile-internal", // print,debug
"org.typelevel" %% "cats-core" % catsV,
"org.typelevel" %% "cats-free" % catsV,
"com.github.doofin.stdScala" %% "stdscala" % "b10536c37c", // new : 184b5cbc7d %%% for cr
"io.github.iltotore" %% "iron" % "2.1.0",
("edu.berkeley.cs" %% "chisel3" % "3.5.5")
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/dependentChisel/algo/stackList2tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import dependentChisel.codegen.sequentialCommands.*
/** algorithm to convert sequential commands to AST in tree structure
*/
object stackList2tree {
type AST = TreeNode[NewInstance | WeakStmt | Ctrl | VarDecls]
// node can be control structure like if, or simple commands like assign
type AST = TreeNode[Ctrl | Cmds]

/** convert sequential commands to AST.
*
Expand All @@ -37,7 +38,7 @@ object stackList2tree {
// end of block, pop out one parent
parents.pop()
// for other stmt,just append
case stmt: (WeakStmt | NewInstance | VarDecls) =>
case stmt: (WeakStmt | NewInstance | VarDecls | BoolProp) =>
val newNd: AST = TreeNode(stmt)
parents.top.children += newNd
case _ =>
Expand Down
41 changes: 35 additions & 6 deletions src/main/scala/dependentChisel/algo/treeTraverse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ object treeTraverse {
node.children.foreach(preOrder(visit, _))
}

/** filter tree nodes based on predicate
/** filter tree nodes based on predicate. There are multiple ways to interpret this:
*
* 1 We remove only the leaves that do not satisfy the predicate, and for branch nodes, we keep
* them if either they satisfy the predicate or if they have any descendant that satisfies the
* predicate (so we keep the structure to reach the satisfying leaves).
*
* 2 We remove every node that does not satisfy the predicate, and if a branch node is removed,
* then we must somehow promote its children? But then the tree structure might change.
*
* 3 We do a transformation such that we keep the tree structure, but we remove any leaf that
* doesn't satisfy the predicate, and for branch nodes, we keep them only if they satisfy the
* predicate OR if they have at least one child that is kept. This is similar to a prune.
*
* 4 the assert is only top level and about inputs/outputs for assume-guarantee style
*
* TODO: test this function
* @param predicate
Expand All @@ -26,21 +39,37 @@ object treeTraverse {
*/
def filter[t](
predicate: t => Boolean,
node: Tree.TreeNode[t]
tree: Tree.TreeNode[t]
): Tree.TreeNode[t] = {
val flag @ (yes, hasChild) = (predicate(node.value), node.children.nonEmpty)
val flag @ (yes, hasChild) = (predicate(tree.value), tree.children.nonEmpty)

// if children is empty, it's leaf node, just return itself if satisfies predicate
if hasChild then {
// recursively filter its children
val filteredChildren = node.children
val filteredChildren = tree.children
.map(child => filter(predicate, child))
.filter(child => predicate(child.value) || child.children.nonEmpty)
Tree.TreeNode(node.value, filteredChildren)
Tree.TreeNode(tree.value, filteredChildren)
} else {
// leaf node, just return itself if satisfies predicate
if yes then node else Tree.TreeNode(node.value, ArrayBuffer())
if yes then tree else Tree.TreeNode(tree.value, ArrayBuffer())
}

}

/** only filter the top level children of the tree.Useful for assume-guarantee style formal
* verification
*
* @param predicate
* @param tree
* @return
*/
def filterTop[t](
predicate: t => Boolean,
tree: Tree.TreeNode[t]
): Tree.TreeNode[t] = {
val filteredChildren = tree.children
.filter(child => predicate(child.value))
tree.copy(children = filteredChildren)
}
}
2 changes: 1 addition & 1 deletion src/main/scala/dependentChisel/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dependentChisel

object api {
export dependentChisel.typesAndSyntax.chiselModules.*
export dependentChisel.typesAndSyntax.varDecls.*
export dependentChisel.typesAndSyntax.circuitDecls.*
export dependentChisel.typesAndSyntax.typesAndOps.*
export dependentChisel.typesAndSyntax.statements.*
export dependentChisel.codegen.compiler.*
Expand Down
16 changes: 8 additions & 8 deletions src/main/scala/dependentChisel/codegen/compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ object compiler {
})
case stmt: WeakStmt => indent + stmt2firrtlStr(stmt)
case stmt: NewInstance => newInstStmt2firrtlStr(indent, stmt) + "\n"
case stmt: VarDecls =>
case stmt: VarDecls =>
indent + varDecl2firrtlStr(indent, stmt)
}

Expand Down Expand Up @@ -201,7 +201,7 @@ object compiler {
s"$opName(${expr2firrtlStr(a)})"
case x: Var[?] =>
// dbg(x)
x.getname
x.getName
case Lit(w) =>
// h0 means HexLit of 0
s"""UInt<${w}>("$w")"""
Expand Down Expand Up @@ -258,7 +258,7 @@ object compiler {
}

def varDecl2firrtlStr(indent: String = "", stmt: VarDecls) = {
val VarDymTyped(width: Int, tp: VarType, name: String) = stmt.v
val VarDynamic(width: Int, tp: VarType, name: String) = stmt.v
tp match {
case VarType.Reg => // reg without init
/* reg mReg : UInt<16>, clock with :
Expand Down Expand Up @@ -315,7 +315,7 @@ object compiler {
WeakStmt(
stmt.lhs,
":=",
bop.copy(a = VarLit(genStmt.lhs.getname)),
bop.copy(a = VarLit(genStmt.lhs.getName)),
prefix = "node "
)
) ++ resList
Expand Down Expand Up @@ -355,7 +355,7 @@ object compiler {
io.y:=a+b becomes y0=a+b;io.y<=y0
new : don't do above
*/
case x: (VarTyped[?] | VarDymTyped) =>
case x: (VarTyped[?] | VarDynamic) =>
val genStmt = expr2stmtBind(stmt.rhs)
List(genStmt, stmt.copy(op = "<=", rhs = genStmt.lhs))
// List(stmt.copy(op = "<="))
Expand All @@ -381,8 +381,8 @@ object compiler {
*/
def varNameTransform(thisInstName: String, v: Var[?]): Var[?] = {
v match {
case x @ VarLit(name) => x
case x @ VarDymTyped(width, tp, name) =>
case x @ VarLit(name) => x
case x @ VarDynamic(width, tp, name) =>
tp match {
case VarType.Input | VarType.Output =>
x.copy(name = ioNameTransform(thisInstName, name))
Expand Down Expand Up @@ -411,7 +411,7 @@ object compiler {
/** recursively apply expr to expr Transform like varNameTransform */
def exprTransform(thisInstName: String, e: Expr[?]): Expr[?] = {
e match {
case v: Var[?] => varNameTransform(thisInstName, v)
case v: Var[?] => varNameTransform(thisInstName, v)
case x: BinOp[w] =>
BinOp(
exprTransform(thisInstName, x.a).asInstanceOf[Expr[Nothing]],
Expand Down
13 changes: 9 additions & 4 deletions src/main/scala/dependentChisel/codegen/sequentialCommands.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ object sequentialCommands {
case If(cond: Bool)
// case IfElse[w <: Int](b: Bool[w])
case Else[w <: Int]()
case Top()
case Top() // represents top level
}

/** all sorts of sequential commands
*/
sealed trait Cmds

/** atomic commands like decl,assign,etc */
sealed trait AtomicCmds extends Cmds

/** represent start/end of control block
*
* @param ctrl
Expand All @@ -34,9 +37,8 @@ object sequentialCommands {
case class End[CT <: Ctrl](ctrl: CT, uid: Uid) extends Cmds

/** atomic commands like decl,assign,etc */
sealed trait AtomicCmds extends Cmds

/** for new mod */
/** new inst for a module */
case class NewInstance(instNm: String, modNm: String) extends AtomicCmds

/** firrtl statements: weakly typed which doesn't require width of lhs = wid of rhs.
Expand All @@ -49,11 +51,14 @@ object sequentialCommands {
) extends AtomicCmds

/** for Wire, Reg, and IO */
case class VarDecls(v: VarDymTyped) extends AtomicCmds
case class VarDecls(v: VarDynamic) extends AtomicCmds
case object Skip extends AtomicCmds
/* TODO:also allow dym check which rm type sig of var[t] ,etc. cases
* of (lhs,rhs) are (dym,stat),(dym,dym)....
1.new super type for Var[w]
*/

/** formal verification commands */
case class BoolProp(name: String, prop: Bool) extends AtomicCmds

}
2 changes: 1 addition & 1 deletion src/main/scala/dependentChisel/codegen/typeCheck.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ object typeCheck {
val isWidthOk = isWidthEqu // | lhsGeqRhs
val msg =
"[error]".toRed() +
s" width mismatch in statement:\n${showPair(lhs.getname, i)}\n " +
s" width mismatch in statement:\n${showPair(lhs.getName, i)}\n " +
s"$op \n" +
s"${showPair(rhs.toString(), j)} "

Expand Down
11 changes: 10 additions & 1 deletion src/main/scala/dependentChisel/global.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dependentChisel

/* global vars */
/** global and package-wide settings
*
* same as package object in scala 2
*/
object global {
val enableWidthCheck = true
// val enableWidthCheck = false
Expand All @@ -12,4 +15,10 @@ object global {
counter += 1
counter
}

/** my pprint, not show field names
*
* @param x
*/
def mPPrint[T](x: T) = { pprint.pprintln(x, showFieldNames = false) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package dependentChisel.monadic
import cats.{Id, ~>}
import cats.data.State

import monadicAST.*
import monadicSyntax.*
import simpleAST.*
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// package precondition.syntax
package dependentChisel.monadic

import scala.compiletime.*
Expand All @@ -11,7 +10,7 @@ import cats.free.Free
import dependentChisel.syntax.naming.*
import dependentChisel.syntax.naming

object monadicAST {
object monadicSyntax {

sealed trait DslStoreA[A]

Expand All @@ -30,7 +29,8 @@ object monadicAST {

case class NewVar(name: String = "") extends DslStoreA[Var] // DslStoreA[Var]
// case class NewWire[t](name: String = "") extends DslStoreA[Var] // DslStoreA[Var]
case class NewWire[n <: Int]() extends DslStoreA[NewWire[n]] { // support both dynamic and static check
case class NewWire[n <: Int]()
extends DslStoreA[NewWire[n]] { // support both dynamic and static check
inline def getVal = constValueOpt[n]
}

Expand Down Expand Up @@ -69,8 +69,7 @@ object monadicAST {
): NewWire[n + m] = {
NewWire[n + m]()
}
case class IfElse(cond: BoolExpr, s1: DslStore[Unit], s2: DslStore[Unit])
extends DslStoreA[Unit]
case class IfElse(cond: BoolExpr, s1: DslStore[Unit], s2: DslStore[Unit]) extends DslStoreA[Unit]
case class If(cond: BoolExpr, s1: DslStore[Unit]) extends DslStoreA[Unit]
case class While(
cond: DslStore[Boolean],
Expand Down
4 changes: 3 additions & 1 deletion src/main/scala/dependentChisel/monadic/monadicTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ package dependentChisel.monadic
import cats.data.*
import cats.implicits.*
import cats.free.Free.*

import com.doofin.stdScalaJvm.*
import com.doofin.stdScala.mainRunnable

import monadicCompilers.*
import monadicAST.*
import monadicSyntax.*

object monadicTest extends mainRunnable {

override def main(args: Array[String] = Array()): Unit = {
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/dependentChisel/monadic/simpleAST.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dependentChisel.monadic

import dependentChisel.monadic.monadicAST.BoolExpr
import dependentChisel.monadic.monadicSyntax.BoolExpr

object simpleAST {
enum Stmt {
Expand Down
Loading