Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different result between run-single and run-bak #6

Open
anjianfeng opened this issue May 12, 2017 · 2 comments
Open

Different result between run-single and run-bak #6

anjianfeng opened this issue May 12, 2017 · 2 comments

Comments

@anjianfeng
Copy link
Collaborator

anjianfeng commented May 12, 2017

很多同学都遇到了这个问题,run-bak始终正确,但是run-single时对时错。
我分析了两个同学的代码,发现时对时错的代码描述在逻辑判断上过于复杂,主要集中在对dmm和imm的操作部分,例如某同学top.scala的原始部分代码如下:

when (io.boot && io.test_im_wr){
	imm(io.test_im_addr >> 2) := io.test_im_in
} 
.elsewhen (io.boot && io.test_dm_wr){
	dmm(io.test_dm_addr >> 2) := io.test_dm_in
} 
.elsewhen (io.boot && io.test_im_rd){
	io.test_im_out := imm(io.test_im_addr >> 2)
} 
.elsewhen (io.boot && io.test_dm_rd){
	io.test_dm_out := dmm(io.test_dm_addr >> 2)
} 
.elsewhen (!io.boot){
    cpath.io.Inst := imm(dpath.io.imem_addr >> 2)
	dpath.io.dmem_datOut := dmm(dpath.io.dmem_addr >> 2)
	when (cpath.io.MemWr === "b1".U) {
		dmm(dpath.io.dmem_addr >> 2) := dpath.io.dmem_datIn
	}

}

这个代码从逻辑上来说确实没有问题,但是条件判断嵌套过于复杂,在执行上述判断嵌套却无法始终保持正确,所以我做了下面的修改:

cpath.io.Inst := imm(dpath.io.imem_addr >> 2)
dpath.io.dmem_datOut := dmm(dpath.io.dmem_addr >> 2)
io.test_dm_out := dmm(io.test_dm_addr >> 2)

when (io.boot && io.test_im_wr){
	imm(io.test_im_addr >> 2) := io.test_im_in
} 
.elsewhen (io.boot && io.test_dm_wr){
	dmm(io.test_dm_addr >> 2) := io.test_dm_in
} 
.elsewhen (io.boot && io.test_im_rd){
	io.test_im_out := imm(io.test_im_addr >> 2)
} 
.elsewhen (io.boot && io.test_dm_rd){
	//io.test_dm_out := dmm(io.test_dm_addr >> 2)
} 
.elsewhen (!io.boot){
	//cpath.io.Inst := imm(dpath.io.imem_addr >> 2)
	//dpath.io.dmem_datOut := dmm(dpath.io.dmem_addr >> 2)
	when (cpath.io.MemWr === "b1".U) {
		dmm(dpath.io.dmem_addr >> 2) := dpath.io.dmem_datIn
	}

}

这个修改将一些不必要的条件去除了(被注释掉的三行),重新运行run-single始终可以通过。

暂时的结论:
不要做过于复杂的判断嵌套,否则有些分支可能不能按预期进入。
至于为何run-bak始终正确,可能是两者仿真机制不同。
我们目前只能从代码描述上进行预防。
请有问题的同学进行尝试,可以将修改结果进行反馈。

@zavs
Copy link
Owner

zavs commented May 12, 2017

Yes, it is from the nested conditional determinations. This problem caused by wrong if-else branch. The "if-else" branch means that "else" will happens if the "if" condition does not happen. However, in our expressions, there are, somehow, the logical overlaps among these conditions, that also why the nested conditions not works correctly in test.
However, I also found if we assign 'cpath.io.Inst' and 'dpath.io.dmem_datOut' without any multiplexer the data path will not be fixed in non-working mode in resetting (when bot =1). As the problem is overlapping logic, we just use "when" to condition test output instead of "elsewhen", and initial the memory output wires.

The code should be:

io.test_dm_out := 0.U
io.test_im_out := 0.U
cpath.io.Inst := 0.U

when (io.boot && io.test_im_wr){
	imm(io.test_im_addr >> 2) := io.test_im_in
	cpath.io.Inst := 0.U
 } 
when (io.boot && io.test_dm_wr){
	dmm(io.test_dm_addr >> 2) := io.test_dm_in
	cpath.io.Inst := 0.U
} 
when (io.boot && io.test_im_rd){
	io.test_im_out := imm(io.test_im_addr >> 2)
	cpath.io.Inst := 0.U
} 
when (io.boot && io.test_dm_rd){
	io.test_dm_out := dmm(io.test_dm_addr >> 2)
	cpath.io.Inst := 0.U
} 
when (!io.boot){
	cpath.io.Inst := Mux(io.boot, 0.U, imm(dpath.io.imem_addr >> 2))
	dpath.io.dmem_datOut := dmm(dpath.io.dmem_addr >> 2)
	when (cpath.io.MemWr) {
		dmm(dpath.io.dmem_addr >> 2) := dpath.io.dmem_datIn
        }
}

It works in my test. It is from our wrong code instead of a bug of chisel or c simulator. As for why Verilator backend works fine constantly, I just guess Firrtl (Firrtl is adopted in C simulation backend) prefer a more detailed simulation than Verilog, in which the function coverage is considered by assigning random signals for stimulated inputs in tester. So, from this point, the C backend can find more problems and bugs from our circuits descriptions.

@SYAAAA
Copy link

SYAAAA commented May 25, 2017

the problem run-single not pass has been solved by me, for instruction nop, if you don't set the init signal such as regwr and memwr, the wrong data may be writen in, because run-bak will init signal as 0, so most of us can pass the run-bak.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants