Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ jobs:
cmake -S . -B build -D YOSYS_PATH="$HOME/.local"
cmake --build build
cmake --install build
- name: Run tests
run: |
export PATH="$HOME/.local/bin:$PATH"
cd build && ctest --output-on-failure
- name: Pack build
shell: bash
run: |
Expand Down
18 changes: 15 additions & 3 deletions architecture/z1010/dsp/zeroasic_dsp.pmg
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pattern zeroasic_dsp_pack
state <SigBit> clock
// A, B: * inputs. C: 3rd input (to adder). D: input to adder (could be same as C)
state <SigSpec> sigA sigB sigC sigD sigP sigMultOut
state <Cell*> ffA ffB ffC ffP
state <Cell*> ffA ffB ffC ffP ffMult
state <Cell*> postAdderStatic
state <bool> useFeedBack multHasReg

Expand Down Expand Up @@ -82,14 +82,19 @@ code sigA sigB sigC sigD clock sigP sigMultOut
endcode

// detect if multiplier output is registered (useful for discerning macc vs macc_pipe)
code argD sigMultOut multHasReg
code argD sigMultOut multHasReg ffMult sigP clock
sigMultOut = sigP; // sigP moves around, we want to keep track of multiplier output.
ffMult = nullptr;
if (nusers(sigP) == 2) {
argD = sigMultOut;
allowAsync = false;
subpattern(out_dffe);
if (dff) {
multHasReg = true;
ffMult = dff;
clock = dffclock;
sigP = dffQ; // advance past the pipeline register so postAddMatching
// searches from the correct node
}
}

Expand All @@ -105,7 +110,7 @@ endcode

// post adder
// sigD will be absorbed.
code postAdderStatic sigP sigD sigC
code postAdderStatic sigP sigD sigC multHasReg ffMult
u_postAdderStatic = nullptr;
subpattern(postAddMatching);
postAdderStatic = u_postAdderStatic;
Expand All @@ -116,6 +121,13 @@ code postAdderStatic sigP sigD sigC
sigD = port(postAdderStatic, u_postAddAB == \A ? \B : \A);
sigC = sigD;
sigP = port(postAdderStatic, \Y);
} else if (multHasReg) {
// No post-adder found downstream of the pipeline-register candidate.
// The DFF on the multiplier output is a plain output register, not a
// pipeline register. Roll back so the P_REG block can absorb it normally.
multHasReg = false;
ffMult = nullptr;
sigP = sigMultOut;
}
endcode

Expand Down
18 changes: 15 additions & 3 deletions architecture/z1060/dsp/zeroasic_dsp.pmg
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pattern zeroasic_dsp_pack
state <SigBit> clock
// A, B: * inputs. C: 3rd input (to adder). D: input to adder (could be same as C)
state <SigSpec> sigA sigB sigC sigD sigP sigMultOut
state <Cell*> ffA ffB ffC ffP
state <Cell*> ffA ffB ffC ffP ffMult
state <Cell*> postAdderStatic
state <bool> useFeedBack multHasReg

Expand Down Expand Up @@ -82,14 +82,19 @@ code sigA sigB sigC sigD clock sigP sigMultOut
endcode

// detect if multiplier output is registered (useful for discerning macc vs macc_pipe)
code argD sigMultOut multHasReg
code argD sigMultOut multHasReg ffMult sigP clock
sigMultOut = sigP; // sigP moves around, we want to keep track of multiplier output.
ffMult = nullptr;
if (nusers(sigP) == 2) {
argD = sigMultOut;
allowAsync = false;
subpattern(out_dffe);
if (dff) {
multHasReg = true;
ffMult = dff;
clock = dffclock;
sigP = dffQ; // advance past the pipeline register so postAddMatching
// searches from the correct node
}
}

Expand All @@ -105,7 +110,7 @@ endcode

