diff --git a/.dockerignore b/.dockerignore
index 8801107ae..93af49793 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -3,4 +3,21 @@
# Allow files and directories
!/.github/**
-!/*.*
\ No newline at end of file
+!/*.*
+!/abc/abc
+!/abc/libabc.a
+!/ace2/ace
+!/ace2/libace.a
+!/openfpga/libopenfpga.a
+!/openfpga/openfpga
+!/vpr/libvpr.a
+!/vpr/vpr
+!/yosys/share/
+!/yosys/yosys
+!/yosys/yosys-abc
+!/yosys/yosys-config
+!/yosys/yosys-filterlib
+!/yosys/yosys-smtbmc
+!/openfpga_flow
+!/openfpga.sh
+!/openfpga_flow/
diff --git a/.github/workflows/basic_reg_test.sh b/.github/workflows/basic_reg_test.sh
index 9d55c6e85..39ec5ad39 100755
--- a/.github/workflows/basic_reg_test.sh
+++ b/.github/workflows/basic_reg_test.sh
@@ -90,6 +90,8 @@ echo -e "Testing K4N4 without local routing architecture";
run-task basic_tests/k4_series/k4n4_no_local_routing --debug --show_thread_logs
echo -e "Testing K4N4 with block RAM";
run-task basic_tests/k4_series/k4n4_bram --debug --show_thread_logs
+echo -e "Testing K4N4 with LUTRAM";
+run-task basic_tests/k4_series/k4n4_lutram --debug --show_thread_logs
echo -e "Testing K4N4 with multiple lengths of routing segments";
run-task basic_tests/k4_series/k4n4_L124 --debug --show_thread_logs
echo -e "Testing K4N4 with 32-bit fracturable multiplier";
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index cee8938ff..079e286e5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -21,7 +21,8 @@ jobs:
runs-on: ubuntu-18.04
outputs:
# this is output as string, see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idoutputs
- source_modified: ${{ steps.changes.outputs.status_code == '0' }}
+ source_modified: ${{ steps.changes.outputs.status_code == '1' }}
+ force_upload: false
steps:
- name: Checkout OpenFPGA repo
uses: actions/checkout@v2
@@ -31,6 +32,7 @@ jobs:
- name: Check for source code changes
id: changes
run: |
+ git diff origin/master HEAD --name-status -- . ':!openfpga_flow' ':!docs'
if git diff origin/master HEAD --name-status --exit-code -- . ':!openfpga_flow' ':!docs'; then
echo "::set-output name=status_code::0"
else
@@ -159,7 +161,7 @@ jobs:
openfpga.sh
docker_distribution:
name: Build docker image for distribution
- if: ${{ github.ref == 'refs/heads/master' }}
+ if: ${{ github.ref == 'refs/heads/master' || fromJSON(needs.change_detect.outputs.force_upload) }}
runs-on: ubuntu-latest
needs: linux_build
steps:
@@ -169,6 +171,9 @@ jobs:
uses: actions/download-artifact@v2
with:
name: openfpga
+ - name: Update dockerignore to add openfpga_flow
+ run: |
+ cat .dockerignore
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
diff --git a/docker/Dockerfile.master b/docker/Dockerfile.master
index 866f8b51b..872ce07a8 100644
--- a/docker/Dockerfile.master
+++ b/docker/Dockerfile.master
@@ -1,14 +1,9 @@
FROM ghcr.io/lnis-uofu/openfpga-env
-RUN mkdir /opt/openfpga /opt/openfpga/openfpga /opt/openfpga/abc /opt/openfpga/ace2 /opt/openfpga/vpr /opt/openfpga/yosys
-COPY openfpga/openfpga /opt/openfpga/openfpga/openfpga
-COPY abc/abc /opt/openfpga/abc/
-COPY ace2/ace /opt/openfpga/ace2/
-COPY vpr/vpr /opt/openfpga/vpr/
-COPY yosys/yosys yosys/yosys-abc yosys/yosys-config yosys/yosys-filterlib yosys/yosys-smtbmc /opt/openfpga/yosys/
-COPY yosys/share /opt/openfpga/yosys/share
-RUN cd /opt/openfpga && chmod +x abc/abc ace2/ace openfpga/openfpga vpr/vpr yosys/yosys yosys/yosys-abc yosys/yosys-config yosys/yosys-filterlib yosys/yosys-smtbmc
-COPY openfpga_flow /opt/openfpga/openfpga_flow
-COPY openfpga.sh /opt/openfpga/openfpga.sh
-ENV PATH="/opt/openfpga/openfpga:/opt/openfpga/yosys:/opt/openfpga/ace2:/opt/openfpga/abc:/opt/openfpga/vpr:${PATH}"
-ENV OPENFPGA_PATH="/opt/openfpga"
+RUN mkdir -p /opt/openfpga
WORKDIR /opt/openfpga
+COPY . /opt/openfpga
+RUN chmod +x abc/abc ace2/ace openfpga/openfpga vpr/vpr
+RUN chmod +x yosys/yosys yosys/yosys-abc yosys/yosys-config yosys/yosys-filterlib yosys/yosys-smtbmc
+ENV PATH="/opt/openfpga/openfpga:/opt/openfpga/yosys:${PATH}"
+ENV PATH="/opt/openfpga/ace2:/opt/openfpga/abc:/opt/openfpga/vpr:${PATH}"
+ENV OPENFPGA_PATH="/opt/openfpga"
diff --git a/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.act b/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.act
new file mode 100644
index 000000000..a6bcf46f1
--- /dev/null
+++ b/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.act
@@ -0,0 +1,7 @@
+clk 0.5 0.5
+addr_0 0.5 0.2
+addr_1 0.5 0.2
+d_in 0.5 0.2
+wr_en 0.5 0.2
+int 0.5 0.2
+d_out 0.25 0.25
diff --git a/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.blif b/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.blif
new file mode 100644
index 000000000..8e5976769
--- /dev/null
+++ b/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.blif
@@ -0,0 +1,16 @@
+.model asyn_spram_4x1
+.inputs clk addr_0 addr_1 d_in wr_en
+.outputs d_out
+
+.subckt spram_4x1 clk=clk addr[0]=addr_0 addr[1]=addr_1 d_in=d_in wr_en=wr_en d_out=int
+
+.names int d_out
+1 1
+
+.end
+
+.model spram_4x1
+.blackbox
+.inputs clk addr[0] addr[1] d_in wr_en
+.outputs d_out
+.end
diff --git a/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.v b/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.v
new file mode 100644
index 000000000..ec5135524
--- /dev/null
+++ b/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.v
@@ -0,0 +1,36 @@
+/////////////////////////////////////////
+// Functionality: 4x1 memory async read
+// Author: Aurelien Alacchi
+////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module asyn_spram_4x1(
+ clk,
+ addr_0,
+ addr_1,
+ d_in,
+ wr_en,
+ d_out );
+
+ input wire clk;
+ input wire addr_0;
+ input wire addr_1;
+ input wire d_in;
+ input wire wr_en;
+ output wire d_out;
+
+ wire[1:0] addr;
+ reg [3:0] mem;
+
+ assign addr = {addr_1, addr_0};
+ assign d_out = (addr == 2'd0)? mem[0]:
+ (addr == 2'd1)? mem[1]:
+ (addr == 2'd2)? mem[2]: mem[3];
+
+ always@(posedge clk) begin
+ if(wr_en) begin
+ mem[addr] <= d_in;
+ end
+ end
+
+endmodule
diff --git a/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.act b/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.act
new file mode 100644
index 000000000..8918ab714
--- /dev/null
+++ b/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.act
@@ -0,0 +1,7 @@
+clk 0.5 0.5
+addr_0 0.5 0.2
+addr_1 0.5 0.2
+d_in 0.5 0.2
+wr_en 0.5 0.2
+int 0.5 0.2
+d_out 0.25 0.25
diff --git a/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.blif b/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.blif
new file mode 100644
index 000000000..37e6cf8d0
--- /dev/null
+++ b/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.blif
@@ -0,0 +1,16 @@
+.model syn_spram_4x1
+.inputs clk addr_0 addr_1 d_in wr_en
+.outputs d_out
+
+.subckt spram_4x1 clk=clk addr[0]=addr_0 addr[1]=addr_1 d_in=d_in wr_en=wr_en d_out=int
+
+.latch int d_out re clk 0
+
+
+.end
+
+.model spram_4x1
+.blackbox
+.inputs clk addr[0] addr[1] d_in wr_en
+.outputs d_out
+.end
diff --git a/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.v b/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.v
new file mode 100644
index 000000000..2816a3c16
--- /dev/null
+++ b/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.v
@@ -0,0 +1,38 @@
+/////////////////////////////////////////
+// Functionality: 4x1 memory async read
+// Author: Aurelien Alacchi
+////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module syn_spram_4x1(
+ clk,
+ addr_0,
+ addr_1,
+ d_in,
+ wr_en,
+ d_out );
+
+ input wire clk;
+ input wire addr_0;
+ input wire addr_1;
+ input wire d_in;
+ input wire wr_en;
+ output reg d_out;
+
+ wire[1:0] addr;
+ wire tmp;
+ reg [3:0] mem;
+
+ assign addr = {addr_1, addr_0};
+ assign tmp = (addr == 2'd0)? mem[0]:
+ (addr == 2'd1)? mem[1]:
+ (addr == 2'd2)? mem[2]: mem[3];
+
+ always@(posedge clk) begin
+ if(wr_en) begin
+ mem[addr] <= d_in;
+ end
+ d_out <= tmp;
+ end
+
+endmodule
diff --git a/openfpga_flow/openfpga_arch/k4_frac_N4_lutram_40nm_cc_openfpga.xml b/openfpga_flow/openfpga_arch/k4_frac_N4_lutram_40nm_cc_openfpga.xml
new file mode 100644
index 000000000..788ddca27
--- /dev/null
+++ b/openfpga_flow/openfpga_arch/k4_frac_N4_lutram_40nm_cc_openfpga.xml
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+ 10e-12
+
+
+ 10e-12
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 5e-12
+
+
+ 10e-12 5e-12
+
+
+
+
+
+
+
+
+
+
+
+
+ 10e-12 5e-12 5e-12
+
+
+ 10e-12 5e-12 5e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openfpga_flow/openfpga_cell_library/verilog/spram_4x1.v b/openfpga_flow/openfpga_cell_library/verilog/spram_4x1.v
new file mode 100644
index 000000000..46d2c5530
--- /dev/null
+++ b/openfpga_flow/openfpga_cell_library/verilog/spram_4x1.v
@@ -0,0 +1,21 @@
+// SPRAM 4x1 for implementation in LUT4-RAM
+// Asynchronous reading
+
+module spram_4x1 (
+ input clk,
+ input[1:0] addr,
+ input d_in,
+ input wr_en,
+ output d_out );
+
+ reg[3:0] mem;
+
+ assign d_out = mem[addr];
+
+ always @(posedge clk) begin
+ if(wr_en) begin
+ mem[addr] <= d_in;
+ end
+ end
+
+endmodule
diff --git a/openfpga_flow/tasks/basic_tests/k4_series/k4n4_lutram/config/task.conf b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_lutram/config/task.conf
new file mode 100644
index 000000000..6e6aa0750
--- /dev/null
+++ b/openfpga_flow/tasks/basic_tests/k4_series/k4n4_lutram/config/task.conf
@@ -0,0 +1,45 @@
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# Configuration file for running experiments
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
+# Each job execute fpga_flow script on combination of architecture & benchmark
+# timeout_each_job is timeout for each job
+# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
+
+[GENERAL]
+run_engine=openfpga_shell
+power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
+power_analysis = true
+spice_output=false
+verilog_output=true
+timeout_each_job = 20*60
+fpga_flow=vpr_blif
+
+[OpenFPGA_SHELL]
+openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_script.openfpga
+openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_frac_N4_lutram_40nm_cc_openfpga.xml
+openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
+
+[ARCHITECTURES]
+arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_frac_N4_tileable_lutram_40nm.xml
+
+[BENCHMARKS]
+#
+bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_or2/and2_or2.blif
+bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.blif
+bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.blif
+
+[SYNTHESIS_PARAM]
+bench0_top = and2_or2
+bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_or2/and2_or2.act
+bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_or2/and2_or2.v
+bench1_top = asyn_spram_4x1
+bench1_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.act
+bench1_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/asyn_spram_4x1/asyn_spram_4x1.v
+bench2_top = syn_spram_4x1
+bench2_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.act
+bench2_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/syn_spram_4x1/syn_spram_4x1.v
+
+[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
+end_flow_with_test=
+vpr_fpga_verilog_formal_verification_top_netlist=
diff --git a/openfpga_flow/vpr_arch/k4_frac_N4_tileable_lutram_40nm.xml b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_lutram_40nm.xml
new file mode 100644
index 000000000..ce31cc671
--- /dev/null
+++ b/openfpga_flow/vpr_arch/k4_frac_N4_tileable_lutram_40nm.xml
@@ -0,0 +1,539 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+ io.outpad io.inpad
+
+
+
+
+
+
+
+
+
+
+
+
+ clb.clk
+
+ clb.O[3:0] clb.I[5:0]
+ clb.O[7:4] clb.I[11:6]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1 1 1 1 1
+ 1 1 1 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 235e-12
+ 235e-12
+ 235e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 261e-12
+ 261e-12
+ 261e-12
+ 261e-12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+