Merge pull request #100 from lnis-uofu/arch_exploration

Added arch exploration files
This commit is contained in:
tangxifan 2021-04-06 21:55:14 -06:00 committed by GitHub
commit 77bba4ec2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 19691 additions and 5 deletions

View File

@ -0,0 +1,684 @@
<!--
Low-cost homogeneous FPGA Architecture for QLSOFA_HD.
- Skywater 130 nm technology
- General purpose logic block:
K = 4, N = 8, fracturable 4 LUTs (can operate as one 4-LUT or two 3-LUTs with all 3 inputs shared)
with optionally registered outputs
- Routing architecture:
- 10% L = 1, fc_in = 0.15, Fc_out = 0.10
- 10% L = 2, fc_in = 0.15, Fc_out = 0.10
- 80% L = 4, fc_in = 0.15, Fc_out = 0.10
- 100 routing tracks per channel
Authors: Xifan Tang
-->
<architecture>
<!--
ODIN II specific config begins
Describes the types of user-specified netlist blocks (in blif, this corresponds to
".model [type_of_block]") that this architecture supports.
Note: Basic LUTs, I/Os, and flip-flops are not included here as there are
already special structures in blif (.names, .input, .output, and .latch)
that describe them.
-->
<models>
<!-- A virtual model for I/O to be used in the physical mode of io block -->
<model name="io">
<input_ports>
<port name="outpad"/>
</input_ports>
<output_ports>
<port name="inpad"/>
</output_ports>
</model>
<model name="frac_lut4">
<input_ports>
<port name="in"/>
</input_ports>
<output_ports>
<port name="lut2_out"/>
<port name="lut3_out"/>
<port name="lut4_out"/>
</output_ports>
</model>
<model name="carry_follower">
<input_ports>
<port name="a"/>
<port name="b"/>
<port name="cin"/>
</input_ports>
<output_ports>
<port name="cout"/>
</output_ports>
</model>
<!-- A virtual model for scan-chain flip-flop to be used in the physical mode of FF -->
<model name="scff">
<input_ports>
<port name="D" clock="clk"/>
<port name="DI" clock="clk"/>
<port name="reset" clock="clk"/>
<port name="clk" is_clock="1"/>
</input_ports>
<output_ports>
<port name="Q" clock="clk"/>
</output_ports>
</model>
</models>
<tiles>
<!-- Do NOT add clock pins to I/O here!!! VPR does not build clock network in the way that OpenFPGA can support
If you need to register the I/O, define clocks in the circuit models
These clocks can be handled in back-end
-->
<!-- Top-side has 1 I/O per tile -->
<tile name="io_top" capacity="1" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="bottom">io_top.outpad io_top.inpad</loc>
</pinlocations>
</tile>
<!-- Right-side has 1 I/O per tile -->
<tile name="io_right" capacity="1" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="left">io_right.outpad io_right.inpad</loc>
</pinlocations>
</tile>
<!-- Bottom-side has 9 I/O per tile -->
<tile name="io_bottom" capacity="9" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="top">io_bottom.outpad io_bottom.inpad</loc>
</pinlocations>
</tile>
<!-- Left-side has 1 I/O per tile -->
<tile name="io_left" capacity="1" area="0">
<equivalent_sites>
<site pb_type="io"/>
</equivalent_sites>
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10"/>
<pinlocations pattern="custom">
<loc side="right">io_left.outpad io_left.inpad</loc>
</pinlocations>
</tile>
<!-- CLB has most pins on the top and right sides -->
<tile name="clb" area="53894">
<equivalent_sites>
<site pb_type="clb"/>
</equivalent_sites>
<input name="I0" num_pins="2" equivalent="full"/>
<input name="I0i" num_pins="2" equivalent="none"/>
<input name="I1" num_pins="2" equivalent="full"/>
<input name="I1i" num_pins="2" equivalent="none"/>
<input name="I2" num_pins="2" equivalent="full"/>
<input name="I2i" num_pins="2" equivalent="none"/>
<input name="I3" num_pins="2" equivalent="full"/>
<input name="I3i" num_pins="2" equivalent="none"/>
<input name="I4" num_pins="2" equivalent="full"/>
<input name="I4i" num_pins="2" equivalent="none"/>
<input name="I5" num_pins="2" equivalent="full"/>
<input name="I5i" num_pins="2" equivalent="none"/>
<input name="I6" num_pins="2" equivalent="full"/>
<input name="I6i" num_pins="2" equivalent="none"/>
<input name="I7" num_pins="2" equivalent="full"/>
<input name="I7i" num_pins="2" equivalent="none"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1" is_non_clock_global="true"/>
<output name="O" num_pins="16" equivalent="none"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<fc in_type="frac" in_val="0.15" out_type="frac" out_val="0.10">
<!-- <fc_override port_name="reg_in" fc_type="frac" fc_val="0"/> -->
<!-- <fc_override port_name="reg_out" fc_type="frac" fc_val="0"/> -->
<fc_override port_name="sc_in" fc_type="frac" fc_val="0"/>
<fc_override port_name="sc_out" fc_type="frac" fc_val="0"/>
<fc_override port_name="cin" fc_type="frac" fc_val="0"/>
<fc_override port_name="cout" fc_type="frac" fc_val="0"/>
<fc_override port_name="clk" fc_type="frac" fc_val="0"/>
<fc_override port_name="reset" fc_type="frac" fc_val="0"/>
</fc>
<!--pinlocations pattern="spread"/-->
<pinlocations pattern="custom">
<loc side="left">clb.clk clb.reset</loc>
<loc side="top">clb.reg_in clb.sc_in clb.cin clb.O[7:0] clb.I0 clb.I0i clb.I1 clb.I1i clb.I2 clb.I2i clb.I3 clb.I3i</loc>
<loc side="right">clb.O[15:8] clb.I4 clb.I4i clb.I5 clb.I5i clb.I6 clb.I6i clb.I7 clb.I7i</loc>
<loc side="bottom">clb.reg_out clb.sc_out clb.cout</loc>
</pinlocations>
</tile>
</tiles>
<!-- ODIN II specific config ends -->
<!-- Physical descriptions begin -->
<layout tileable="true">
<auto_layout aspect_ratio="1.0">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</auto_layout>
<fixed_layout name="2x2" width="4" height="4">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
<fixed_layout name="12x12" width="14" height="14">
<!--Perimeter of 'io' blocks with 'EMPTY' blocks at corners-->
<row type="io_top" starty="H-1" priority="100"/>
<row type="io_bottom" starty="0" priority="100"/>
<col type="io_left" startx="0" priority="100"/>
<col type="io_right" startx="W-1" priority="100"/>
<corners type="EMPTY" priority="101"/>
<!--Fill with 'clb'-->
<fill type="clb" priority="10"/>
</fixed_layout>
</layout>
<device>
<sizing R_minW_nmos="8926" R_minW_pmos="16067"/>
<!-- The grid_logic_tile_area below will be used for all blocks that do not explicitly set their own (non-routing)
area; set to 0 since we explicitly set the area of all blocks currently in this architecture file.
-->
<area grid_logic_tile_area="0"/>
<chan_width_distr>
<x distr="uniform" peak="1.000000"/>
<y distr="uniform" peak="1.000000"/>
</chan_width_distr>
<switch_block type="wilton" fs="3" sub_type="subset" sub_fs="3"/>
<connection_block input_switch_name="ipin_cblock"/>
</device>
<switchlist>
<switch type="mux" name="L1_mux" R="0" Cin="0" Cout="0" Tdel="${L1_SB_MUX_DELAY}" mux_trans_size="2.630740" buf_size="27.645901"/>
<switch type="mux" name="L2_mux" R="0" Cin="0" Cout="0" Tdel="${L2_SB_MUX_DELAY}" mux_trans_size="2.630740" buf_size="27.645901"/>
<switch type="mux" name="L4_mux" R="0" Cin="0" Cout="0" Tdel="${L4_SB_MUX_DELAY}" mux_trans_size="2.630740" buf_size="27.645901"/>
<!--switch ipin_cblock resistance set to yeild for 4x minimum drive strength buffer-->
<switch type="mux" name="ipin_cblock" R="0" Cout="0" Cin="0" Tdel="${CB_MUX_DELAY}" mux_trans_size="1.222260" buf_size="auto"/>
</switchlist>
<segmentlist>
<!-- GIVE a specific name for the segment! OpenFPGA appreciate that! -->
<segment name="L1" freq="0.10" length="1" type="unidir" Rmetal="${L1_WIRE_R}" Cmetal="${L1_WIRE_C}">
<mux name="L1_mux"/>
<sb type="pattern">1 1</sb>
<cb type="pattern">1</cb>
</segment>
<segment name="L2" freq="0.10" length="2" type="unidir" Rmetal="${L2_WIRE_R}" Cmetal="${L2_WIRE_C}">
<mux name="L2_mux"/>
<sb type="pattern">1 1 1</sb>
<cb type="pattern">1 1</cb>
</segment>
<segment name="L4" freq="0.80" length="4" type="unidir" Rmetal="${L4_WIRE_R}" Cmetal="${L4_WIRE_C}">
<mux name="L4_mux"/>
<sb type="pattern">1 1 1 1 1</sb>
<cb type="pattern">1 1 1 1</cb>
</segment>
</segmentlist>
<directlist>
<direct name="carry_chain" from_pin="clb.cout" to_pin="clb.cin" x_offset="0" y_offset="-1" z_offset="0"/>
<!-- <direct name="shift_register" from_pin="clb.reg_out" to_pin="clb.reg_in" x_offset="0" y_offset="-1" z_offset="0"/> -->
<direct name="scan_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0"/>
</directlist>
<complexblocklist>
<!-- Define input pads begin -->
<pb_type name="io">
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
<!-- Do NOT add clock pins to I/O here!!! VPR does not build clock network in the way that OpenFPGA can support
If you need to register the I/O, define clocks in the circuit models
These clocks can be handled in back-end
-->
<!-- A mode denotes the physical implementation of an I/O
This mode will be not packable but is mainly used for fabric verilog generation
-->
<mode name="physical" disabled_in_pack="true">
<pb_type name="iopad" blif_model=".subckt io" num_pb="1">
<input name="outpad" num_pins="1"/>
<output name="inpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="outpad" input="io.outpad" output="iopad.outpad">
<delay_constant max="${OUTPAD_DELAY}" in_port="io.outpad" out_port="iopad.outpad"/>
</direct>
<direct name="inpad" input="iopad.inpad" output="io.inpad">
<delay_constant max="${INPAD_DELAY}" in_port="iopad.inpad" out_port="io.inpad"/>
</direct>
</interconnect>
</mode>
<!-- IOs can operate as either inputs or outputs.
Delays below come from Ian Kuon. They are small, so they should be interpreted as
the delays to and from registers in the I/O (and generally I/Os are registered
today and that is when you timing analyze them.
-->
<mode name="inpad">
<pb_type name="inpad" blif_model=".input" num_pb="1">
<output name="inpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="inpad" input="inpad.inpad" output="io.inpad">
<delay_constant max="${INPAD_DELAY}" in_port="inpad.inpad" out_port="io.inpad"/>
</direct>
</interconnect>
</mode>
<mode name="outpad">
<pb_type name="outpad" blif_model=".output" num_pb="1">
<input name="outpad" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="outpad" input="io.outpad" output="outpad.outpad">
<delay_constant max="${OUTPAD_DELAY}" in_port="io.outpad" out_port="outpad.outpad"/>
</direct>
</interconnect>
</mode>
<power method="ignore"/>
</pb_type>
<!-- Define I/O pads ends -->
<!-- Define general purpose logic block (CLB) begin -->
<!-- -Due to the absence of local routing,
the 4 inputs of fracturable LUT4 are no longer equivalent,
because the 4th input can not be switched when the dual-LUT3 modes are used.
So pin equivalence should be applied to the first 3 inputs only
-->
<pb_type name="clb">
<input name="I0" num_pins="2" equivalent="full"/>
<input name="I0i" num_pins="2" equivalent="none"/>
<input name="I1" num_pins="2" equivalent="full"/>
<input name="I1i" num_pins="2" equivalent="none"/>
<input name="I2" num_pins="2" equivalent="full"/>
<input name="I2i" num_pins="2" equivalent="none"/>
<input name="I3" num_pins="2" equivalent="full"/>
<input name="I3i" num_pins="2" equivalent="none"/>
<input name="I4" num_pins="2" equivalent="full"/>
<input name="I4i" num_pins="2" equivalent="none"/>
<input name="I5" num_pins="2" equivalent="full"/>
<input name="I5i" num_pins="2" equivalent="none"/>
<input name="I6" num_pins="2" equivalent="full"/>
<input name="I6i" num_pins="2" equivalent="none"/>
<input name="I7" num_pins="2" equivalent="full"/>
<input name="I7i" num_pins="2" equivalent="none"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1" is_non_clock_global="true"/>
<output name="O" num_pins="16" equivalent="none"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Describe fracturable logic element.
Each fracturable logic element has a 6-LUT that can alternatively operate as two 5-LUTs with shared inputs.
The outputs of the fracturable logic element can be optionally registered
-->
<pb_type name="fle" num_pb="8">
<input name="in" num_pins="4"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1"/>
<output name="out" num_pins="2"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Physical mode definition begin (physical implementation of the fle) -->
<mode name="physical" disabled_in_pack="true">
<pb_type name="fabric" num_pb="1">
<input name="in" num_pins="4"/>
<input name="reg_in" num_pins="1"/>
<input name="sc_in" num_pins="1"/>
<input name="cin" num_pins="1"/>
<input name="reset" num_pins="1"/>
<output name="out" num_pins="2"/>
<output name="reg_out" num_pins="1"/>
<output name="sc_out" num_pins="1"/>
<output name="cout" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<pb_type name="frac_logic" num_pb="1">
<input name="in" num_pins="4"/>
<input name="cin" num_pins="1"/>
<output name="out" num_pins="2"/>
<output name="cout" num_pins="1"/>
<!-- Define LUT -->
<pb_type name="frac_lut4" blif_model=".subckt frac_lut4" num_pb="1">
<input name="in" num_pins="4"/>
<output name="lut2_out" num_pins="2"/>
<output name="lut3_out" num_pins="2"/>
<output name="lut4_out" num_pins="1"/>
</pb_type>
<pb_type name="carry_follower" blif_model=".subckt carry_follower" num_pb="1">
<input name="a" num_pins="1"/>
<input name="b" num_pins="1"/>
<input name="cin" num_pins="1"/>
<output name="cout" num_pins="1"/>
</pb_type>
<interconnect>
<direct name="direct1" input="frac_logic.in[0:1]" output="frac_lut4.in[0:1]"/>
<direct name="direct2" input="frac_logic.in[3:3]" output="frac_lut4.in[3:3]"/>
<direct name="direct3" input="frac_logic.cin" output="carry_follower.b"/>
<direct name="direct4" input="frac_lut4.lut2_out[1:1]" output="carry_follower.a"/>
<direct name="direct5" input="frac_lut4.lut2_out[0:0]" output="carry_follower.cin"/>
<direct name="direct6" input="carry_follower.cout" output="frac_logic.cout"/>
<direct name="direct7" input="frac_lut4.lut3_out[1]" output="frac_logic.out[1]"/>
<!-- Xifan Tang: I use out[0] because the output of lut6 in lut6 mode is wired to the out[0] -->
<mux name="mux1" input="frac_lut4.lut4_out frac_lut4.lut3_out[0]" output="frac_logic.out[0]"/>
<mux name="mux2" input="frac_logic.cin frac_logic.in[2:2]" output="frac_lut4.in[2:2]"/>
</interconnect>
</pb_type>
<!-- Define flip-flop with scan-chain capability, DI is the scan-chain data input -->
<pb_type name="ff" blif_model=".subckt scff" num_pb="2">
<input name="D" num_pins="1"/>
<input name="DI" num_pins="1"/>
<input name="reset" num_pins="1"/>
<output name="Q" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<T_setup value="${FF_T_SETUP}" port="ff.D" clock="clk"/>
<T_setup value="${FF_T_SETUP}" port="ff.DI" clock="clk"/>
<T_setup value="${FF_T_SETUP}" port="ff.reset" clock="clk"/>
<T_clock_to_Q max="${FF_T_CLK2Q}" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="fabric.in" output="frac_logic.in"/>
<direct name="direct2" input="fabric.cin" output="frac_logic.cin"/>
<direct name="direct3" input="fabric.sc_in" output="ff[0].DI"/>
<direct name="direct4" input="ff[0].Q" output="ff[1].DI"/>
<direct name="direct5" input="ff[1].Q" output="fabric.sc_out"/>
<direct name="direct6" input="ff[1].Q" output="fabric.reg_out"/>
<direct name="direct7" input="frac_logic.cout" output="fabric.cout"/>
<complete name="complete1" input="fabric.clk" output="ff[1:0].clk"/>
<complete name="complete2" input="fabric.reset" output="ff[1:0].reset"/>
<mux name="mux1" input="frac_logic.out[0:0] fabric.reg_in" output="ff[0:0].D">
<delay_constant max="${LUT_OUT0_TO_FF_D_DELAY}" in_port="frac_logic.out[0:0]" out_port="ff[0:0].D"/>
<delay_constant max="${LUT_OUT0_TO_FF_D_DELAY}" in_port="fabric.reg_in" out_port="ff[0:0].D"/>
</mux>
<mux name="mux2" input="frac_logic.out[1:1] ff[0:0].Q" output="ff[1:1].D">
<delay_constant max="${LUT_OUT1_TO_FF_D_DELAY}" in_port="frac_logic.out[1:1]" out_port="ff[1:1].D"/>
<delay_constant max="${LUT_OUT1_TO_FF_D_DELAY}" in_port="ff[0:0].Q" out_port="ff[1:1].D"/>
</mux>
<mux name="mux3" input="ff[0].Q frac_logic.out[0]" output="fabric.out[0]">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="${LUT_OUT0_TO_FLE_OUT_DELAY}" in_port="frac_logic.out[0]" out_port="fabric.out[0]"/>
<delay_constant max="${FF0_Q_TO_FLE_OUT_DELAY}" in_port="ff[0].Q" out_port="fabric.out[0]"/>
</mux>
<mux name="mux4" input="ff[1].Q frac_logic.out[1]" output="fabric.out[1]">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="${LUT_OUT1_TO_FLE_OUT_DELAY}" in_port="frac_logic.out[1]" out_port="fabric.out[1]"/>
<delay_constant max="${FF1_Q_TO_FLE_OUT_DELAY}" in_port="ff[1].Q" out_port="fabric.out[1]"/>
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in" output="fabric.in"/>
<direct name="direct2" input="fle.reg_in" output="fabric.reg_in"/>
<direct name="direct3" input="fle.sc_in" output="fabric.sc_in"/>
<direct name="direct4" input="fle.cin" output="fabric.cin"/>
<direct name="direct5" input="fabric.out" output="fle.out"/>
<direct name="direct6" input="fabric.reg_out" output="fle.reg_out"/>
<direct name="direct7" input="fabric.sc_out" output="fle.sc_out"/>
<direct name="direct8" input="fabric.cout" output="fle.cout"/>
<direct name="direct9" input="fle.clk" output="fabric.clk"/>
<direct name="direct10" input="fle.reset" output="fabric.reset"/>
</interconnect>
</mode>
<!-- Physical mode definition end (physical implementation of the fle) -->
<!-- Dual 3-LUT mode definition begin -->
<mode name="n2_lut3">
<pb_type name="lut3inter" num_pb="1">
<input name="in" num_pins="3"/>
<output name="out" num_pins="2"/>
<clock name="clk" num_pins="1"/>
<pb_type name="ble3" num_pb="2">
<input name="in" num_pins="3"/>
<output name="out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Define the LUT -->
<pb_type name="lut3" blif_model=".names" num_pb="1" class="lut">
<input name="in" num_pins="3" port_class="lut_in"/>
<output name="out" num_pins="1" port_class="lut_out"/>
<!-- LUT timing using delay matrix -->
<delay_matrix type="max" in_port="lut3.in" out_port="lut3.out">
${LUT3_DELAY}
${LUT3_DELAY}
${LUT3_DELAY}
</delay_matrix>
</pb_type>
<!-- Define the flip-flop -->
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
<input name="D" num_pins="1" port_class="D"/>
<output name="Q" num_pins="1" port_class="Q"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="${FF_T_SETUP}" port="ff.D" clock="clk"/>
<T_clock_to_Q max="${FF_T_CLK2Q}" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="ble3.in[2:0]" output="lut3[0:0].in[2:0]"/>
<direct name="direct2" input="lut3[0:0].out" output="ff[0:0].D">
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
<pack_pattern name="ble3" in_port="lut3[0:0].out" out_port="ff[0:0].D"/>
</direct>
<direct name="direct3" input="ble3.clk" output="ff[0:0].clk"/>
<mux name="mux1" input="ff[0:0].Q lut3.out[0:0]" output="ble3.out[0:0]">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="${LUT3_OUT_TO_FLE_OUT_DELAY}" in_port="lut3.out[0:0]" out_port="ble3.out[0:0]"/>
<delay_constant max="${FF1_Q_TO_FLE_OUT_DELAY}" in_port="ff[0:0].Q" out_port="ble3.out[0:0]"/>
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="lut3inter.in" output="ble3[0:0].in"/>
<direct name="direct2" input="lut3inter.in" output="ble3[1:1].in"/>
<direct name="direct3" input="ble3[1:0].out" output="lut3inter.out"/>
<complete name="complete1" input="lut3inter.clk" output="ble3[1:0].clk"/>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in[2:0]" output="lut3inter.in"/>
<direct name="direct2" input="lut3inter.out" output="fle.out"/>
<direct name="direct3" input="fle.clk" output="lut3inter.clk"/>
</interconnect>
</mode>
<!-- Dual 3-LUT mode definition end -->
<!-- 4-LUT mode definition begin -->
<mode name="n1_lut4">
<!-- Define 4-LUT mode -->
<pb_type name="ble4" num_pb="1">
<input name="in" num_pins="4"/>
<output name="out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<!-- Define LUT -->
<pb_type name="lut4" blif_model=".names" num_pb="1" class="lut">
<input name="in" num_pins="4" port_class="lut_in"/>
<output name="out" num_pins="1" port_class="lut_out"/>
<!-- LUT timing using delay matrix -->
<delay_matrix type="max" in_port="lut4.in" out_port="lut4.out">
${LUT4_DELAY}
${LUT4_DELAY}
${LUT4_DELAY}
${LUT4_DELAY}
</delay_matrix>
</pb_type>
<!-- Define flip-flop -->
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop">
<input name="D" num_pins="1" port_class="D"/>
<output name="Q" num_pins="1" port_class="Q"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="${FF_T_SETUP}" port="ff.D" clock="clk"/>
<T_clock_to_Q max="${FF_T_CLK2Q}" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="ble4.in" output="lut4[0:0].in"/>
<direct name="direct2" input="lut4.out" output="ff.D">
<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->
<pack_pattern name="ble4" in_port="lut4.out" out_port="ff.D"/>
<delay_constant max="${LUT_OUT0_TO_FF_D_DELAY}" in_port="lut4.out" out_port="ff.D"/>
</direct>
<direct name="direct3" input="ble4.clk" output="ff.clk"/>
<mux name="mux1" input="ff.Q lut4.out" output="ble4.out">
<!-- LUT to output is faster than FF to output on a Stratix IV -->
<delay_constant max="${LUT4_OUT_TO_FLE_OUT_DELAY}" in_port="lut4.out" out_port="ble4.out"/>
<delay_constant max="${FF0_Q_TO_FLE_OUT_DELAY}" in_port="ff.Q" out_port="ble4.out"/>
</mux>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.in" output="ble4.in"/>
<direct name="direct2" input="ble4.out" output="fle.out[0:0]"/>
<direct name="direct3" input="fle.clk" output="ble4.clk"/>
</interconnect>
</mode>
<!-- 4-LUT mode definition end -->
<!-- Define shift register begin -->
<!-- <mode name="shift_register">
<pb_type name="shift_reg" num_pb="1">
<input name="reg_in" num_pins="1"/>
<output name="ff_out" num_pins="2"/>
<output name="reg_out" num_pins="1"/>
<clock name="clk" num_pins="1"/>
<pb_type name="ff" blif_model=".latch" num_pb="2" class="flipflop">
<input name="D" num_pins="1" port_class="D"/>
<output name="Q" num_pins="1" port_class="Q"/>
<clock name="clk" num_pins="1" port_class="clock"/>
<T_setup value="${FF_T_SETUP}" port="ff.D" clock="clk"/>
<T_clock_to_Q max="${FF_T_CLK2Q}" port="ff.Q" clock="clk"/>
</pb_type>
<interconnect>
<direct name="direct1" input="shift_reg.reg_in" output="ff[0].D">
<delay_constant max="${LUT_OUT0_TO_FF_D_DELAY}" in_port="shift_reg.reg_in" out_port="ff[0].D"/>
</direct>
<direct name="direct2" input="ff[0].Q" output="ff[1].D">
<delay_constant max="${FF0_TO_FF1_DELAY}" in_port="ff[0].Q" out_port="ff[1].D"/>
</direct>
<direct name="direct3" input="ff[1].Q" output="shift_reg.reg_out"/>
<direct name="direct4" input="ff[0].Q" output="shift_reg.ff_out[0:0]">
<delay_constant max="${FF0_Q_TO_FLE_OUT_DELAY}" in_port="ff[0].Q" out_port="shift_reg.ff_out[0:0]"/>
</direct>
<direct name="direct5" input="ff[1].Q" output="shift_reg.ff_out[1:1]">
<delay_constant max="${FF1_Q_TO_FLE_OUT_DELAY}" in_port="ff[1].Q" out_port="shift_reg.ff_out[1:1]"/>
</direct>
<complete name="complete1" input="shift_reg.clk" output="ff.clk"/>
</interconnect>
</pb_type>
<interconnect>
<direct name="direct1" input="fle.reg_in" output="shift_reg.reg_in"/>
<direct name="direct2" input="shift_reg.reg_out" output="fle.reg_out"/>
<direct name="direct3" input="shift_reg.ff_out" output="fle.out"/>
<direct name="direct4" input="fle.clk" output="shift_reg.clk"/>
</interconnect>
</mode> -->
<!-- Define shift register end -->
</pb_type>
<interconnect>
<!-- We use direct connections to reduce the area to the most
The global local routing is going to compensate the loss in routability
-->
<!-- FIXME: The implicit port definition results in I0[0] connected to
in[2]. Such twisted connection is not expected.
I[0] should be connected to in[0]
-->
<direct name="direct_fle0" input="clb.I0[0:1]" output="fle[0:0].in[0:1]">
</direct>
<direct name="direct_fle0i" input="clb.I0i[0:1]" output="fle[0:0].in[2:3]">
</direct>
<direct name="direct_fle1" input="clb.I1[0:1]" output="fle[1:1].in[0:1]">
</direct>
<direct name="direct_fle1i" input="clb.I1i[0:1]" output="fle[1:1].in[2:3]">
</direct>
<direct name="direct_fle2" input="clb.I2[0:1]" output="fle[2:2].in[0:1]">
</direct>
<direct name="direct_fle2i" input="clb.I2i[0:1]" output="fle[2:2].in[2:3]">
</direct>
<direct name="direct_fle3" input="clb.I3[0:1]" output="fle[3:3].in[0:1]">
</direct>
<direct name="direct_fle3i" input="clb.I3i[0:1]" output="fle[3:3].in[2:3]">
</direct>
<direct name="direct_fle4" input="clb.I4[0:1]" output="fle[4:4].in[0:1]">
</direct>
<direct name="direct_fle4i" input="clb.I4i[0:1]" output="fle[4:4].in[2:3]">
</direct>
<direct name="direct_fle5" input="clb.I5[0:1]" output="fle[5:5].in[0:1]">
</direct>
<direct name="direct_fle5i" input="clb.I5i[0:1]" output="fle[5:5].in[2:3]">
</direct>
<direct name="direct_fle6" input="clb.I6[0:1]" output="fle[6:6].in[0:1]">
</direct>
<direct name="direct_fle6i" input="clb.I6i[0:1]" output="fle[6:6].in[2:3]">
</direct>
<direct name="direct_fle7" input="clb.I7[0:1]" output="fle[7:7].in[0:1]">
</direct>
<direct name="direct_fle7i" input="clb.I7i[0:1]" output="fle[7:7].in[2:3]">
</direct>
<complete name="clks" input="clb.clk" output="fle[7:0].clk">
</complete>
<complete name="resets" input="clb.reset" output="fle[7:0].reset">
</complete>
<!-- This way of specifying direct connection to clb outputs is important because this architecture uses automatic spreading of opins.
By grouping to output pins in this fashion, if a logic block is completely filled by 6-LUTs,
then the outputs those 6-LUTs take get evenly distributed across all four sides of the CLB instead of clumped on two sides (which is what happens with a more
naive specification).
-->
<direct name="clbouts1" input="fle[3:0].out[0:1]" output="clb.O[7:0]"/>
<direct name="clbouts2" input="fle[7:4].out[0:1]" output="clb.O[15:8]"/>
<!-- Shift register chain links -->
<direct name="shift_register_in" input="clb.reg_in" output="fle[0:0].reg_in">
<!-- Put all inter-block carry chain delay on this one edge -->
<delay_constant max="0" in_port="clb.reg_in" out_port="fle[0:0].reg_in"/>
<!--pack_pattern name="chain" in_port="clb.reg_in" out_port="fle[0:0].reg_in"/-->
</direct>
<direct name="shift_register_out" input="fle[7:7].reg_out" output="clb.reg_out">
<!--pack_pattern name="chain" in_port="fle[7:7].reg_out" out_port="clb.reg_out"/-->
</direct>
<direct name="shift_register_link" input="fle[6:0].reg_out" output="fle[7:1].reg_in">
<!--pack_pattern name="chain" in_port="fle[6:0].reg_out" out_port="fle[7:1].reg_in"/-->
</direct>
<!-- Scan chain links -->
<direct name="scan_chain_in" input="clb.sc_in" output="fle[0:0].sc_in">
<!-- Put all inter-block carry chain delay on this one edge -->
<delay_constant max="0" in_port="clb.sc_in" out_port="fle[0:0].sc_in"/>
</direct>
<direct name="scan_chain_out" input="fle[7:7].sc_out" output="clb.sc_out">
</direct>
<direct name="scan_chain_link" input="fle[6:0].sc_out" output="fle[7:1].sc_in">
</direct>
<!-- Carry chain links -->
<direct name="carry_chain_in" input="clb.cin" output="fle[0:0].cin">
<!-- Put all inter-block carry chain delay on this one edge -->
<delay_constant max="0" in_port="clb.cin" out_port="fle[0:0].cin"/>
</direct>
<direct name="carry_chain_out" input="fle[7:7].cout" output="clb.cout">
</direct>
<direct name="carry_chain_link" input="fle[6:0].cout" output="fle[7:1].cin">
</direct>
</interconnect>
<!-- Every input pin is driven by 15% of the tracks in a channel, every output pin is driven by 10% of the tracks in a channel -->
<!-- Place this general purpose logic block in any unspecified column -->
</pb_type>
<!-- Define general purpose logic block (CLB) ends -->
</complexblocklist>
</architecture>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
# This script is designed to generate Verilog testbenches
# with a fixed device layout
# It will only output netlists to be used by verification tools
# including
# - Verilog testbenches, used by ModelSim
# - SDC for a mapped FPGA fabric, used by Synopsys PrimeTime
#
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal --device ${OPENFPGA_VPR_DEVICE_LAYOUT} --absorb_buffer_luts off
# Read OpenFPGA architecture definition
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
# Read OpenFPGA simulation settings
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
# Annotate the OpenFPGA architecture to VPR data base
# to debug use --verbose options
link_openfpga_arch --sort_gsb_chan_node_in_edges
# Check and correct any naming conflicts in the BLIF netlist
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
# Apply fix-up to clustering nets based on routing results
pb_pin_fixup --verbose
# Apply fix-up to Look-Up Table truth tables based on packing results
lut_truth_table_fixup
# Build the module graph
# - Enabled compression on routing architecture modules
# - Enable pin duplication on grid modules
build_fabric --compress_routing --duplicate_grid_pin #--verbose
# Repack the netlist to physical pbs
# This must be done before bitstream generator and testbench generation
# Strongly recommend it is done after all the fix-up have been applied
repack #--verbose
# Build the bitstream
# - Output the fabric-independent bitstream to a file
build_architecture_bitstream --verbose --write_file arch_bitstream.xml
# Build fabric-dependent bitstream
build_fabric_bitstream --verbose
# Write fabric-dependent bitstream
write_fabric_bitstream --file fabric_bitstream.xml --format xml
# Write the Verilog testbench for FPGA fabric
# - We suggest the use of same output directory as fabric Verilog netlists
# - Must specify the reference benchmark file if you want to output any testbenches
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
write_verilog_testbench --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/verilog_testbench \
--fabric_netlist_file_path ${OPENFPGA_FABRIC_VERILOG_NETLIST} \
--reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} \
--print_top_testbench \
# --print_preconfig_top_testbench \ disabled for now due to disk space limitation on github actions
--print_simulation_ini ${OPENFPGA_VERILOG_OUTPUT_DIR}/SimulationDeck/simulation_deck.ini \
--explicit_port_mapping
# Exclude signal initialization since it does not help simulator converge
# due to the lack of reset pins for flip-flops
#--include_signal_init
# Write the SDC to run timing analysis for a mapped FPGA fabric
write_analysis_sdc --file ${OPENFPGA_VERILOG_OUTPUT_DIR}/sdc_analysis
# Finish and exit OpenFPGA
exit
# Note :
# To run verification at the end of the flow maintain source in ./SRC directory

View File

@ -0,0 +1,48 @@
<!-- Simulation Setting for OpenFPGA framework
This file will use
- a fixed operating clock frequency
- a fixed programming clock frequency
Note: all the numbers are tuned to STA results from physical layouts
-->
<openfpga_simulation_setting>
<clock_setting>
<!-- Use 50MHz as the Caravel SoC can operate at 50MHz
As the FPGA core does not share the clock with Caravel SoC
the actual clock frequency could be higher
-->
<operating frequency="50e6" num_cycles="100" slack="0.2"/>
<!-- Use 50MHz as the Caravel SoC can operate at 50MHz
As the FPGA core does not share the clock with Caravel SoC
the actual programming clock frequency could be higher
-->
<programming frequency="50e6"/>
</clock_setting>
<simulator_option>
<operating_condition temperature="25"/>
<output_log verbose="false" captab="false"/>
<accuracy type="abs" value="1e-13"/>
<runtime fast_simulation="true"/>
</simulator_option>
<monte_carlo num_simulation_points="2"/>
<measurement_setting>
<slew>
<rise upper_thres_pct="0.95" lower_thres_pct="0.05"/>
<fall upper_thres_pct="0.05" lower_thres_pct="0.95"/>
</slew>
<delay>
<rise input_thres_pct="0.5" output_thres_pct="0.5"/>
<fall input_thres_pct="0.5" output_thres_pct="0.5"/>
</delay>
</measurement_setting>
<stimulus>
<clock>
<rise slew_type="abs" slew_time="20e-12" />
<fall slew_type="abs" slew_time="20e-12" />
</clock>
<input>
<rise slew_type="abs" slew_time="25e-12" />
<fall slew_type="abs" slew_time="25e-12" />
</input>
</stimulus>
</openfpga_simulation_setting>

