-
Notifications
You must be signed in to change notification settings - Fork 52
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
Icarus Verilog can trigger fatal Multiple assignments to port
issue due to simulated x
s
#1801
Comments
Okay, I'm going to write down my debugging process. There are a couple of things that stand out as possibly causing problems. First, I followed the reproduction instructions but couldn't get
Not sure why this is happening. Using
|
Added the following patch (ignore the whitespace changes) which fixes the combinational loop. The high-level idea is putting the output from the Because we're using the register, we need to reset the value in the register every time we loop which is why we add another group. @nathanielnrn can you take a shot at using this? diff --git a/fpgas/axi-calyx-py/axi-reads-calyx.futil b/fpgas/axi-calyx-py/axi-reads-calyx.futil
index 57f382ce..71af30c6 100644
--- a/fpgas/axi-calyx-py/axi-reads-calyx.futil
+++ b/fpgas/axi-calyx-py/axi-reads-calyx.futil
@@ -31,12 +31,12 @@ component m_arread_channel(
ARSIZE: 3,
ARLEN : 8, //in AXI4 this is 8 bits, 1-256 transfers in requested transaction.
-
+
// 00 for fixed, 01 for incrementing, 2 for wrap, needs to be incr)
ARBURST : 2) {
cells{
is_arvalid = std_reg(1);
- //todo(nathanielnrn): we get this from `s_axi_control`. Need to check
+ //todo(nathanielnrn): we get this from `s_axi_control`. Need to check
//how we known actual address
//should probably live in `s_axi_control` but for now will live here
ref base_addr = std_reg(64);
@@ -51,7 +51,7 @@ component m_arread_channel(
txn_adder = std_add(32);
block_transfer_done_and = std_and(1);
-
+ bt_reg = std_reg(1);
}
@@ -64,20 +64,28 @@ component m_arread_channel(
is_arvalid.write_en = 1'b1;
assert_val[done] = is_arvalid.done;
}
-
+
group deassert_val {
is_arvalid.in = 1'b0;
is_arvalid.write_en = 1'b1;
deassert_val[done] = is_arvalid.done;
}
+ group reset_bt {
+ bt_reg.in = 1'b0;
+ bt_reg.write_en = 1'b1;
+ reset_bt[done] = bt_reg.done;
+ }
+
group block_transfer{
block_transfer_done_and.left = ARREADY;
block_transfer_done_and.right = is_arvalid.out;
- block_transfer[done] = block_transfer_done_and.out;
+ bt_reg.in = block_transfer_done_and.out;
+ bt_reg.write_en = 1'b1;
+ block_transfer[done] = bt_reg.out;
}
- group do_ar_transfer {
+ group do_ar_transfer {
ARADDR = base_addr.out;
ARSIZE = 3'b110; //see link above, needs to match data width to host.
//For now this can be taken from .yxi, as size of mem.
@@ -119,6 +127,7 @@ component m_arread_channel(
txn_init;
while perform_reads.out with check_reads_done{
seq{
+ reset_bt;
assert_val;
block_transfer;
deassert_val;
@@ -147,7 +156,7 @@ component m_read_channel(
ref data_received = seq_mem_d1(32, 16, 64);
is_rdy = std_reg(1);
ref curr_addr = std_reg(64); //TODO(nathanielnrn): not used in axi, only internal
-
+
n_RLAST = std_not(1);
@@ -159,6 +168,7 @@ component m_read_channel(
block_transfer_done_and = std_and(1);
+ bt_reg = std_reg(1);
}
wires{
@@ -185,10 +195,18 @@ component m_read_channel(
deassert_rdy[done] = is_rdy.done;
}
+ group init_bt {
+ bt_reg.in = 1'b0;
+ bt_reg.write_en = 1'b1;
+ init_bt[done] = bt_reg.done;
+ }
+
group block_transfer {
block_transfer_done_and.left = is_rdy.out;
block_transfer_done_and.right = RVALID;
- block_transfer[done] = block_transfer_done_and.out;
+ bt_reg.in = block_transfer_done_and.out;
+ bt_reg.write_en = 1'b1;
+ block_transfer[done] = bt_reg.out;
//block_transfer[done] = !(is_rdy.out & RVALID) ? 1'b0; //good to be explicit and not rely on undefined behavior
}
@@ -205,6 +223,7 @@ component m_read_channel(
//XXX(nathanielnrn): is this it? Do we need any other conditions?
while n_RLAST.out with not_rlast{
seq{
+ init_bt;
assert_rdy;
block_transfer;
deassert_rdy;
@@ -247,7 +266,7 @@ component main(
cells{
vec1_data = seq_mem_d1(32,16,64);
// Not used currently
- //vec2_data = seq_mem_d1(32,16,4);
+ //vec2_data = seq_mem_d1(32,16,4);
output_data = seq_mem_d1(32,1,0);
curr_addr = std_reg(64); //TODO(nathanielnrn): figure out where this comes from, see generated toplevel and kernel interface requirements below. |
I think this was probably caused by #859 |
@nathanielnrn had a synchronous discussion about this and we noticed a couple of problems:
The fix was to add the following to the top of the harness:
There is a bigger problem to address here: writing a harness to execute Calyx programs is non-trivial because the user needs to reset control state and then correctly assert the |
Also, we should use |
Multiple assignments to port
issue due to simulated x
s
To elaborate a bit on the
As @rachitnigam mentioned, one solution to this is making sure that It is unclear why asking for waveforms causes the simulation to fail here, while just invoking |
Elaborating on some issues mentioned here.
Haven't had time to create a minimal reproducing example yet, will hopefully be able to work on that after Friday. For now the full steps and code generating the error is listed.
The tl;dr is that simulating verilog via
cocotb
, using Icarus as our simulator, can sometimes (when settingWAVES=1
) creates the following error:The relevant lines in the generated verilog are here.
The steps to reproduce should be as followed
(Technically, this step is not needed, the verilog in the branch should suffice but is here for completeness.)
3. Then navigate to
calyx/fpgas/axi-calyx-py/
and runfud e axi-reads-calyx.futil --from calyx --to verilog -o outputs/axi-reads.v
.This should create a file identical to the one in the branch
Navigate to
calyx/fpgas/axi-calyx-py/cocotb/
and runmake
(relevant Makefile). This executes the cocotb python test defined here. This should terminate normally after simulating for 1020 ns.In the same directory run
make WAVES=1
. This asks Icarus to create an.fst
file. This will give the errorFurther invocations of
make
also seem to throw this concurrent assignment error.To be able to simulate again (i.e going back to step 4) one can run
make clean
followed bymake
The text was updated successfully, but these errors were encountered: