summaryrefslogtreecommitdiff
path: root/main-scala3.scala
blob: dc6b5d8476ac27e1b5cc58e84bcf824f7c06988f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import chisel3._
import chisel3.util._
import chisel3.stage.ChiselStage

class DataBox[D <: Data](val a: D)

trait Monoid[D <: Data]:
  def unit(a: DataBox[D]): DataBox[D]
  def transform(a: DataBox[D]): DataBox[D]

given UIntMonoid: Monoid[UInt] with
  def unit(a: DataBox[UInt]): DataBox[UInt] = DataBox(a.a)
  def transform(a: DataBox[UInt]): DataBox[UInt] = DataBox(a.a+1.U)
  // def unit: DataBox[UInt] = DataBox(1.U)

given BoolMonoid: Monoid[Bool] with
  def unit(a: DataBox[Bool]): DataBox[Bool] = DataBox(a.a)
  def transform(a: DataBox[Bool]): DataBox[Bool] = DataBox(!a.a)

class AxiPorts[D <: Data](
  
)

// this typer should be part of the library code, there needs to be a
// way for users to get typers for their own datatypes in addition to
// being able to use built-in types
enum Typer[D <: Data](unit: DataBox[D] => DataBox[D], transform: DataBox[D] => DataBox[D]):
  case UIntTyper extends Typer(UIntMonoid.unit, UIntMonoid.transform)
  case BoolTyper extends Typer(BoolMonoid.unit, BoolMonoid.transform)
  def boxUnit(a: D): DataBox[D] = unit(DataBox(a))
  def boxTransform(a: D): DataBox[D] = transform(DataBox(a))

class Tree extends Module {
  import Typer._
  // ad-hoc typer
  given SIntTyper: Monoid[SInt] with
      def unit(a: DataBox[SInt]) = DataBox(a.a)
      def transform(a: DataBox[SInt]) = DataBox(a.a-1.S)

  val myData: UInt = 1.U
  val typeBoxedUInt = Typer.UIntTyper.boxUnit(myData) // myData.type
  val typeBoxedBool = Typer.BoolTyper.boxUnit(true.B)

  val a, b, c = IO(Input(typeBoxedBool.a))
  val foo, bar = IO(Input(UIntTyper.boxTransform(typeBoxedUInt.a).a))

  def sint_typer(using Monoid[SInt]) =
    val typeBoxedSInt = SIntTyper.unit(DataBox(-128.S))
    val fizz = IO(Input(typeBoxedSInt.a))
    fizz

  val fizz = sint_typer

  val out = IO(Output(UInt(8.W)))
  val myReg = RegInit(0.U(8.W))

  when(a && b && c) {
    myReg := foo
  }
  out := myReg
}


@main def runTree(): Unit = println(ChiselStage.emitVerilog(gen = new Tree))