Skip to content

Commit

Permalink
CI - Run RTL elaboration (using ghdl, verilator) during tests, add SV…
Browse files Browse the repository at this point in the history
… tests
  • Loading branch information
stefanlippuner committed Nov 4, 2023
1 parent 92413bc commit ac97a96
Show file tree
Hide file tree
Showing 90 changed files with 16,501 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v4

- name: Install Tools
run: sudo apt-get install ghdl verilator

- name: Setup Python venv
run: |
python3 -m venv .venv
Expand Down
23 changes: 23 additions & 0 deletions proto/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ def test_hdl_ref():
print('test hdl with ref: {}'.format(f))
cheby_file = srcdir + f + '.cheby'
vhdl_file = srcdir + f + '.vhdl'
sv_file = srcdir + f + '.sv'
t = parse_ok(cheby_file)
layout_ok(t)
expand_hdl.expand_hdl(t)
Expand All @@ -398,8 +399,25 @@ def test_hdl_ref():
print_vhdl.print_vhdl(buf, h)
if not compare_buffer_and_file(buf, vhdl_file):
error('vhdl generation error for {}'.format(f))
buf_sv = write_buffer()
print_verilog.print_verilog(buf_sv, h)
if not compare_buffer_and_file(buf_sv, sv_file):
error('SV generation error for {}'.format(f))
nbr_tests += 1

# Elaboration tests
top_entity = t.hdl_module_name

vhdl_pkgs = [srcdir + 'tb/cheby_pkg.vhd', srcdir + 'tb/wishbone_pkg.vhd']
res = subprocess.run(['ghdl', '-s'] + vhdl_pkgs + [vhdl_file])
if res.returncode != 0:
error('VHDL elaboration failed for {}'.format(f))

sv_pkgs = [srcdir + 'tb/dpssram.sv', srcdir + 'tb/wishbone_pkg.sv']
res = subprocess.run(['verilator', '--lint-only', '--top', top_entity] + sv_pkgs + [sv_file])
if res.returncode != 0:
error('SV elaboration failed for {}'.format(f))

def test_verilog_ref():
# Generate verilog and compare with a baseline.
global nbr_tests
Expand All @@ -426,6 +444,7 @@ def test_issue84():
print('test hdl with ref: {}'.format(f))
cheby_file = srcdir + f + '.cheby'
vhdl_file = srcdir + f + '.vhdl'
sv_file = srcdir + f + '.sv'
t = parse_ok(cheby_file)
layout_ok(t)
expand_hdl.expand_hdl(t)
Expand All @@ -435,6 +454,10 @@ def test_issue84():
print_vhdl.print_vhdl(buf, h)
if not compare_buffer_and_file(buf, vhdl_file):
error('vhdl generation error for {}'.format(f))
buf_sv = write_buffer()
print_verilog.print_verilog(buf_sv, h)
if not compare_buffer_and_file(buf_sv, sv_file):
error('SV generation error for {}'.format(f))
nbr_tests += 1

def test_self():
Expand Down
165 changes: 165 additions & 0 deletions testfiles/bug-cernbe/repro.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@

module example
(
input wire Clk,
input wire Rst,
input wire [2:1] VMEAddr,
output reg [15:0] VMERdData,
input wire [15:0] VMEWrData,
input wire VMERdMem,
input wire VMEWrMem,
output wire VMERdDone,
output wire VMEWrDone,

// The first register (with some fields)
output wire [31:0] regA_o,

// CERN-BE bus sm
output reg [1:1] sm_VMEAddr_o,
input wire [15:0] sm_VMERdData_i,
output wire [15:0] sm_VMEWrData_o,
output reg sm_VMERdMem_o,
output wire sm_VMEWrMem_o,
input wire sm_VMERdDone_i,
input wire sm_VMEWrDone_i
);
wire rst_n;
reg rd_ack_int;
reg wr_ack_int;
reg [31:0] regA_reg;
reg [1:0] regA_wreq;
reg [1:0] regA_wack;
reg rd_ack_d0;
reg [15:0] rd_dat_d0;
reg wr_req_d0;
reg [2:1] wr_adr_d0;
reg [15:0] wr_dat_d0;
reg sm_ws;
reg sm_wt;
assign rst_n = ~Rst;
assign VMERdDone = rd_ack_int;
assign VMEWrDone = wr_ack_int;

// pipelining for wr-in+rd-out
always @(posedge(Clk) or negedge(rst_n))
begin
if (!rst_n)
begin
rd_ack_int <= 1'b0;
wr_req_d0 <= 1'b0;
end
else
begin
rd_ack_int <= rd_ack_d0;
VMERdData <= rd_dat_d0;
wr_req_d0 <= VMEWrMem;
wr_adr_d0 <= VMEAddr;
wr_dat_d0 <= VMEWrData;
end
end

