YosysHQ / yosys

Yosys Open SYnthesis Suite
https://yosyshq.net/yosys/
ISC License
3.46k stars 886 forks source link

ERROR: Assert `current_val[i].wire != NULL || current_val[i] == value.bits[i]\' failed in ./kernel/consteval.h:79. #1479

Open norandomtechie opened 4 years ago

norandomtechie commented 4 years ago

Steps to reproduce the issue

The following code causes Yosys to fail an assertion error:

// Lab 11 
module top (hz100, reset, pb, ss7, ss6, ss5, ss4, ss3, ss2, ss1, ss0, left, right, red, green, blue);
  input hz100, reset;
  input [20:0] pb;
  output [7:0] ss7, ss6, ss5, ss4, ss3, ss2, ss1, ss0, left, right;
  output red, green, blue;
  // Variable, Wire, and Registries
  reg [31:0] entry; // value being entered
  reg [31:0] saved; // saved value to use as a second operand
  reg [4:0] op; // the selected operation
  reg displaysaved; // show entry or saved?
  reg equalpressed; // has equal been pressed?
  wire [4:0] key; // outkey of scankey module
  wire pressed; // strobe of scankey module
  wire [7:0] interss7;
  reg [31:0] nextresult;
  wire [31:0] addresult;
  wire [31:0] subresult;

  // Instantiations
  //fa u(.x(pb[0]), .y(pb[1]), .cin(pb[2]), .cout(right[1]), .s(right[0]));
  //fa4 u(.x(pb[7:4]), .y(pb[3:0]), .cin(pb[8]), .cout(right[4]), .s(right[3:0]));
  //fa8 u(.x(pb[15:8]), .y(pb[7:0]), .cin(pb[16]), .cout(red), .s(right[7:0]));
  //bcda8 u(.x(pb[15:8]), .y(pb[7:0]), .cin(pb[16]), .cout(red), .s(right[7:0]));
  scankey sk(.clk(hz100), .reset(reset), .inkeys({pb[19:15],5'b0,pb[9:0]}), .strobe(pressed), .outkey(key));
  bcdadd32 bcd8a(.x(saved), .y(entry), .s(addresult));
  bcdsub32 bcd8s(.x(saved), .y(entry), .s(subresult));

  // 7-Segment Set
  //wire [31:0] num = displaysaved ? saved : entry;
  wire [31:0] pos = displaysaved ? saved : entry;
  wire isneg = pos[31:28] == 9;
  wire [31:0] neg;
  bcdsub32 inverter(.x(0), .y(pos), .s(neg));
  wire [31:0] num = isneg ? neg : pos;
  assign ss7 = (isneg) ? 8'b01000000 : interss7;
  ssdec s7(.in(num[31:28]), .enable(|num[31:28]), .out(interss7));
  ssdec s6(.in(num[27:24]), .enable(|num[31:24]), .out(ss6));
  ssdec s5(.in(num[23:20]), .enable(|num[31:20]), .out(ss5));
  ssdec s4(.in(num[19:16]), .enable(|num[31:16]), .out(ss4));
  ssdec s3(.in(num[15:12]), .enable(|num[31:12]), .out(ss3));
  ssdec s2(.in(num[11:8]), .enable(|num[31:8]), .out(ss2));
  ssdec s1(.in(num[7:4]), .enable(|num[31:4]), .out(ss1));
  ssdec s0(.in(num[3:0]), .enable(1'b1), .out(ss0));

  // Main Body Code
  //always @(*) nextresult = entry;
  //always @(*) begin
  // nextresult <= saved;
  // if (op == 5'b00000) nextresult <= entry;
  // if (op == 5'b10010) nextresult <= saved + entry;
  // if (op == 5'b10011) nextresult <= saved - entry;
  //end
  always @(*) begin
    nextresult <= saved;
    if (op == 5'b00000) nextresult <= entry;
    if (op == 5'b10010) nextresult <= addresult;
    if (op == 5'b10011) nextresult <= subresult;
  end
  always @(posedge pressed, posedge reset) begin
    if (reset == 1'b1) begin
      entry <= 32'b0;
      saved <= 32'b0;
      op <= 5'b0;
      displaysaved <= 1'b0;
      equalpressed <= 1'b0;
    end
    else begin
      if (key == 5'b10001) begin
        if (displaysaved == 1'b0) begin
          entry <= (entry >> 4);
        end
      end
      if (key == 5'b10000) begin
        saved <= nextresult;
        displaysaved <= 1;
        equalpressed <= 1;
      end
      if (key[4] == 0) begin
        if (equalpressed == 1) begin
          entry <= {28'b0,key[3:0]};
          saved <= 32'b0;
          op <= 5'b0;
          displaysaved <= 1'b0;
          equalpressed <= 1'b0;
        end
        else begin
          if(entry[31:28] == 4'b0) begin
            entry <= (entry << 4) | key;
          end
          else begin
            entry <= entry | key;
          end
          displaysaved <= 0;
        end
      end
      if (key[4:1] == 4'b1001) begin
        if(equalpressed == 0) begin
          saved <= nextresult;
        end
        op[4:0] <= key[4:0];
        displaysaved <= 1;
        entry <= 0;
        equalpressed <= 0;
      end
    end
  end 
endmodule //32-Bit BCD Subtractor 

module bcdsub32(x, y, s);
  //IO
  input wire [31:0] x, y;
  output wire [31:0] s;
  //Variable Declarations
  wire [3:0] cset;
  //Instantations
  bcda8 e1(.x(x[7:0]), .y(8'h99-y[7:0]), .cin(1'b1), .cout(cset[0]), .s(s[7:0]));
  bcda8 e2(.x(x[15:8]), .y(8'h99-y[15:8]), .cin(cset[0]), .cout(cset[1]), .s(s[15:8]));
  bcda8 e3(.x(x[23:16]), .y(8'h99-y[23:16]), .cin(cset[1]), .cout(cset[2]), .s(s[23:16]));
  bcda8 e4(.x(x[31:24]), .y(8'h99-y[31:24]), .cin(cset[2]), .cout(cset[3]), .s(s[31:24]));

endmodule //32-Bit BCD Adder 
module bcdadd32(x, y, s);
  //IO
  input wire [31:0] x, y;
  output wire [31:0] s;
  //Variable Declarations
  wire [3:0] cset;
  //Instantations
  bcda8 e1(.x(x[7:0]), .y(y[7:0]), .cin(1'b0), .cout(cset[0]), .s(s[7:0]));
  bcda8 e2(.x(x[15:8]), .y(y[15:8]), .cin(cset[0]), .cout(cset[1]), .s(s[15:8]));
  bcda8 e3(.x(x[23:16]), .y(y[23:16]), .cin(cset[1]), .cout(cset[2]), .s(s[23:16]));
  bcda8 e4(.x(x[31:24]), .y(y[31:24]), .cin(cset[2]), .cout(cset[3]), .s(s[31:24]));

endmodule //8-Bit BCD Adder 

module bcda8(x, y, cin, cout, s);
  //IO
  input wire [7:0] x, y;
  input wire cin;
  output wire [7:0] s;
  output wire cout;

  //Variable Declaration
  wire cset;

  //Instantiations
  bcda4 d1(.x(x[3:0]), .y(y[3:0]), .cin(cin), .cout(cset), .s(s[3:0]));
  bcda4 d2(.x(x[7:4]), .y(y[7:4]), .cin(cset), .cout(cout), .s(s[7:4]));

  //Main Body Code

endmodule //4-Bit BCD Adder 
module bcda4(x, y, cin, cout, s);
  //IO
  input wire [3:0] x, y;
  input wire cin;
  output wire [3:0] s;
  output wire cout;

  //Variable Declaration
  wire [3:0] new_s;
    //Variable names are hard
  wire [3:0] yote;
  wire new_cout;
  wire c_yote;

  //Instantiations
  fa4 c1(.x(x[3:0]), .y(y[3:0]), .cin(cin), .cout(c_yote), .s(yote[3:0]));
  fa4 c2(.x(yote[3:0]), .y(4'b0110), .cin(c_yote), .cout(new_cout), .s(new_s[3:0]));

  //Main Body Code
  assign s = (yote > 4'b1001) ? new_s : yote;
  assign cout = (yote > 4'b1001) ? new_cout : c_yote;

endmodule // 8-Bit Binary Ripple-Carry Adder 

module fa8(x, y, cin, cout, s);
  //IO
  input wire [7:0] x, y;
  input wire cin;
  output wire [7:0] s;
  output wire cout;

  // Variable Declaration
  wire [6:0] cset;

  // Instantiations
  fa b1(.x(x[0]), .y(y[0]), .cin(cin), .cout(cset[0]), .s(s[0]));
  fa b2(.x(x[1]), .y(y[1]), .cin(cset[0]), .cout(cset[1]), .s(s[1]));
  fa b3(.x(x[2]), .y(y[2]), .cin(cset[1]), .cout(cset[2]), .s(s[2]));
  fa b4(.x(x[3]), .y(y[3]), .cin(cset[2]), .cout(cset[3]), .s(s[3]));
  fa b5(.x(x[4]), .y(y[4]), .cin(cset[3]), .cout(cset[4]), .s(s[4]));
  fa b6(.x(x[5]), .y(y[5]), .cin(cset[4]), .cout(cset[5]), .s(s[5]));
  fa b7(.x(x[6]), .y(y[6]), .cin(cset[5]), .cout(cset[6]), .s(s[6]));
  fa b8(.x(x[7]), .y(y[7]), .cin(cset[6]), .cout(cout), .s(s[7]));
  //Main Body Code 
endmodule // 4-Bit Binary Ripple-Carry Adder 

module fa4(x, y, cin, cout, s);
  // IO
  input wire [3:0] x, y;
  input wire cin;
  output wire [3:0] s;
  output wire cout;

  // Variable Declaration
  wire [2:0] cset;

  // Instantiations
  fa a1(.x(x[0]), .y(y[0]), .cin(cin), .cout(cset[0]), .s(s[0]));
  fa a2(.x(x[1]), .y(y[1]), .cin(cset[0]), .cout(cset[1]), .s(s[1]));
  fa a3(.x(x[2]), .y(y[2]), .cin(cset[1]), .cout(cset[2]), .s(s[2]));
  fa a4(.x(x[3]), .y(y[3]), .cin(cset[2]), .cout(cout), .s(s[3])); 
endmodule // Full Adder Module 

module fa(x, y, cin, cout, s);
  // IO
  input wire x, y, cin;
  output wire cout, s;

  // Main Body Code
  assign {cout,s} = x+y+cin;

endmodule // Seven Segment Decoder 

module ssdec(in, enable, out);
    //Setup IO
    input wire [3:0]in, enable;
    output wire [6:0]out;
    //Declare Array
    wire [15:0] aarray;
    wire [15:0] barray;
    wire [15:0] carray;
    wire [15:0] darray;
    wire [15:0] earray;
    wire [15:0] farray;
    wire [15:0] garray;

    //Declare Inputs
    wire W;
    wire X;
    wire Y;
    wire Z;

    //Truth Tables
    assign aarray[15:0] = {1'b1,1'b1,1'b0,1'b1,1'b0,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b0,1'b1,1'b1,1'b0,1'b1};
    assign barray[15:0] = {1'b0,1'b0,1'b1,1'b0,1'b0,1'b1,1'b1,1'b1,1'b1,1'b0,1'b0,1'b1,1'b1,1'b1,1'b1,1'b1};
    assign carray[15:0] = {1'b0,1'b0,1'b1,1'b0,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b0,1'b1,1'b1};
    assign darray[15:0] = {1'b0,1'b1,1'b1,1'b1,1'b1,1'b0,1'b1,1'b1,1'b0,1'b1,1'b1,1'b0,1'b1,1'b1,1'b0,1'b1};
    assign earray[15:0] = {1'b1,1'b1,1'b1,1'b1,1'b1,1'b1,1'b0,1'b1,1'b0,1'b1,1'b0,1'b0,1'b0,1'b1,1'b0,1'b1};
    assign farray[15:0] = {1'b1,1'b1,1'b0,1'b1,1'b1,1'b1,1'b1,1'b1,1'b0,1'b1,1'b1,1'b1,1'b0,1'b0,1'b0,1'b1};
    assign garray[15:0] = {1'b1,1'b1,1'b1,1'b0,1'b1,1'b1,1'b1,1'b1,1'b0,1'b1,1'b1,1'b1,1'b1,1'b1,1'b0,1'b0};

    //Input Assignment
    assign W = in[3];
    assign X = in[2];
    assign Y = in[1];
    assign Z = in[0];
    //7 Segments Outputs
    assign out[0] = aarray[{W,X,Y,Z}] & enable;
    assign out[1] = barray[{W,X,Y,Z}] & enable;
    assign out[2] = carray[{W,X,Y,Z}] & enable;
    assign out[3] = darray[{W,X,Y,Z}] & enable;
    assign out[4] = earray[{W,X,Y,Z}] & enable;
    assign out[5] = farray[{W,X,Y,Z}] & enable;
    assign out[6] = garray[{W,X,Y,Z}] & enable;

endmodule // Scankey Module 

module scankey(clk, reset, inkeys, strobe, outkey);
  //IO
  input wire clk, reset;
  input wire [19:0] inkeys;
  output wire strobe;
  output wire [4:0] outkey;
  //Variable Declarations
  wire keyclk;
  reg [1:0] deloot;

  assign strobe = deloot[1];
  assign keyclk = |inkeys;

  assign outkey = (inkeys[19]==1) ? 5'b10011 :
            (inkeys[18]==1) ? 5'b10010 :
            (inkeys[17]==1) ? 5'b10001 :
            (inkeys[16]==1) ? 5'b10000 :
            (inkeys[15]==1) ? 5'b01111 :
            (inkeys[14]==1) ? 5'b01110 :
            (inkeys[13]==1) ? 5'b01101 :
            (inkeys[12]==1) ? 5'b01100 :
            (inkeys[11]==1) ? 5'b01011 :
            (inkeys[10]==1) ? 5'b01010 :
            (inkeys[9]==1) ? 5'b01001 :
            (inkeys[8]==1) ? 5'b01000 :
            (inkeys[7]==1) ? 5'b00111 :
            (inkeys[6]==1) ? 5'b00110 :
            (inkeys[5]==1) ? 5'b00101 :
            (inkeys[4]==1) ? 5'b00100 :
            (inkeys[3]==1) ? 5'b00011 :
            (inkeys[2]==1) ? 5'b00010 :
            (inkeys[1]==1) ? 5'b00001 : 5'b00000;

  always @ (posedge clk, posedge reset) begin
    if (reset == 1'b01) begin
      deloot <= 2'b00;
    end
    else begin
      deloot <= (deloot << 1) | keyclk;
    end
  end

endmodule

The Yosys version used was Yosys 0.9+932 (git sha1 3c6a566d, gcc 6.3.0-18+deb9u1 -fPIC -Os).

The command used was yosys -p "read_verilog test.v; synth_ice40 -top top; write_verilog struct_test.v"

We use the generated struct_test.v file to be able to perform gate level simulation of the code using CVC.

Expected behavior

We expected the compiler to load the file test.v, synthesize it with the ice40 scripts, then write it back out as a synthesized Verilog file called struct_test.v.

Actual behavior

The following output is produced:

2.19.14. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \top..

2.19.15. Executing OPT_EXPR pass (perform const folding).
Optimizing module top.

2.19.16. Finished OPT passes. (There is nothing left to do.)

2.20. Executing FSM pass (extract and optimize FSM).

2.20.1. Executing FSM_DETECT pass (finding FSMs in design).
Found FSM state register top.op.

2.20.2. Executing FSM_EXTRACT pass (extracting FSM from design).
Extracting FSM `\op' from module `\top'.
  found $adff cell for state register: $procdff$163
  root of input selection tree: $0\op[4:0]
  found reset state: 5'00000 (from async reset)
  found ctrl input: $eq$test.v:97$28_Y
  found ctrl input: \key [4]
  found ctrl input: \equalpressed
  found ctrl input: \pb [19]
  found ctrl input: \pb [18]
  found ctrl input: \pb [17]
  found ctrl input: \pb [16]
  found ctrl input: \pb [15]
  found ctrl input: \pb [9]
  found ctrl input: \pb [8]
  found ctrl input: \pb [7]
  found ctrl input: \pb [6]
  found ctrl input: \pb [5]
  found ctrl input: \pb [4]
  found ctrl input: \pb [3]
  found ctrl input: \pb [2]
  found ctrl input: \pb [1]
  found state code: 5'00001
  found state code: 5'00010
  found state code: 5'00011
  found state code: 5'00100
  found state code: 5'00101
  found state code: 5'00110
  found state code: 5'00111
  found state code: 5'01000
  found state code: 5'01001
  found state code: 5'01111
  found state code: 5'10000
  found state code: 5'10001
  found state code: 5'10010
  found state code: 5'10011
  found ctrl output: $eq$test.v:56$13_Y
  found ctrl output: $eq$test.v:57$14_Y
  found ctrl output: $eq$test.v:58$15_Y
  ctrl inputs: { $eq$test.v:97$28_Y \key [4] \equalpressed \pb [19:15] \pb [9:1] }
  ctrl outputs: { $0\op[4:0] $eq$test.v:58$15_Y $eq$test.v:57$14_Y $eq$test.v:56$13_Y }
  transition:    5'00000 17'000-------------- ->    5'00000 8'00000001
  transition:    5'00000 17'001-------------- ->    5'00000 8'00000001
  transition:    5'00000 17'01--------------- ->    5'00000 8'00000001
  transition:    5'00000 17'10-00000000000000 ->    5'00000 8'00000001
  transition:    5'00000 17'10-00000000000001 ->    5'00001 8'00001001
  transition:    5'00000 17'10-0000000000001- ->    5'00010 8'00010001
  transition:    5'00000 17'10-000000000001-- ->    5'00011 8'00011001
  transition:    5'00000 17'10-00000000001--- ->    5'00100 8'00100001
  transition:    5'00000 17'10-0000000001---- ->    5'00101 8'00101001
  transition:    5'00000 17'10-000000001----- ->    5'00110 8'00110001
  transition:    5'00000 17'10-00000001------ ->    5'00111 8'00111001
  transition:    5'00000 17'10-0000001------- ->    5'01000 8'01000001
  transition:    5'00000 17'10-000001-------- ->    5'01001 8'01001001
  transition:    5'00000 17'10-00001--------- ->    5'01111 8'01111001
