How do you instanciate a same module twice? - chisel

I am developping a code in chisel, and tried to instanciate a module Encryption twice.
If I just use Enc0 in the code below, it works fine.
But if I use Enc0 and Enc1, then I have the following error appearing for line 40 :
[error] chisel3.internal.ChiselException: Connection between sink (chisel3.core.UInt#1fc1) and source (chisel3.core.UInt#1f8d) failed #: Sink or source unavailable to current module.
30 val Enc0 = Module(new Encryption())
31 Enc0.io.lab1 := a0
32 Enc0.io.lab2 := b0
33 Enc0.io.lab3 := a0 & b0
34 Enc0.io.key := io.secret_key
35 Enc0.io.wire_id := io.wire_index
36 Enc0.io.go := io.go
37 val tab0 = Enc0.io.enc
38 io.garbled_table.out0 := tab0
39
40 val Enc1 = Module(new Encryption())
41 Enc1.io.lab1 := a0
42 Enc1.io.lab2 := b1
43 Enc1.io.lab3 := a0 & b1
44 Enc1.io.key := io.secret_key
45 Enc1.io.wire_id := io.wire_index
46 Enc1.io.go := io.go
47 val tab1 = Enc1.io.enc
48 io.garbled_table.out1 := tab1
All the inputs and outputs of Enc0 and Enc1 are correctly connected, since Enc0 can work when I comment all lines 40-48.
So I don't know why it is not working

I have expanded this out to a module that does compile. Perhaps you can compare this to your example above. It is probably an error in the IO direction of one of your intermediate wires. It's less than ideal (there is working being done to improve error messages like this) but can you figure out which line is the problem by uncommenting replacing the right hand sides of 40-48 with DontCare, and replacing those one by one until you narrow down the offending line.
My example that seems to build.
import chisel3._
import chisel3.experimental.MultiIOModule
class Encryption extends Module {
val io = IO(new Bundle {
val lab1 = Input(Bool())
val lab2 = Input(Bool())
val lab3 = Input(Bool())
val key = Input(UInt(8.W))
val wire_id = Input(UInt(8.W))
val go = Input(UInt(8.W))
val enc = Output(UInt(8.W))
})
}
class Parent extends MultiIOModule {
val a0 = IO(Input(Bool()))
val b0 = IO(Input(Bool()))
val a1 = IO(Input(Bool()))
val b1 = IO(Input(Bool()))
val secret_key = IO(Input(UInt(8.W)))
val io = IO(new Bundle {
val secret_key = Input(UInt(8.W))
val wire_index = Input(UInt(8.W))
val garbled_table = new Bundle {
val out0 = Output(UInt(8.W))
val out1 = Output(UInt(8.W))
}
val go = Input(UInt(8.W))
})
val Enc0 = Module(new Encryption())
Enc0.io.lab1 := a0
Enc0.io.lab2 := b0
Enc0.io.lab3 := a0 & b0
Enc0.io.key := io.secret_key
Enc0.io.wire_id := io.wire_index
Enc0.io.go := io.go
val tab0 = Enc0.io.enc
io.garbled_table.out0 := tab0
val Enc1 = Module(new Encryption())
Enc1.io.lab1 := a0
Enc1.io.lab2 := b1
Enc1.io.lab3 := a0 & b1
Enc1.io.key := io.secret_key
Enc1.io.wire_id := io.wire_index
Enc1.io.go := io.go
val tab1 = Enc1.io.enc
io.garbled_table.out1 := tab1
}
object Encryption {
def main(args: Array[String]): Unit = {
println(Driver.emit(() => new Parent))
}
}

Related

Chisel compiled successfully but can't generate correctly verilog

I use Chisel write an RISC-V CPU, Chisel code compiled successfully and Firrtl code generate successfully too, but the verilog code just has a module statement.The Verilog files are basically empty.
It generates all module's Firrtl code.When I use Verilator to simulation it, under the test_run_dir fold it is just a 1kb verilog file and an empty VCD file.
Here is the code
package CPUModule
import chisel3._
import chisel3.util._
import chisel3.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
import IFUModule._
import IDUModule._
import MemModel._
import EXUModule._
import WBUModule._
class SingleCycleCPU extends Module {
val io = IO(new Bundle {
val in_enable = Input(Bool())
})
val MM = Module(new MemoryModel) // L1D and L1I
val PC = Module(new PromgrameCounter) // pc
val PD = Module(new PlexDecoder) // decoder
val RF = Module(new RegisterFile) // regfile
val ALU = Module(new ALU) // ALU
val AGU = Module(new LSU) // AGU
val WB = Module(new WriteBackUnit) // write back
// L1I
val MM_in_L1I_readen = Wire(Bool())
val MM_in_L1I_readdr = Wire(UInt(32.W))
val MM_out_L1I_readdata = Wire(UInt(32.W))
// L1D
val MM_in_L1D_readen = Wire(Bool())
val MM_in_L1D_readaddr = Wire(UInt(32.W))
val MM_out_L1D_readdata = Wire(UInt(32.W))
val MM_in_L1D_writeen = Wire(Bool())
val MM_in_L1D_writeaddr = Wire(UInt(32.W))
val MM_in_L1D_writedata = Wire(UInt(32.W))
// not use
MM_in_L1I_readen := false.B
MM_in_L1I_readdr := DontCare
MM_in_L1D_readen := false.B
MM_in_L1D_readaddr := DontCare
// MM_out_L1D_readdata := DontCare
MM_in_L1D_writeen := false.B
MM_in_L1D_writeaddr := DontCare
MM_in_L1D_writedata := DontCare
val MM_L1D_FLAG = Wire(Bool()) // L1D enable
MM.io.in_L1I_readenable := MM_in_L1I_readen
MM.io.in_L1I_readaddr := MM_in_L1I_readdr
MM_out_L1I_readdata := MM.io.out_L1I_readdata
MM.io.in_L1D_readenable := MM_in_L1D_readen
MM.io.in_L1D_readaddr := MM_in_L1D_readaddr
MM_out_L1D_readdata := MM.io.out_L1D_readdata
MM.io.in_L1D_writeenable := MM_in_L1D_writeen
MM.io.in_L1D_writeaddr := MM_in_L1D_writeaddr
MM.io.in_L1D_writedata := MM_in_L1D_writedata
// PC
val PC_out_data = Wire(UInt(32.W))
PC.io.in_enable := io.in_enable // 启动PC
PC.io.in_immpcenable := false.B
PC.io.in_immpcnumber := 0.U(32.W)
PC_out_data := PC.io.out_pcnumber
// get inst
when(!MM_in_L1D_readen && !MM_in_L1D_writeen) {
MM_in_L1I_readen := true.B
MM_in_L1I_readdr := PC_out_data
} .otherwise {
MM_in_L1I_readen := false.B
MM_in_L1I_readdr := DontCare
}
// decoder
val PD_out_mircocode = Wire(UInt(32.W))
val PD_out_rs1 = Wire(UInt(5.W))
val PD_out_rs2 = Wire(UInt(5.W))
val PD_out_rd = Wire(UInt(5.W))
val PD_out_immItype = Wire(UInt(12.W))
val PD_out_immStype5 = Wire(UInt(5.W))
val PD_out_immStype7 = Wire(UInt(7.W))
val PD_out_shamt = Wire(UInt(5.W))
val reg_mircocode = RegInit(0.U(32.W))
val reg_rs1 = RegInit(0.U(5.W))
val reg_rs2 = RegInit(0.U(5.W))
val reg_rd = RegInit(0.U(5.W))
val reg_immItype = RegInit(0.U(12.W))
val reg_immStype5 = RegInit(0.U(5.W))
val reg_immStype7 = RegInit(0.U(7.W))
val reg_shamt = RegInit(0.U(5.W))
PD.io.in_instruction := MM_out_L1I_readdata
PD_out_mircocode := PD.io.out_mircocode
PD_out_rs1 := PD.io.out_rs1
PD_out_rs2 := PD.io.out_rs2
PD_out_rd := PD.io.out_rd
PD_out_immItype := PD.io.out_immItype
PD_out_immStype5 := PD.io.out_immStype5
PD_out_immStype7 := PD.io.out_immStype7
PD_out_shamt := PD.io.out_shamt
reg_mircocode := PD_out_mircocode
reg_rs1 := PD_out_rs1
reg_rs2 := PD_out_rs2
reg_rd := PD_out_rd
reg_immItype := PD_out_immItype
reg_immStype5 := PD_out_immStype5
reg_immStype7 := PD_out_immStype7
reg_shamt := PD_out_shamt
// reg file
val RF_in_readen = Wire(Bool())
val RF_out_readdata_1 = Wire(UInt(32.W))
val RF_out_readdata_2 = Wire(UInt(32.W))
val RF_in_writeen = Wire(Bool())
val RF_in_writeaddr = Wire(UInt(32.W))
val RF_in_writedata = Wire(UInt(32.W))
RF_in_readen := true.B
RF_in_writeen := false.B
RF.io.in_read := RF_in_readen
RF.io.in_readaddress_1 := reg_rs1
RF.io.in_readaddress_2 := reg_rs2
RF_out_readdata_1 := RF.io.out_readdata_1
RF_out_readdata_2 := RF.io.out_readdata_2
RF.io.in_write := RF_in_writeen
RF.io.in_writeaddress_1 := RF_in_writeaddr
RF.io.in_writedata_1 := RF_in_writedata
val reg_rf_data_1 = RegInit(0.U(32.W))
val reg_rf_data_2 = RegInit(0.U(32.W))
reg_rf_data_1 := RF_out_readdata_1
reg_rf_data_2 := RF_out_readdata_2
// ALU AGU
// ALU
val ALU_out_rd = Wire(UInt(32.W))
ALU.io.in_mircocode := reg_mircocode
ALU.io.in_rs1data := reg_rf_data_1
ALU.io.in_rs2data := reg_rf_data_2
ALU.io.in_immItype := reg_immItype
ALU.io.in_shamt := reg_shamt
ALU_out_rd := ALU.io.out_rddata
// AGU
val AGU_out_L1D_readen = Wire(Bool())
val AGU_out_L1D_readaddr = Wire(UInt(32.W))
val AGU_out_L1D_writeen = Wire(Bool())
val AGU_out_L1D_writeaddr = Wire(UInt(32.W))
val AGU_out_L1D_writedata = Wire(UInt(32.W))
val AGU_out_rdaddr = Wire(UInt(5.W))
AGU.io.in_mircocode := reg_mircocode
AGU.io.in_rs1data := reg_rf_data_1
AGU.io.in_rs2data := reg_rf_data_2
AGU.io.in_immItype := reg_immItype
AGU.io.in_immStype5 := reg_immStype5
AGU.io.in_immStype7 := reg_immStype7
AGU.io.in_rdaddress := reg_rd
AGU_out_L1D_readen := AGU.io.out_read_enable
AGU_out_L1D_writeen := AGU.io.out_write_enable
AGU_out_L1D_writeaddr := AGU.io.out_writeaddress
AGU_out_L1D_writedata := AGU.io.out_writedata
AGU_out_L1D_readaddr := AGU.io.out_readaddress
AGU_out_rdaddr := AGU.io.out_rdaddress
// connect AGU output to L1D input
when(AGU_out_L1D_readen) {
// connect
MM_in_L1D_readen := AGU_out_L1D_readen
MM_in_L1D_readaddr := AGU_out_L1D_readaddr
// not use
MM_in_L1D_writeen := false.B
MM_in_L1D_writeaddr := DontCare
MM_in_L1D_writedata := DontCare
MM_L1D_FLAG := true.B
} .elsewhen(AGU_out_L1D_writeen) {
// connect
MM_in_L1D_writeen := AGU_out_L1D_writeen
MM_in_L1D_writeaddr := AGU_out_L1D_writeaddr
MM_in_L1D_writedata := AGU_out_L1D_writedata
// not use
MM_in_L1D_readen := false.B
MM_in_L1D_readaddr := DontCare
MM_L1D_FLAG := false.B
} .otherwise {
// not use
MM_in_L1D_readen := false.B
MM_in_L1D_readaddr := DontCare
MM_in_L1D_writeen := false.B
MM_in_L1D_writeaddr := DontCare
MM_in_L1D_writedata := DontCare
MM_L1D_FLAG := true.B
}
val reg_L1D_readdata = RegInit(0.U(32.W))
reg_L1D_readdata := MM_out_L1D_readdata
val reg_ALU_rddata = RegInit(0.U(32.W))
reg_ALU_rddata := ALU_out_rd
val reg_AGU_rdaddr = RegInit(0.U(4.W))
reg_AGU_rdaddr := AGU_out_rdaddr
// write back
val WB_in_enable = Wire(Bool())
val WB_out_rdaddr = Wire(UInt(32.W))
val WB_out_rddata = Wire(UInt(32.W))
WB_in_enable := true.B
WB.io.in_enable := WB_in_enable
WB.io.in_address_1 := reg_AGU_rdaddr
WB.io.in_needwritedata_1 := reg_L1D_readdata
WB.io.in_mircocode := reg_mircocode
WB.io.in_address_2 := reg_rd
WB.io.in_needwritedata_2 := reg_ALU_rddata
WB_out_rdaddr := WB.io.out_address
WB_out_rddata := WB.io.out_data
val reg_wb_addr = RegInit(0.U(5.W))
val reg_wb_data = RegInit(0.U(32.W))
reg_wb_addr := WB_out_rdaddr
reg_wb_data := WB_out_rddata
// close read com
RF_in_readen := false.B
// open write com
RF_in_writeen := true.B
RF_in_writeaddr := reg_wb_addr
RF_in_writedata := reg_wb_data
}
// Tester
class TestSingleCycleCPU(c: SingleCycleCPU) extends PeekPokeTester(c) {
// poke
poke(c.io.in_enable, true.B)
// wait
step(1)
}
object SingleCycleCPU {
def main(args: Array[String]): Unit = {
val args = Array("--backend-name", "verilator")
chisel3.iotesters.Driver.execute(args, () => new SingleCycleCPU) { c => new TestSingleCycleCPU(c) }
// chisel3.Driver.execute(args, () => new SingleCycleCPU)
}
}
The FIRRTL compiler does a fair amount of optimizations between the output of Chisel and emitting Verilog. In this case, your code is getting removed by Dead Code Elimination because there is no effect on the outside world.
I would suggest adding some output to monitor what's going on, perhaps turn PC_out_data into an output:
val io = IO(new Bundle {
val in_enable = Input(Bool())
val PC_out_data = Output(UInt(32.W))
})
You'll have to replace references to PC_out_data with io.PC_out_data, but if you do this, anything that has an effect on the PC will no longer be deleted.
For more information, check out my answer to this question which discusses optimizations and how they remove signals (in addition to how names are propagated from Chisel to Verilog which you also might find interesting): How to keep all variable name In chisel when generate Verilog code

Sublime Text 3 smlnj REPL not printing exceptions

When an exception is raised in the code I don't get any message or anything at all printed. For example the following code:
fun test n =
if n = 1
then raise Fail ("hey")
else 2
val t = test 1
When I type
- use "test.sml";
the output is just
[opening test.sml]
val it = () : unit
I would like it to print that an exception was raised and the message ("hey")
Any ideas on how to fix this
I'm using smlnj 110.82
Because you didn't handle your exception.
You should do like:
fun test n =
if n = 1
then raise Fail ("hey")
else 2
val t = test 1 handle Fail msg => 0;
[opening practice.sml]
val test = fn : int -> int
val t = 0 : int
val it = () : unit
if you hope to see Fail msg in your screen, just take use of side effect:
fun test n =
if n = 1
then raise Fail ("hey")
else 2
val t = test 1 handle Fail msg => (print (msg ^ "\n"); 0)
[opening practice.sml]
hey
val test = fn : int -> int
val t = 0 : int
val it = () : unit

How to generate a sum and carry with Chisel in one line?

Is it possible to generate sum and carry in one line in Chisel similar to this code in Verilog?
module Adder_with_carry(
input [3:0] A,
input [3:0] B,
input Carry_in,
output [3:0] Sum,
output Carry_out
);
assign {Carry_out, Sum} = A + B + Carry_in;
endmodule
I am using this code
class Adder extends Module{
val io = new Bundle{
val a = UInt(INPUT, 3)
val b = UInt(INPUT, 3)
val carry_in = UInt (INPUT, 1)
val sum = UInt (OUTPUT, 2)
val carry_out = UInt(OUTPUT, 1)
}
val SUM = io.a + io.b + io.carry_in;
io.carry_out := SUM(2)
io.sum := SUM(1,0)
}
But I think it will be more convenient if there is a one-liner for this.

andThen for function of two arguments in Scala

Suppose I have two functions f and g:
val f: (Int, Int) => Int = _ + _
val g: Int => String = _ + ""
Now I would like to compose them with andThen to get a function h
val h: (Int, Int) => String = f andThen g
Unfortunately it doesn't compile :(
scala> val h = (f andThen g)
<console> error: value andThen is not a member of (Int, Int) => Int
val h = (f andThen g)
Why doesn't it compile and how can I compose f and g to get (Int, Int) => String ?
It doesn't compile because andThen is a method of Function1 (a function of one parameter: see the scaladoc).
Your function f has two parameters, so would be an instance of Function2 (see the scaladoc).
To get it to compile, you need to transform f into a function of one parameter, by tupling:
scala> val h = f.tupled andThen g
h: (Int, Int) => String = <function1>
test:
scala> val t = (1,1)
scala> h(t)
res1: String = 2
You can also write the call to h more simply because of auto-tupling, without explicitly creating a tuple (although auto-tupling is a little controversial due to its potential for confusion and loss of type-safety):
scala> h(1,1)
res1: String = 2
Function2 does not have an andThen method.
You can manually compose them, though:
val h: (Int, Int) => String = { (x, y) => g(f(x,y)) }

How to return a function in scala

How can I return a function side-effecting lexical closure1 in Scala?
For instance, I was looking at this code sample in Go:
...
// fib returns a function that returns
// successive Fibonacci numbers.
func fib() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return b
}
}
...
println(f(), f(), f(), f(), f())
prints
1 2 3 5 8
And I can't figure out how to write the same in Scala.
1. Corrected after Apocalisp comment
Slightly shorter, you don't need the return.
def fib() = {
var a = 0
var b = 1
() => {
val t = a;
a = b
b = t + b
b
}
}
Gah! Mutable variables?!
val fib: Stream[Int] =
1 #:: 1 #:: (fib zip fib.tail map Function.tupled(_+_))
You can return a literal function that gets the nth fib, for example:
val fibAt: Int => Int = fib drop _ head
EDIT: Since you asked for the functional way of "getting a different value each time you call f", here's how you would do that. This uses Scalaz's State monad:
import scalaz._
import Scalaz._
def uncons[A](s: Stream[A]) = (s.tail, s.head)
val f = state(uncons[Int])
The value f is a state transition function. Given a stream, it will return its head, and "mutate" the stream on the side by taking its tail. Note that f is totally oblivious to fib. Here's a REPL session illustrating how this works:
scala> (for { _ <- f; _ <- f; _ <- f; _ <- f; x <- f } yield x)
res29: scalaz.State[scala.collection.immutable.Stream[Int],Int] = scalaz.States$$anon$1#d53513
scala> (for { _ <- f; _ <- f; _ <- f; x <- f } yield x)
res30: scalaz.State[scala.collection.immutable.Stream[Int],Int] = scalaz.States$$anon$1#1ad0ff8
scala> res29 ! fib
res31: Int = 5
scala> res30 ! fib
res32: Int = 3
Clearly, the value you get out depends on the number of times you call f. But this is all purely functional and therefore modular and composable. For example, we can pass any nonempty Stream, not just fib.
So you see, you can have effects without side-effects.
While we're sharing cool implementations of the fibonacci function that are only tangentially related to the question, here's a memoized version:
val fib: Int => BigInt = {
def fibRec(f: Int => BigInt)(n: Int): BigInt = {
if (n == 0) 1
else if (n == 1) 1
else (f(n-1) + f(n-2))
}
Memoize.Y(fibRec)
}
It uses the memoizing fixed-point combinator implemented as an answer to this question: In Scala 2.8, what type to use to store an in-memory mutable data table?
Incidentally, the implementation of the combinator suggests a slightly more explicit technique for implementing your function side-effecting lexical closure:
def fib(): () => Int = {
var a = 0
var b = 1
def f(): Int = {
val t = a;
a = b
b = t + b
b
}
f
}
Got it!! after some trial and error:
def fib() : () => Int = {
var a = 0
var b = 1
return (()=>{
val t = a;
a = b
b = t + b
b
})
}
Testing:
val f = fib()
println(f(),f(),f(),f())
1 2 3 5 8
You don't need a temp var when using a tuple:
def fib() = {
var t = (1,-1)
() => {
t = (t._1 + t._2, t._1)
t._1
}
}
But in real life you should use Apocalisp's solution.