// post adder
// sigD will be absorbed.
code postAdderStatic sigP sigD sigC
code postAdderStatic sigP sigD sigC multHasReg ffMult
u_postAdderStatic = nullptr;
subpattern(postAddMatching);
postAdderStatic = u_postAdderStatic;
Expand All @@ -116,6 +121,13 @@ code postAdderStatic sigP sigD sigC
sigD = port(postAdderStatic, u_postAddAB == \A ? \B : \A);
sigC = sigD;
sigP = port(postAdderStatic, \Y);
} else if (multHasReg) {
// No post-adder found downstream of the pipeline-register candidate.
// The DFF on the multiplier output is a plain output register, not a
// pipeline register. Roll back so the P_REG block can absorb it normally.
multHasReg = false;
ffMult = nullptr;
sigP = sigMultOut;
}
endcode

Expand Down
1 change: 1 addition & 0 deletions src/zeroasic_dsp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void zeroasic_dsp_pack(zeroasic_dsp_pm &pm) {

if (st.multHasReg) {
cell->setParam(ID(MULT_HAS_REG), State::S1);
pm.autoremove(st.ffMult);
} else {
cell->setParam(ID(MULT_HAS_REG), State::S0);
}
Expand Down
24 changes: 24 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ set(ALL_TESTS
unit/heartbeat-z1010-hardcode.ys
unit/heartbeat-z1000-config-abspath.ys
unit/heartbeat-z1010-config-abspath.ys
unit/dsp/mae-techmap-efpga_mult.ys
unit/dsp/mae-techmap-efpga_mult_regi.ys
unit/dsp/mae-techmap-efpga_mult_rego.ys
unit/dsp/mae-techmap-efpga_mult_regio.ys
unit/dsp/mae-techmap-efpga_macc.ys
unit/dsp/mae-techmap-efpga_macc_regi.ys
unit/dsp/mae-techmap-efpga_macc_pipe.ys
unit/dsp/mae-techmap-efpga_macc_pipe_regi.ys
unit/dsp/mae-techmap-efpga_mult_addc.ys
unit/dsp/mae-techmap-efpga_mult_addc_regi.ys
unit/dsp/mae-techmap-efpga_mult_addc_rego.ys
unit/dsp/mae-techmap-efpga_mult_addc_regio.ys
unit/dsp/mae-techmap-efpga_mult_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_regi_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_rego_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_regio_unsigned.ys
unit/dsp/mae-techmap-efpga_macc_unsigned.ys
unit/dsp/mae-techmap-efpga_macc_regi_unsigned.ys
unit/dsp/mae-techmap-efpga_macc_pipe_unsigned.ys
unit/dsp/mae-techmap-efpga_macc_pipe_regi_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_addc_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_addc_regi_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_addc_rego_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_addc_regio_unsigned.ys
)

foreach(test_script ${ALL_TESTS})
Expand Down
33 changes: 33 additions & 0 deletions tests/unit/dsp/mae-techmap-efpga_macc.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# yosys -m wildebeest -s mae-techmap-efpga_macc.ys
read_verilog <<EOF
module efpga_macc_map_inst
# (
parameter INPUT_WIDTH = 18,
parameter OUTPUT_WIDTH = 40
)
(
input clk,
input resetn,
input signed [(INPUT_WIDTH-1):0] a,
input signed [(INPUT_WIDTH-1):0] b,
output reg [(OUTPUT_WIDTH-1):0] y
);

wire signed [(2*INPUT_WIDTH-1):0] product;

assign product = a * b;

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
y <= 'h0;
end
else begin
y <= y + product;
end
end

endmodule
EOF

synth_fpga -partname z1010
select -assert-count 1 */t:efpga_macc
40 changes: 40 additions & 0 deletions tests/unit/dsp/mae-techmap-efpga_macc_pipe.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# yosys -m wildebeest -s mae-techmap-efpga_macc_pipe.ys
read_verilog <<EOF
module efpga_macc_pipe_map_inst
# (
parameter INPUT_WIDTH = 18,
parameter OUTPUT_WIDTH = 40
)
(
input clk,
input resetn,
input signed [(INPUT_WIDTH-1):0] a,
input signed [(INPUT_WIDTH-1):0] b,
output reg [(OUTPUT_WIDTH-1):0] y
);