ERROR: Assert `current_val[i].wire != NULL || current_val[i] == value.bits[i]' failed in ./kernel/consteval.h:79.
Ravenslofty commented 4 years ago

Minimised test case: using 1479.tar.gz, run yosys -p "fsm" 1479.il.

Unrelated to the bug, but I suggest you use synth_ice40's -abc9 option to improve performance.

mwkmwkmwk commented 4 years ago

Another testcase, with a different pass:

module \top
  wire input 1 \A
  wire output 2 \Y
  cell $_AND_ \sub
    connect \A \A
    connect \B 1'0
    connect \Y \Y
  end
end

Blows up on extract_fa

mwkmwkmwk commented 4 years ago

Nevermind, it's an unrelated bug...

norandomtechie commented 4 years ago

I did try the abc9 option you specified, as "synth_ice40 -abc9 -top top", but it made no difference. It also had an error with another design, so I will have to hold off on using that option.

We think we may have fixed it by synchronizing outkey in the scankey module above to the given clock. Currently, outkey is assigned combinationally, but if we change the module to do the following:

module scankey (clk, reset, inkeys, strobe, outkey);
  input clk, reset;
  input [19:0] inkeys;
  output strobe;
  output reg [4:0] outkey;

  wire [4:0] next_outkey;

  reg [2:0] delay;
  always @(posedge clk, posedge reset)
  if (reset) begin
    delay <= 0;
    outkey <= 0;
  end
  else begin
    delay <= delay << 1 | |inkeys;
    outkey <= next_outkey;
  end

  assign strobe = delay[2];
  assign next_outkey = inkeys [19] ? 5'd19 :
                       inkeys [18] ? 5'd18 :
                       inkeys [17] ? 5'd17 :
                       inkeys [16] ? 5'd16 :
                       inkeys [15] ? 5'd15 :
                       inkeys [14] ? 5'd14 :
                       inkeys [13] ? 5'd13 :
                       inkeys [12] ? 5'd12 :
                       inkeys [11] ? 5'd11 :
                       inkeys [10] ? 5'd10 :
                       inkeys [ 9] ? 5'd9  :
                       inkeys [ 8] ? 5'd8  :
                       inkeys [ 7] ? 5'd7  :
                       inkeys [ 6] ? 5'd6  :
                       inkeys [ 5] ? 5'd5  :
                       inkeys [ 4] ? 5'd4  :
                       inkeys [ 3] ? 5'd3  :
                       inkeys [ 2] ? 5'd2  :
                       inkeys [ 1] ? 5'd1  : 5'd0;
endmodule

Then it works just fine. However, I still think this is a bug, because the design theoretically should still work, regardless of having it synchronized to the clock domain or not.

Ravenslofty commented 4 years ago

This is undoubtedly a bug; compiler crashes are always bugs.

Your ABC9 error is weird; it generally produces better synthesis results than the default, which is why I recommended it. However without further information it's not really possible to diagnose it further.

On Tue, 12 Nov 2019, 13:59 Niraj Menon, notifications@github.com wrote:

I did try the abc9 option you specified, as "synth_ice40 -abc9 -top top", but it made no difference. It also had an error with another design, so I will have to hold off on using that option.

We think we may have fixed it by synchronizing outkey in the scankey module above to the given clock. Currently, outkey is assigned combinationally, but if we change the module to do the following:

module scankey (clk, reset, inkeys, strobe, outkey); input clk, reset; input [19:0] inkeys; output strobe; output reg [4:0] outkey;

wire [4:0] next_outkey;

reg [2:0] delay; always @(posedge clk, posedge reset) if (reset) begin delay <= 0; outkey <= 0; end else begin delay <= delay << 1 | |inkeys; outkey <= next_outkey; end

assign strobe = delay[2]; assign next_outkey = inkeys [19] ? 5'd19 : inkeys [18] ? 5'd18 : inkeys [17] ? 5'd17 : inkeys [16] ? 5'd16 : inkeys [15] ? 5'd15 : inkeys [14] ? 5'd14 : inkeys [13] ? 5'd13 : inkeys [12] ? 5'd12 : inkeys [11] ? 5'd11 : inkeys [10] ? 5'd10 : inkeys [ 9] ? 5'd9 : inkeys [ 8] ? 5'd8 : inkeys [ 7] ? 5'd7 : inkeys [ 6] ? 5'd6 : inkeys [ 5] ? 5'd5 : inkeys [ 4] ? 5'd4 : inkeys [ 3] ? 5'd3 : inkeys [ 2] ? 5'd2 : inkeys [ 1] ? 5'd1 : 5'd0; endmodule

Then it works just fine. However, I still think this is a bug, because the design theoretically should still work, regardless of having it synchronized to the clock domain or not.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/YosysHQ/yosys/issues/1479?email_source=notifications&email_token=AALPDW3BLWIVLVB5TJTK2WTQTKZD3A5CNFSM4JKLIZR2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOED2KQLQ#issuecomment-552904750, or unsubscribe https://github.com/notifications/unsubscribe-auth/AALPDWZ3PYFJ253BRWFZ7DLQTKZD3ANCNFSM4JKLIZRQ .

Rodrigodd commented 6 months ago

Stumble on the same assert. Was able to minimize my code by hand to the following:

module test(input a, b, output c);
assign c = a ? 1 : 0;
assign c = b ? 1 : 0;
endmodule

Errors when I try to use eval -table:

$ yosys -p 'read_verilog test.v; eval -table a -table b'

 Yosys 0.38 (git sha1 543faed9c, gcc 13.2.1 -march=x86-64 -mtune=generic -O2 -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -ffile-prefix-map=/build/yosys/src=/usr/src/debug/yosys -fPIC -Os)

-- Running command `read_verilog test.v; eval -table a -table b' --