// Register regA
assign regA_o = regA_reg;
always @(posedge(Clk) or negedge(rst_n))
begin
if (!rst_n)
begin
regA_reg <= 32'b00000000000000000000000000000000;
regA_wack <= 2'b0;
end
else
begin
if (regA_wreq[0] == 1'b1)
regA_reg[15:0] <= wr_dat_d0;
if (regA_wreq[1] == 1'b1)
regA_reg[31:16] <= wr_dat_d0;
regA_wack <= regA_wreq;
end
end

// Interface sm
assign sm_VMEWrData_o = wr_dat_d0;
always @(posedge(Clk) or negedge(rst_n))
begin
if (!rst_n)
sm_wt <= 1'b0;
else
sm_wt <= (sm_wt | sm_ws) & ~sm_VMEWrDone_i;
end
assign sm_VMEWrMem_o = sm_ws;
always @(VMEAddr, wr_adr_d0, sm_wt, sm_ws)
if ((sm_ws | sm_wt) == 1'b1)
sm_VMEAddr_o <= wr_adr_d0[1:1];
else
sm_VMEAddr_o <= VMEAddr[1:1];

// Process for write requests.
always @(wr_adr_d0, wr_req_d0, regA_wack, sm_VMEWrDone_i)
begin
regA_wreq <= 2'b0;
sm_ws <= 1'b0;
case (wr_adr_d0[2:2])
1'b0:
case (wr_adr_d0[1:1])
1'b0:
begin
// Reg regA
regA_wreq[1] <= wr_req_d0;
wr_ack_int <= regA_wack[1];
end
1'b1:
begin
// Reg regA
regA_wreq[0] <= wr_req_d0;
wr_ack_int <= regA_wack[0];
end
default:
wr_ack_int <= wr_req_d0;
endcase
1'b1:
begin
// Submap sm
sm_ws <= wr_req_d0;
wr_ack_int <= sm_VMEWrDone_i;
end
default:
wr_ack_int <= wr_req_d0;
endcase
end

// Process for read requests.
always @(VMEAddr, VMERdMem, regA_reg, sm_VMERdData_i, sm_VMERdDone_i)
begin
// By default ack read requests
rd_dat_d0 <= {16{1'bx}};
sm_VMERdMem_o <= 1'b0;
case (VMEAddr[2:2])
1'b0:
case (VMEAddr[1:1])
1'b0:
begin
// Reg regA
rd_ack_d0 <= VMERdMem;
rd_dat_d0 <= regA_reg[31:16];
end
1'b1:
begin
// Reg regA
rd_ack_d0 <= VMERdMem;
rd_dat_d0 <= regA_reg[15:0];
end
default:
rd_ack_d0 <= VMERdMem;
endcase
1'b1:
begin
// Submap sm
sm_VMERdMem_o <= VMERdMem;
rd_dat_d0 <= sm_VMERdData_i;
rd_ack_d0 <= sm_VMERdDone_i;
end
default:
rd_ack_d0 <= VMERdMem;
endcase
end
endmodule
113 changes: 113 additions & 0 deletions testfiles/bug-cernbe/sub_repro.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@

module sub_repro
(
input wire Clk,
input wire Rst,
input wire [1:1] VMEAddr,
output reg [15:0] VMERdData,
input wire [15:0] VMEWrData,
input wire VMERdMem,
input wire VMEWrMem,
output wire VMERdDone,
output wire VMEWrDone,

// The first register (with some fields)
output wire [15:0] subrA_o,

// The first register (with some fields)
input wire [15:0] subrB_i
);
wire rst_n;
reg rd_ack_int;
reg wr_ack_int;
reg [15:0] subrA_reg;
reg subrA_wreq;
reg subrA_wack;
reg rd_ack_d0;
reg [15:0] rd_dat_d0;
reg wr_req_d0;
reg [1:1] wr_adr_d0;
reg [15:0] wr_dat_d0;
assign rst_n = ~Rst;
assign VMERdDone = rd_ack_int;
assign VMEWrDone = wr_ack_int;

// pipelining for wr-in+rd-out
always @(posedge(Clk) or negedge(rst_n))
begin
if (!rst_n)
begin
rd_ack_int <= 1'b0;
wr_req_d0 <= 1'b0;
end
else
begin
rd_ack_int <= rd_ack_d0;
VMERdData <= rd_dat_d0;
wr_req_d0 <= VMEWrMem;
wr_adr_d0 <= VMEAddr;
wr_dat_d0 <= VMEWrData;
end
end

// Register subrA
assign subrA_o = subrA_reg;
always @(posedge(Clk) or negedge(rst_n))
begin
if (!rst_n)
begin
subrA_reg <= 16'b0000000000000000;
subrA_wack <= 1'b0;
end
else
begin
if (subrA_wreq == 1'b1)
subrA_reg <= wr_dat_d0;
subrA_wack <= subrA_wreq;
end
end

// Register subrB

// Process for write requests.
always @(wr_adr_d0, wr_req_d0, subrA_wack)
begin
subrA_wreq <= 1'b0;
case (wr_adr_d0[1:1])
1'b0:
begin
// Reg subrA
subrA_wreq <= wr_req_d0;
wr_ack_int <= subrA_wack;
end
1'b1:
// Reg subrB
wr_ack_int <= wr_req_d0;
default:
wr_ack_int <= wr_req_d0;
endcase
end

// Process for read requests.
always @(VMEAddr, VMERdMem, subrA_reg, subrB_i)
begin
// By default ack read requests
rd_dat_d0 <= {16{1'bx}};
case (VMEAddr[1:1])
1'b0:
begin
// Reg subrA
rd_ack_d0 <= VMERdMem;
rd_dat_d0 <= subrA_reg;
end
1'b1:
begin
// Reg subrB
rd_ack_d0 <= VMERdMem;
rd_dat_d0 <= subrB_i;
end
default:
rd_ack_d0 <= VMERdMem;
endcase
end
endmodule
Loading

0 comments on commit ac97a96

Please sign in to comment.