View File

@ -26,6 +26,9 @@ parser = argparse.ArgumentParser(description='Setup repository');
parser.add_argument('--openfpga_root_path',
default='../OpenFPGA',
help='Specify the root directory of OpenFPGA project');
parser.add_argument('--noruns',
action='store_true',
help='Just setup SOFA, don\'t do task runs');
args = parser.parse_args();
#####################################################################
@ -116,19 +119,22 @@ logging.info("Processed for " + str(num_task_config_file_processed) + "openfpga
openfpga_task_src_dir = skywater_openfpga_homepath + "/SCRIPT/skywater_openfpga_task";
openfpga_task_des_dir = openfpga_root_path + "/openfpga_flow/tasks/skywater_openfpga_task";
if (os.path.isdir(openfpga_task_des_dir) or os.path.isfile(openfpga_task_des_dir)):
logging.warning("There is already a skywater_openfpga_task directory/file at " + openfpga_task_des_dir);
logging.error("Failed to create symbolic link!");
exit(1);
elif (os.path.islink(openfpga_task_des_dir)):
if (os.path.islink(openfpga_task_des_dir)):
logging.warning("There is already a skywater_openfpga_task symbolic link at " + openfpga_task_des_dir);
os.unlink(openfpga_task_des_dir);
logging.warning("Removed the symbolic link");
elif (os.path.isdir(openfpga_task_des_dir) or os.path.isfile(openfpga_task_des_dir)):
logging.warning("There is already a skywater_openfpga_task directory/file at " + openfpga_task_des_dir);
logging.error("Failed to create symbolic link!");
exit(1);
os.symlink(openfpga_task_src_dir, openfpga_task_des_dir, True);
logging.info("Created OpenFPGA task symbolic link at " + openfpga_task_des_dir);
if (args.noruns):
exit(0);
#####################################################################
# Execute openfpga task runs
#####################################################################

View File

@ -0,0 +1,39 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# 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_130nm/130nm.xml
power_analysis = true
spice_output=false
verilog_output=true
timeout_each_job = 1*60
fpga_flow=yosys_vpr
arch_variable_file=${SKYWATER_OPENFPGA_HOME}/ARCH/timing_annotation/k4_frac_N8_tileable_register_scan_chain_nonLR_caravel_io_skywater130nm_timing_tt_025C_1v80.yml
[OpenFPGA_SHELL]
openfpga_shell_template=${SKYWATER_OPENFPGA_HOME}/SCRIPT/openfpga_shell_script/skywater_generate_testbench_arch_exploration.openfpga
openfpga_arch_file=${SKYWATER_OPENFPGA_HOME}/ARCH/openfpga_arch/k4_frac_N8_reset_softadder_register_scan_chain_caravel_io_skywater130nm_fdhd_cc_openfpga.xml
openfpga_sim_setting_file=${SKYWATER_OPENFPGA_HOME}/SCRIPT/openfpga_simulation_setting/efpga_12x12_sim_auto_clock.xml
openfpga_vpr_device_layout=auto
openfpga_vpr_route_chan_width=40 # Don't care
openfpga_verilog_output_dir=${SKYWATER_OPENFPGA_HOME}/TESTBENCH/k4_N8_caravel_io_FPGA_12x12_fdhd_cc/prepnr
openfpga_fabric_verilog_netlist=${SKYWATER_OPENFPGA_HOME}/HDL/k4_N8_caravel_io_FPGA_12x12_fdhd_cc/SRC/fabric_netlists.v
external_fabric_key_file=${SKYWATER_OPENFPGA_HOME}/ARCH/fabric_key/fabric_key_12x12.xml # Don't care
[ARCHITECTURES]
arch0=${SKYWATER_OPENFPGA_HOME}/ARCH/vpr_arch/k4_frac_N8_tileable_reset_softadder_scan_chain_nonLR_caravel_io_skywater130nm.xml
[BENCHMARKS]
bench0=${SKYWATER_OPENFPGA_HOME}/BENCHMARK/vexriscv/vexriscv_small.v
[SYNTHESIS_PARAM]
bench0_top = VexRiscv
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
# none