1. Executing Verilog-2005 frontend: test.v
Parsing Verilog input from `test.v' to AST representation.
Generating RTLIL representation for module `\test'.
Successfully finished Verilog frontend.

2. Executing EVAL pass (evaluate the circuit given an input).
ERROR: Assert `current_val[i].wire != NULL || current_val[i] == value.bits[i]' failed in ./kernel/consteval.h:79.

But if I try:

module test(input a, b, output c);
assign c = a ? 1 : 0;
assign c = b;
endmodule

It works:

$ yosys -p 'read_verilog test.v; eval -table a -table b'

 Yosys 0.38 (git sha1 543faed9c, gcc 13.2.1 -march=x86-64 -mtune=generic -O2 -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -ffile-prefix-map=/build/yosys/src=/usr/src/debug/yosys -fPIC -Os)

-- Running command `read_verilog test.v; eval -table a -table b' --

1. Executing Verilog-2005 frontend: test.v
Parsing Verilog input from `test.v' to AST representation.
Generating RTLIL representation for module `\test'.
Successfully finished Verilog frontend.

2. Executing EVAL pass (evaluate the circuit given an input).

  \b  \a |  \c
 --- --- | ---
 1'0 1'0 | 1'0
 1'0 1'1 | 1'0
 1'1 1'0 | 1'1
 1'1 1'1 | 1'1

End of script. Logfile hash: ace15c8f0e, CPU: user 0.02s system 0.00s, MEM: 20.82 MB peak
Yosys 0.38 (git sha1 543faed9c, gcc 13.2.1 -march=x86-64 -mtune=generic -O2 -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -ffile-prefix-map=/build/yosys/src=/usr/src/debug/yosys -fPIC -Os)
Time spent: 51% 1x eval (0 sec), 48% 2x read_verilog (0 sec)