reg signed [(2*INPUT_WIDTH-1):0] product;

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
product <= 'h0;
end
else begin
product <= a * b;
end
end

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
y <= 'h0;
end
else begin
y <= y + product;
end
end

endmodule
EOF

synth_fpga -partname z1010
select -assert-count 1 */t:efpga_macc_pipe
54 changes: 54 additions & 0 deletions tests/unit/dsp/mae-techmap-efpga_macc_pipe_regi.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# yosys -m wildebeest -s mae-techmap-efpga_macc_pipe_regi.ys
read_verilog <<EOF
module efpga_macc_pipe_regi_map_inst
# (
parameter INPUT_WIDTH = 18,
parameter OUTPUT_WIDTH = 40
)
(
input clk,
input resetn,
input signed [(INPUT_WIDTH-1):0] a,
input signed [(INPUT_WIDTH-1):0] b,
output reg [(OUTPUT_WIDTH-1):0] y
);

reg signed [(2*INPUT_WIDTH-1):0] product;

reg signed [(INPUT_WIDTH-1):0] a_reg;
reg signed [(INPUT_WIDTH-1):0] b_reg;

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
a_reg <= 'h0;
b_reg <= 'h0;
end
else begin
a_reg <= a;
b_reg <= b;
end
end

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
product <= 'h0;
end
else begin
product <= a_reg * b_reg;
end
end

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
y <= 'h0;
end
else begin
y <= y + product;
end
end

endmodule
EOF

synth_fpga -partname z1010
select -assert-count 1 */t:efpga_macc_pipe_regi
54 changes: 54 additions & 0 deletions tests/unit/dsp/mae-techmap-efpga_macc_pipe_regi_unsigned.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# yosys -m wildebeest -s mae-techmap-efpga_macc_pipe_regi_unsigned.ys
read_verilog <<EOF
module efpga_macc_pipe_regi_unsigned_map_inst
# (
parameter INPUT_WIDTH = 17,
parameter OUTPUT_WIDTH = 40
)
(
input clk,
input resetn,
input [(INPUT_WIDTH-1):0] a,
input [(INPUT_WIDTH-1):0] b,
output reg [(OUTPUT_WIDTH-1):0] y
);

reg [(2*INPUT_WIDTH-1):0] product;

reg [(INPUT_WIDTH-1):0] a_reg;
reg [(INPUT_WIDTH-1):0] b_reg;

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
a_reg <= 'h0;
b_reg <= 'h0;
end
else begin
a_reg <= a;
b_reg <= b;
end
end

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
product <= 'h0;
end
else begin
product <= a_reg * b_reg;
end
end

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
y <= 'h0;
end
else begin
y <= y + product;
end
end

endmodule
EOF

synth_fpga -partname z1010
select -assert-count 1 */t:efpga_macc_pipe_regi
40 changes: 40 additions & 0 deletions tests/unit/dsp/mae-techmap-efpga_macc_pipe_unsigned.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# yosys -m wildebeest -s mae-techmap-efpga_macc_pipe_unsigned.ys
read_verilog <<EOF
module efpga_macc_pipe_unsigned_map_inst
# (
parameter INPUT_WIDTH = 17,
parameter OUTPUT_WIDTH = 40
)
(
input clk,
input resetn,
input [(INPUT_WIDTH-1):0] a,
input [(INPUT_WIDTH-1):0] b,
output reg [(OUTPUT_WIDTH-1):0] y
);

reg [(2*INPUT_WIDTH-1):0] product;

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
product <= 'h0;
end
else begin
product <= a * b;
end
end

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
y <= 'h0;
end
else begin
y <= y + product;
end
end

endmodule
EOF

synth_fpga -partname z1010
select -assert-count 1 */t:efpga_macc_pipe
Loading
Loading