Update VPR7 X2P with new engine
This commit is contained in:
parent
e2e4a9287d
commit
46d44fa42a
|
@ -1,11 +0,0 @@
|
|||
This directory contains sample architecture files that are used in testing
|
||||
libarchfpga. In addition, the architecture files in this directory are used by
|
||||
the regression testing facilities of Odin II.
|
||||
|
||||
Please be sure to retain sample_arch.xml and update it with any changes that
|
||||
are made to the libvpr library.
|
||||
|
||||
Ken Kent
|
||||
ken@unb.ca
|
||||
06.18.2009
|
||||
|
|
@ -1,716 +0,0 @@
|
|||
<architecture>
|
||||
|
||||
<!-- jluu and ken: ODIN II specific config -->
|
||||
<models>
|
||||
<model name="multiply">
|
||||
<input_ports>
|
||||
<port name="a"/>
|
||||
<port name="b"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
|
||||
<model name="single_port_ram">
|
||||
<input_ports>
|
||||
<port name="we"/> <!-- control -->
|
||||
<port name="addr"/> <!-- address lines -->
|
||||
<port name="data"/> <!-- data lines can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="clk" is_clock="1"/> <!-- memories are often clocked -->
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out"/> <!-- output can be broken down into smaller bit widths minimum size 1 -->
|
||||
</output_ports>
|
||||
</model>
|
||||
|
||||
<model name="dual_port_ram">
|
||||
<input_ports>
|
||||
<port name="we1"/> <!-- write enable -->
|
||||
<port name="we2"/> <!-- write enable -->
|
||||
<port name="addr1"/> <!-- address lines -->
|
||||
<port name="addr2"/> <!-- address lines -->
|
||||
<port name="data1"/> <!-- data lines can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="data2"/> <!-- data lines can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="clk" is_clock="1"/> <!-- memories are often clocked -->
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out1"/> <!-- output can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="out2"/> <!-- output can be broken down into smaller bit widths minimum size 1 -->
|
||||
</output_ports>
|
||||
</model>
|
||||
</models>
|
||||
<!-- jluu and ken: ODIN II specific config ends -->
|
||||
|
||||
<!-- jluu and ken: Physical descriptions begin -->
|
||||
<!-- <layout width="20" height="20"/> -->
|
||||
<layout auto="1.0"/>
|
||||
<device>
|
||||
<sizing R_minW_nmos="5726.870117" R_minW_pmos="15491.700195" ipin_mux_trans_size="1.000000"/>
|
||||
<timing C_ipin_cblock="1.191000e-14" T_ipin_cblock="1.482000e-10"/>
|
||||
<area grid_logic_tile_area="30000.000000"/>
|
||||
<chan_width_distr>
|
||||
<io width="1.000000"/>
|
||||
<x distr="uniform" peak="1.000000"/>
|
||||
<y distr="uniform" peak="1.000000"/>
|
||||
</chan_width_distr>
|
||||
<switch_block type="wilton" fs="3"/>
|
||||
</device>
|
||||
<switchlist>
|
||||
<switch type="mux" name="0" R="94.841003" Cin="1.537000e-14" Cout="2.194000e-13" Tdel="6.562000e-11" mux_trans_size="10.000000" buf_size="1"/>
|
||||
</switchlist>
|
||||
<segmentlist>
|
||||
<segment freq="1.000000" length="4" type="unidir" Rmetal="11.064550" Cmetal="4.727860e-14">
|
||||
<mux name="0"/>
|
||||
<sb type="pattern">1 1 1 1 1</sb>
|
||||
<cb type="pattern">1 1 1 1</cb>
|
||||
</segment>
|
||||
</segmentlist>
|
||||
<complexblocklist>
|
||||
<pb_type name="io" capacity="7">
|
||||
<input name="outpad" num_pins="1" equivalent="false"/>
|
||||
<output name="inpad" num_pins="1"/>
|
||||
<clock name="clock" num_pins="1"/>
|
||||
|
||||
<!-- IOs can operate as either inputs or outputs -->
|
||||
<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"/>
|
||||
</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"/>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
|
||||
<!-- IOs go on the periphery of the FPGA, for consistency,
|
||||
make it physically equivalent on all sides so that only one definition of I/Os is needed.
|
||||
If I do not make a physically equivalent definition, then I need to define 4 different I/Os, one for each side of the FPGA
|
||||
-->
|
||||
<pinlocations pattern="custom">
|
||||
<loc side="left">io.outpad io.inpad io.clock</loc>
|
||||
<loc side="top">io.outpad io.inpad io.clock</loc>
|
||||
<loc side="right">io.outpad io.inpad io.clock</loc>
|
||||
<loc side="bottom">io.outpad io.inpad io.clock</loc>
|
||||
</pinlocations>
|
||||
|
||||
<gridlocations>
|
||||
<loc type="perimeter" priority="10"/>
|
||||
</gridlocations>
|
||||
|
||||
</pb_type>
|
||||
<pb_type name="clb">
|
||||
|
||||
<input name="I" num_pins="56" equivalent="true"/>
|
||||
<output name="O" num_pins="16"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<pb_type name="ble" num_pb="8">
|
||||
<input name="in" num_pins="7"/>
|
||||
<output name="out" num_pins="2"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<pb_type name="soft_logic" num_pb="1">
|
||||
<input name="in" num_pins="7"/>
|
||||
<output name="out" num_pins="2"/>
|
||||
<mode name="n2_lut5">
|
||||
<pb_type name="lut5" blif_model=".names" num_pb="2" class="lut">
|
||||
<input name="in" num_pins="5" port_class="lut_in"/>
|
||||
<output name="out" num_pins="1" port_class="lut_out"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="soft_logic.in[4:0]" output="lut5[0:0].in[4:0]"/>
|
||||
<direct name="direct2" input="lut5[0:0].out" output="soft_logic.out[0:0]"/>
|
||||
<direct name="direct3" input="soft_logic.in[6:2]" output="lut5[1:1].in[4:0]"/>
|
||||
<direct name="direct4" input="lut5[1:1].out" output="soft_logic.out[1:1]"/>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="n1_lut6">
|
||||
<pb_type name="lut6" blif_model=".names" num_pb="1" class="lut">
|
||||
<input name="in" num_pins="6" port_class="lut_in"/>
|
||||
<output name="out" num_pins="1" port_class="lut_out"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="soft_logic.in[5:0]" output="lut6[0:0].in[5:0]"/>
|
||||
<direct name="direct2" input="lut6[0:0].out" output="soft_logic.out[0:0]"/>
|
||||
</interconnect>
|
||||
</mode>
|
||||
</pb_type>
|
||||
<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"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<!-- Two ff, make ff available to only corresponding luts -->
|
||||
<direct name="direct1" input="ble.in" output="soft_logic.in"/>
|
||||
<direct name="direct2" input="soft_logic.out[0:0]" output="ff[0:0].D"/>
|
||||
<direct name="direct3" input="soft_logic.out[1:1]" output="ff[1:1].D"/>
|
||||
<direct name="direct4" input="ble.clk" output="ff[0:0].clk"/>
|
||||
<direct name="direct5" input="ble.clk" output="ff[1:1].clk"/>
|
||||
<mux name="mux1" input="ff[0:0].Q soft_logic.out[0:0]" output="ble.out[0:0]"/>
|
||||
<mux name="mux2" input="ff[1:1].Q soft_logic.out[1:1]" output="ble.out[1:1]"/>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<complete name="complete1" input="clb.I ble[7:0].out" output="ble[7:0].in"/>
|
||||
<complete name="complete2" input="clb.clk" output="ble[7:0].clk"/>
|
||||
<direct name="direct1" input="ble[7:0].out" output="clb.O"/>
|
||||
</interconnect>
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
<gridlocations>
|
||||
<loc type="fill" priority="1"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
<pb_type name="memory" height="4">
|
||||
<input name="addr1" num_pins="16"/>
|
||||
<input name="addr2" num_pins="16"/>
|
||||
<input name="data" num_pins="64"/>
|
||||
<input name="we1" num_pins="1"/>
|
||||
<input name="we2" num_pins="1"/>
|
||||
<output name="out" num_pins="64"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
|
||||
<mode name="mem_1024x64_sp">
|
||||
<pb_type name="mem_1024x64_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="10" port_class="address"/>
|
||||
<input name="data" num_pins="64" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="64" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[9:0]" output="mem_1024x64_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[63:0]" output="mem_1024x64_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_1024x64_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_1024x64_sp.out" output="memory.out[63:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_1024x64_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_2048x32_dp">
|
||||
<pb_type name="mem_2048x32_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr1" num_pins="11" port_class="address1"/>
|
||||
<input name="addr2" num_pins="11" port_class="address2"/>
|
||||
<input name="data1" num_pins="32" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="32" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="32" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="32" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[10:0]" output="mem_2048x32_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[10:0]" output="mem_2048x32_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[31:0]" output="mem_2048x32_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[63:32]" output="mem_2048x32_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_2048x32_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_2048x32_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_2048x32_dp.out1" output="memory.out[31:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_2048x32_dp.out2" output="memory.out[63:32]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_2048x32_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_2048x32_sp">
|
||||
<pb_type name="mem_2048x32_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="11" port_class="address"/>
|
||||
<input name="data" num_pins="32" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="32" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[10:0]" output="mem_2048x32_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[31:0]" output="mem_2048x32_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_2048x32_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_2048x32_sp.out" output="memory.out[31:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_2048x32_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_4096x16_dp">
|
||||
<pb_type name="mem_4096x16_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr1" num_pins="12" port_class="address1"/>
|
||||
<input name="addr2" num_pins="12" port_class="address2"/>
|
||||
<input name="data1" num_pins="16" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="16" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="16" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="16" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[11:0]" output="mem_4096x16_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[11:0]" output="mem_4096x16_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[15:0]" output="mem_4096x16_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[31:16]" output="mem_4096x16_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_4096x16_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_4096x16_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_4096x16_dp.out1" output="memory.out[15:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_4096x16_dp.out2" output="memory.out[31:16]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_4096x16_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_4096x16_sp">
|
||||
<pb_type name="mem_4096x16_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="12" port_class="address"/>
|
||||
<input name="data" num_pins="16" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="16" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[11:0]" output="mem_4096x16_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[15:0]" output="mem_4096x16_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_4096x16_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_4096x16_sp.out" output="memory.out[15:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_4096x16_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_8192x8_dp">
|
||||
<pb_type name="mem_8192x8_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr1" num_pins="13" port_class="address1"/>
|
||||
<input name="addr2" num_pins="13" port_class="address2"/>
|
||||
<input name="data1" num_pins="8" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="8" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="8" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="8" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[12:0]" output="mem_8192x8_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[12:0]" output="mem_8192x8_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[7:0]" output="mem_8192x8_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[15:8]" output="mem_8192x8_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_8192x8_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_8192x8_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_8192x8_dp.out1" output="memory.out[7:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_8192x8_dp.out2" output="memory.out[15:8]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_8192x8_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_8192x8_sp">
|
||||
<pb_type name="mem_8192x8_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="13" port_class="address"/>
|
||||
<input name="data" num_pins="8" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="8" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[12:0]" output="mem_8192x8_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[7:0]" output="mem_8192x8_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_8192x8_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_8192x8_sp.out" output="memory.out[7:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_8192x8_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_16384x4_dp">
|
||||
<pb_type name="mem_16384x4_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr1" num_pins="14" port_class="address1"/>
|
||||
<input name="addr2" num_pins="14" port_class="address2"/>
|
||||
<input name="data1" num_pins="4" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="4" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="4" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="4" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[13:0]" output="mem_16384x4_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[13:0]" output="mem_16384x4_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[3:0]" output="mem_16384x4_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[7:4]" output="mem_16384x4_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_16384x4_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_16384x4_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_16384x4_dp.out1" output="memory.out[3:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_16384x4_dp.out2" output="memory.out[7:4]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_16384x4_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_16384x4_sp">
|
||||
<pb_type name="mem_16384x4_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="14" port_class="address"/>
|
||||
<input name="data" num_pins="4" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="4" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[13:0]" output="mem_16384x4_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[3:0]" output="mem_16384x4_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_16384x4_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_16384x4_sp.out" output="memory.out[3:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_16384x4_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_32768x2_dp">
|
||||
<pb_type name="mem_32768x2_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr1" num_pins="15" port_class="address1"/>
|
||||
<input name="addr2" num_pins="15" port_class="address2"/>
|
||||
<input name="data1" num_pins="2" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="2" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="2" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="2" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[14:0]" output="mem_32768x2_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[14:0]" output="mem_32768x2_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[1:0]" output="mem_32768x2_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[3:2]" output="mem_32768x2_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_32768x2_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_32768x2_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_32768x2_dp.out1" output="memory.out[1:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_32768x2_dp.out2" output="memory.out[3:2]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_32768x2_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_32768x2_sp">
|
||||
<pb_type name="mem_32768x2_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="15" port_class="address"/>
|
||||
<input name="data" num_pins="2" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="2" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[14:0]" output="mem_32768x2_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[1:0]" output="mem_32768x2_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_32768x2_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_32768x2_sp.out" output="memory.out[1:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_32768x2_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_65536x1_dp">
|
||||
<pb_type name="mem_65536x1_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr1" num_pins="16" port_class="address1"/>
|
||||
<input name="addr2" num_pins="16" port_class="address2"/>
|
||||
<input name="data1" num_pins="1" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="1" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="1" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="1" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[15:0]" output="mem_65536x1_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[15:0]" output="mem_65536x1_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[0:0]" output="mem_65536x1_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[1:1]" output="mem_65536x1_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_65536x1_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_65536x1_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_65536x1_dp.out1" output="memory.out[0:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_65536x1_dp.out2" output="memory.out[1:1]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_65536x1_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_65536x1_sp">
|
||||
<pb_type name="mem_65536x1_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1" area="1000">
|
||||
<input name="addr" num_pins="16" port_class="address"/>
|
||||
<input name="data" num_pins="1" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="1" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[15:0]" output="mem_65536x1_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[0:0]" output="mem_65536x1_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_65536x1_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_65536x1_sp.out" output="memory.out[0:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_65536x1_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
<gridlocations>
|
||||
<loc type="col" start="2" repeat="5" priority="2"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
<!-- This is the 36*36 uniform mult -->
|
||||
<pb_type name="mult_36" height="3">
|
||||
<input name="a" num_pins="36"/>
|
||||
<input name="b" num_pins="36"/>
|
||||
<output name="out" num_pins="72"/>
|
||||
|
||||
<mode name="two_divisible_mult_18x18">
|
||||
<pb_type name="divisible_mult_18x18" num_pb="2">
|
||||
<input name="a" num_pins="18"/>
|
||||
<input name="b" num_pins="18"/>
|
||||
<output name="out" num_pins="36"/>
|
||||
|
||||
<mode name="two_mult_9x9">
|
||||
<pb_type name="mult_9x9_slice" num_pb="2">
|
||||
<input name="A_cfg" num_pins="9"/>
|
||||
<input name="B_cfg" num_pins="9"/>
|
||||
<output name="OUT_cfg" num_pins="18"/>
|
||||
|
||||
<pb_type name="mult_9x9" blif_model=".subckt multiply" num_pb="1" area="300">
|
||||
<input name="a" num_pins="9"/>
|
||||
<input name="b" num_pins="9"/>
|
||||
<output name="out" num_pins="18"/>
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="{a b}" out_port="out"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_9x9_slice.A_cfg" output="mult_9x9.a">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_9x9_slice.A_cfg" out_port="mult_9x9.a"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_9x9_slice.A_cfg" out_port="mult_9x9.a"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_9x9_slice.B_cfg" output="mult_9x9.b">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_9x9_slice.B_cfg" out_port="mult_9x9.b"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_9x9_slice.B_cfg" out_port="mult_9x9.b"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_9x9.out" output="mult_9x9_slice.OUT_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_9x9.out" out_port="mult_9x9_slice.OUT_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_9x9.out" out_port="mult_9x9_slice.OUT_cfg"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="divisible_mult_18x18.a" output="mult_9x9_slice[1:0].A_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="divisible_mult_18x18.a" out_port="mult_9x9_slice[1:0].A_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="divisible_mult_18x18.a" out_port="mult_9x9_slice[1:0].A_cfg"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="divisible_mult_18x18.b" output="mult_9x9_slice[1:0].B_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="divisible_mult_18x18.b" out_port="mult_9x9_slice[1:0].B_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="divisible_mult_18x18.b" out_port="mult_9x9_slice[1:0].B_cfg"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_9x9_slice[1:0].OUT_cfg" output="divisible_mult_18x18.out">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_9x9_slice[1:0].OUT_cfg" out_port ="divisible_mult_18x18.out"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_9x9_slice[1:0].OUT_cfg" out_port="divisible_mult_18x18.out"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mult_18x18">
|
||||
<pb_type name="mult_18x18_slice" num_pb="1">
|
||||
<input name="A_cfg" num_pins="18"/>
|
||||
<input name="B_cfg" num_pins="18"/>
|
||||
<output name="OUT_cfg" num_pins="36"/>
|
||||
|
||||
<pb_type name="mult_18x18" blif_model=".subckt multiply" num_pb="1" area="1000">
|
||||
<input name="a" num_pins="18"/>
|
||||
<input name="b" num_pins="18"/>
|
||||
<output name="out" num_pins="36"/>
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="{a b}" out_port="out"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_18x18_slice.A_cfg" output="mult_18x18.a">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_18x18_slice.A_cfg" out_port="mult_18x18.a"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_18x18_slice.A_cfg" out_port="mult_18x18.a"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_18x18_slice.B_cfg" output="mult_18x18.b">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_18x18_slice.B_cfg" out_port="mult_18x18.b"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_18x18_slice.B_cfg" out_port="mult_18x18.b"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_18x18.out" output="mult_18x18_slice.OUT_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_18x18.out" out_port="mult_18x18_slice.OUT_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_18x18.out" out_port="mult_18x18_slice.OUT_cfg"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="divisible_mult_18x18.a" output="mult_18x18_slice.A_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="divisible_mult_18x18.a" out_port="mult_18x18_slice.A_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="divisible_mult_18x18.a" out_port="mult_18x18_slice.A_cfg"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="divisible_mult_18x18.b" output="mult_18x18_slice.B_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="divisible_mult_18x18.b" out_port="mult_18x18_slice.B_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="divisible_mult_18x18.b" out_port="mult_18x18_slice.B_cfg"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_18x18_slice.OUT_cfg" output="divisible_mult_18x18.out">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_18x18_slice.OUT_cfg" out_port="divisible_mult_18x18.out"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_18x18_slice.OUT_cfg" out_port="divisible_mult_18x18.out"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_36.a" output="divisible_mult_18x18[1:0].a">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36.a" out_port="divisible_mult_18x18[1:0].a"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36.a" out_port="divisible_mult_18x18[1:0].a"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_36.b" output="divisible_mult_18x18[1:0].a">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36.b" out_port="divisible_mult_18x18[1:0].a"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36.b" out_port="divisible_mult_18x18[1:0].a"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="divisible_mult_18x18[1:0].out" output="mult_36.out">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="divisible_mult_18x18[1:0].out" out_port ="mult_36.out"/>
|
||||
<C_constant C="1.89e-13" in_port="divisible_mult_18x18[1:0].out" out_port="mult_36.out"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mult_36x36">
|
||||
<pb_type name="mult_36x36_slice" num_pb="1">
|
||||
<input name="A_cfg" num_pins="36"/>
|
||||
<input name="B_cfg" num_pins="36"/>
|
||||
<output name="OUT_cfg" num_pins="72"/>
|
||||
|
||||
<pb_type name="mult_36x36" blif_model=".subckt multiply" num_pb="1" area="4000">
|
||||
<input name="a" num_pins="36"/>
|
||||
<input name="b" num_pins="36"/>
|
||||
<output name="out" num_pins="72"/>
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="{a b}" out_port="out"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_36x36_slice.A_cfg" output="mult_36x36.a">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36x36_slice.A_cfg" out_port="mult_36x36.a"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36x36_slice.A_cfg" out_port="mult_36x36.a"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_36x36_slice.B_cfg" output="mult_36x36.b">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36x36_slice.B_cfg" out_port="mult_36x36.b"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36x36_slice.B_cfg" out_port="mult_36x36.b"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_36x36.out" output="mult_36x36_slice.OUT_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36x36.out" out_port="mult_36x36_slice.OUT_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36x36.out" out_port="mult_36x36_slice.OUT_cfg"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_36.a" output="mult_36x36_slice.A_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36.a" out_port="mult_36x36_slice.A_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36.a" out_port="mult_36x36_slice.A_cfg"/>
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_36.b" output="mult_36x36_slice.B_cfg">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36.b" out_port="mult_36x36_slice.B_cfg"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36.b" out_port="mult_36x36_slice.B_cfg"/>
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_36x36_slice.OUT_cfg" output="mult_36.out">
|
||||
<delay_constant max="2.03e-13" min="1.89e-13" in_port="mult_36x36_slice.OUT_cfg" out_port="mult_36.out"/>
|
||||
<C_constant C="1.89e-13" in_port="mult_36x36_slice.OUT_cfg" out_port="mult_36.out"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
|
||||
<gridlocations>
|
||||
<loc type="col" start="4" repeat="5" priority="2"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
</complexblocklist>
|
||||
</architecture>
|
|
@ -1,815 +0,0 @@
|
|||
<!--
|
||||
Architecture based off Stratix IV
|
||||
Use closest ifar architecture: K06 N10 45nm fc 0.15 area-delay optimized, scale to 40 nm using linear scaling
|
||||
n10k06l04.fc15.area1delay1.cmos45nm.bptm.cmos45nm.xml
|
||||
- because documentation sparser for soft logic (delays not in QUIP), harder to track down, not worth our time considering the level of accuracy is approximate
|
||||
- delays multiplied by 40/45 to normalize for process difference between stratix 4 and 45 nm technology (called full scaling)
|
||||
|
||||
Use delay numbers off Altera device handbook:
|
||||
|
||||
http://www.altera.com/literature/hb/stratix-iv/stx4_5v1.pdf
|
||||
http://www.altera.com/literature/hb/stratix-iv/stx4_siv51004.pdf
|
||||
http://www.altera.com/literature/hb/stratix-iv/stx4_siv51003.pdf
|
||||
multipliers at 600 MHz, no detail on 9x9 vs 36x36
|
||||
- datasheets unclear
|
||||
- claims 4 18x18 independant multipliers, following test indicates that this is not the case:
|
||||
created 4 18x18 mulitpliers, logiclocked them to a single DSP block, compile
|
||||
result - 2 18x18 multipliers got packed together, the other 2 got ejected out of the logiclock region without error
|
||||
conclusion - just take the 600 MHz as is, and Quartus II logiclock hasn't fixed the bug that I've seen it do to registers when I worked at Altera (ie. eject without warning)
|
||||
|
||||
NOTE: Area numbers for hard blocks unknown!
|
||||
-->
|
||||
|
||||
<architecture>
|
||||
|
||||
<!-- ODIN II specific config -->
|
||||
<models>
|
||||
<model name="multiply">
|
||||
<input_ports>
|
||||
<port name="a"/>
|
||||
<port name="b"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
|
||||
<model name="single_port_ram">
|
||||
<input_ports>
|
||||
<port name="we"/> <!-- control -->
|
||||
<port name="addr"/> <!-- address lines -->
|
||||
<port name="data"/> <!-- data lines can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="clk" is_clock="1"/> <!-- memories are often clocked -->
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out"/> <!-- output can be broken down into smaller bit widths minimum size 1 -->
|
||||
</output_ports>
|
||||
</model>
|
||||
|
||||
<model name="dual_port_ram">
|
||||
<input_ports>
|
||||
<port name="we1"/> <!-- write enable -->
|
||||
<port name="we2"/> <!-- write enable -->
|
||||
<port name="addr1"/> <!-- address lines -->
|
||||
<port name="addr2"/> <!-- address lines -->
|
||||
<port name="data1"/> <!-- data lines can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="data2"/> <!-- data lines can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="clk" is_clock="1"/> <!-- memories are often clocked -->
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out1"/> <!-- output can be broken down into smaller bit widths minimum size 1 -->
|
||||
<port name="out2"/> <!-- output can be broken down into smaller bit widths minimum size 1 -->
|
||||
</output_ports>
|
||||
</model>
|
||||
|
||||
<!-- fake carry-chain example -->
|
||||
<model name="alm">
|
||||
<input_ports>
|
||||
<port name="in"/>
|
||||
<port name="cin"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="out"/>
|
||||
<port name="cout"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
|
||||
|
||||
<model name="adder">
|
||||
<input_ports>
|
||||
<port name="a"/>
|
||||
<port name="b"/>
|
||||
<port name="cin"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="cout"/>
|
||||
<port name="sumout"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
<!--
|
||||
<model name="sub">
|
||||
<input_ports>
|
||||
<port name="a"/>
|
||||
<port name="b"/>
|
||||
<port name="cin"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="cout"/>
|
||||
<port name="sumout"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
-->
|
||||
|
||||
</models>
|
||||
<!-- ODIN II specific config ends -->
|
||||
|
||||
|
||||
<!-- Physical descriptions begin (area optimized for N8-K6-L4 -->
|
||||
<layout auto="1.0"/>
|
||||
|
||||
<device>
|
||||
<sizing R_minW_nmos="6065.520020" R_minW_pmos="18138.500000" ipin_mux_trans_size="1.222260"/>
|
||||
<timing C_ipin_cblock="0.000000e+00" T_ipin_cblock="7.247000e-11"/>
|
||||
<area grid_logic_tile_area="14813.392"/>
|
||||
<chan_width_distr>
|
||||
<io width="1.000000"/>
|
||||
<x distr="uniform" peak="1.000000"/>
|
||||
<y distr="uniform" peak="1.000000"/>
|
||||
</chan_width_distr>
|
||||
<switch_block type="wilton" fs="3"/>
|
||||
</device>
|
||||
<switchlist>
|
||||
<switch type="mux" name="0" R="0.000000" Cin="0.000000e+00" Cout="0.000000e+00" Tdel="6.837e-11" mux_trans_size="2.630740" buf_size="27.645901"/>
|
||||
</switchlist>
|
||||
<segmentlist>
|
||||
<segment freq="1.000000" length="4" type="unidir" Rmetal="0.000000" Cmetal="0.000000e+00">
|
||||
<mux name="0"/>
|
||||
<sb type="pattern">1 1 1 1 1</sb>
|
||||
<cb type="pattern">1 1 1 1</cb>
|
||||
</segment>
|
||||
</segmentlist>
|
||||
|
||||
<complexblocklist>
|
||||
<!-- Capacity is a unique property of I/Os, it is the maximum number of I/Os that can be placed at the same (X,Y) location on the FPGA -->
|
||||
<pb_type name="io" capacity="8">
|
||||
<input name="outpad" num_pins="1"/>
|
||||
<output name="inpad" num_pins="1"/>
|
||||
<clock name="clock" num_pins="1"/>
|
||||
|
||||
<!-- IOs can operate as either inputs or outputs -->
|
||||
<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="4.243e-11" 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="1.394e-11" in_port="io.outpad" out_port="outpad.outpad"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
|
||||
<!-- IOs go on the periphery of the FPGA, for consistency,
|
||||
make it physically equivalent on all sides so that only one definition of I/Os is needed.
|
||||
If I do not make a physically equivalent definition, then I need to define 4 different I/Os, one for each side of the FPGA
|
||||
-->
|
||||
<pinlocations pattern="custom">
|
||||
<loc side="left">io.outpad io.inpad io.clock</loc>
|
||||
<loc side="top">io.outpad io.inpad io.clock</loc>
|
||||
<loc side="right">io.outpad io.inpad io.clock</loc>
|
||||
<loc side="bottom">io.outpad io.inpad io.clock</loc>
|
||||
</pinlocations>
|
||||
|
||||
<gridlocations>
|
||||
<loc type="perimeter" priority="10"/>
|
||||
</gridlocations>
|
||||
|
||||
</pb_type>
|
||||
|
||||
|
||||
<pb_type name="clb">
|
||||
<input name="I" num_pins="33" equivalent="true"/>
|
||||
<output name="O" num_pins="10" equivalent="false"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
|
||||
<!-- Describe basic logic element, with ifar delay numbers -->
|
||||
<pb_type name="ble" num_pb="10">
|
||||
<input name="in" num_pins="6"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<pb_type name="soft_logic" num_pb="1">
|
||||
<input name="in" num_pins="6"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<mode name="n1_lut6">
|
||||
<pb_type name="lut6" blif_model=".names" num_pb="1" class="lut">
|
||||
<input name="in" num_pins="6" 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="lut6.in" out_port="lut6.out">
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
</delay_matrix>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="soft_logic.in[5:0]" output="lut6[0:0].in[5:0]"/>
|
||||
<direct name="direct2" input="lut6[0:0].out" output="soft_logic.out[0:0]">
|
||||
<!-- CAD related parameters -->
|
||||
<!-- Advanced "power-user" options: Describe connections that belong to forced pack blocks to give hints to the packer on what blocks to keep together
|
||||
Assumes pattern nets must be single-fanout
|
||||
-->
|
||||
<pack_pattern name="ble" in_port="lut6[0:0].out" out_port="soft_logic.out[0:0]"/>
|
||||
<!-- CAD related parameters -->
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
</pb_type>
|
||||
<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="2.448e-10" port="ff.D" clock="clk"/>
|
||||
<T_clock_to_Q max="7.732e-11" port="ff.Q" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<!-- Two ff, make ff available to only corresponding luts -->
|
||||
<direct name="direct1" input="ble.in" output="soft_logic.in"/>
|
||||
<direct name="direct2" input="soft_logic.out" output="ff.D">
|
||||
<pack_pattern name="ble" in_port="soft_logic.out" out_port="ff.D"/>
|
||||
</direct>
|
||||
<direct name="direct4" input="ble.clk" output="ff.clk"/>
|
||||
<mux name="mux1" input="ff.Q soft_logic.out" output="ble.out"/>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<complete name="crossbar" input="clb.I ble[9:0].out" output="ble[9:0].in">
|
||||
<delay_constant max="8.044000e-11" in_port="clb.I" out_port="ble[9:0].in" />
|
||||
<delay_constant max="7.354000e-11" in_port="ble[9:0].out" out_port="ble[9:0].in" />
|
||||
</complete>
|
||||
<complete name="clks" input="clb.clk" output="ble[9:0].clk">
|
||||
</complete>
|
||||
<direct name="clbouts" input="ble[9:0].out" output="clb.O">
|
||||
</direct>
|
||||
</interconnect>
|
||||
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
|
||||
<pinlocations pattern="spread"/>
|
||||
<gridlocations>
|
||||
<loc type="fill" priority="1"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
<!-- This is the 36*36 uniform mult -->
|
||||
<pb_type name="mult_36" height="4">
|
||||
<input name="a" num_pins="36"/>
|
||||
<input name="b" num_pins="36"/>
|
||||
<output name="out" num_pins="72"/>
|
||||
|
||||
<mode name="two_divisible_mult_18x18">
|
||||
<pb_type name="divisible_mult_18x18" num_pb="2">
|
||||
<input name="a" num_pins="18"/>
|
||||
<input name="b" num_pins="18"/>
|
||||
<output name="out" num_pins="36"/>
|
||||
|
||||
<mode name="two_mult_9x9">
|
||||
<pb_type name="mult_9x9_slice" num_pb="2">
|
||||
<input name="A_cfg" num_pins="9"/>
|
||||
<input name="B_cfg" num_pins="9"/>
|
||||
<output name="OUT_cfg" num_pins="18"/>
|
||||
|
||||
<pb_type name="mult_9x9" blif_model=".subckt multiply" num_pb="1">
|
||||
<input name="a" num_pins="9"/>
|
||||
<input name="b" num_pins="9"/>
|
||||
<output name="out" num_pins="18"/>
|
||||
<delay_constant max="1.667e-9" in_port="mult_9x9.a" out_port="mult_9x9.out"/>
|
||||
<delay_constant max="1.667e-9" in_port="mult_9x9.b" out_port="mult_9x9.out"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_9x9_slice.A_cfg" output="mult_9x9.a">
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_9x9_slice.B_cfg" output="mult_9x9.b">
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_9x9.out" output="mult_9x9_slice.OUT_cfg">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="divisible_mult_18x18.a" output="mult_9x9_slice[1:0].A_cfg">
|
||||
</direct>
|
||||
<direct name="b2b" input="divisible_mult_18x18.b" output="mult_9x9_slice[1:0].B_cfg">
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_9x9_slice[1:0].OUT_cfg" output="divisible_mult_18x18.out">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mult_18x18">
|
||||
<pb_type name="mult_18x18_slice" num_pb="1">
|
||||
<input name="A_cfg" num_pins="18"/>
|
||||
<input name="B_cfg" num_pins="18"/>
|
||||
<output name="OUT_cfg" num_pins="36"/>
|
||||
|
||||
<pb_type name="mult_18x18" blif_model=".subckt multiply" num_pb="1" >
|
||||
<input name="a" num_pins="18"/>
|
||||
<input name="b" num_pins="18"/>
|
||||
<output name="out" num_pins="36"/>
|
||||
<delay_constant max="1.667e-9" in_port="mult_18x18.a" out_port="mult_18x18.out"/>
|
||||
<delay_constant max="1.667e-9" in_port="mult_18x18.b" out_port="mult_18x18.out"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_18x18_slice.A_cfg" output="mult_18x18.a">
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_18x18_slice.B_cfg" output="mult_18x18.b">
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_18x18.out" output="mult_18x18_slice.OUT_cfg">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="divisible_mult_18x18.a" output="mult_18x18_slice.A_cfg">
|
||||
</direct>
|
||||
<direct name="b2b" input="divisible_mult_18x18.b" output="mult_18x18_slice.B_cfg">
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_18x18_slice.OUT_cfg" output="divisible_mult_18x18.out">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_36.a" output="divisible_mult_18x18[1:0].a">
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_36.b" output="divisible_mult_18x18[1:0].b">
|
||||
</direct>
|
||||
<direct name="out2out" input="divisible_mult_18x18[1:0].out" output="mult_36.out">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mult_36x36">
|
||||
<pb_type name="mult_36x36_slice" num_pb="1">
|
||||
<input name="A_cfg" num_pins="36"/>
|
||||
<input name="B_cfg" num_pins="36"/>
|
||||
<output name="OUT_cfg" num_pins="72"/>
|
||||
|
||||
<pb_type name="mult_36x36" blif_model=".subckt multiply" num_pb="1">
|
||||
<input name="a" num_pins="36"/>
|
||||
<input name="b" num_pins="36"/>
|
||||
<output name="out" num_pins="72"/>
|
||||
<delay_constant max="1.667e-9" in_port="mult_36x36.a" out_port="mult_36x36.out"/>
|
||||
<delay_constant max="1.667e-9" in_port="mult_36x36.b" out_port="mult_36x36.out"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_36x36_slice.A_cfg" output="mult_36x36.a">
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_36x36_slice.B_cfg" output="mult_36x36.b">
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_36x36.out" output="mult_36x36_slice.OUT_cfg">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="a2a" input="mult_36.a" output="mult_36x36_slice.A_cfg">
|
||||
</direct>
|
||||
<direct name="b2b" input="mult_36.b" output="mult_36x36_slice.B_cfg">
|
||||
</direct>
|
||||
<direct name="out2out" input="mult_36x36_slice.OUT_cfg" output="mult_36.out">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
|
||||
<gridlocations>
|
||||
<loc type="col" start="4" repeat="8" priority="2"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
|
||||
<!-- Memory based off Stratix IV 144K memory. Setup time set to match flip-flop setup time at 45 nm. Clock to q based off 144K max MHz -->
|
||||
<pb_type name="memory" height="6">
|
||||
<input name="addr1" num_pins="17"/>
|
||||
<input name="addr2" num_pins="17"/>
|
||||
<input name="data" num_pins="72"/>
|
||||
<input name="we1" num_pins="1"/>
|
||||
<input name="we2" num_pins="1"/>
|
||||
<output name="out" num_pins="72"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
|
||||
<mode name="mem_2048x72_sp">
|
||||
<pb_type name="mem_2048x72_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr" num_pins="11" port_class="address"/>
|
||||
<input name="data" num_pins="72" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="72" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_2048x72_sp.addr" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_2048x72_sp.data" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_2048x72_sp.we" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_2048x72_sp.out" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[10:0]" output="mem_2048x72_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[71:0]" output="mem_2048x72_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_2048x72_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_2048x72_sp.out" output="memory.out[71:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_2048x72_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_4096x36_dp">
|
||||
<pb_type name="mem_4096x36_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr1" num_pins="12" port_class="address1"/>
|
||||
<input name="addr2" num_pins="12" port_class="address2"/>
|
||||
<input name="data1" num_pins="36" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="36" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="36" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="36" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_dp.addr1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_dp.data1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_dp.we1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_dp.addr2" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_dp.data2" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_dp.we2" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_4096x36_dp.out1" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_4096x36_dp.out2" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[11:0]" output="mem_4096x36_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[11:0]" output="mem_4096x36_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[35:0]" output="mem_4096x36_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[71:36]" output="mem_4096x36_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_4096x36_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_4096x36_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_4096x36_dp.out1" output="memory.out[35:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_4096x36_dp.out2" output="memory.out[71:36]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_4096x36_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_4096x36_sp">
|
||||
<pb_type name="mem_4096x36_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr" num_pins="12" port_class="address"/>
|
||||
<input name="data" num_pins="36" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="36" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_sp.addr" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_sp.data" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_4096x36_sp.we" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_4096x36_sp.out" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[11:0]" output="mem_4096x36_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[35:0]" output="mem_4096x36_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_4096x36_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_4096x36_sp.out" output="memory.out[35:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_4096x36_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_9182x18_dp">
|
||||
<pb_type name="mem_9182x18_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr1" num_pins="13" port_class="address1"/>
|
||||
<input name="addr2" num_pins="13" port_class="address2"/>
|
||||
<input name="data1" num_pins="18" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="18" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="18" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="18" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_dp.addr1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_dp.data1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_dp.we1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_dp.addr2" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_dp.data2" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_dp.we2" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_9182x18_dp.out1" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_9182x18_dp.out2" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[12:0]" output="mem_9182x18_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[12:0]" output="mem_9182x18_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[17:0]" output="mem_9182x18_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[35:18]" output="mem_9182x18_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_9182x18_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_9182x18_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_9182x18_dp.out1" output="memory.out[17:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_9182x18_dp.out2" output="memory.out[35:18]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_9182x18_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_9182x18_sp">
|
||||
<pb_type name="mem_9182x18_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr" num_pins="13" port_class="address"/>
|
||||
<input name="data" num_pins="18" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="18" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_sp.addr" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_sp.data" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_9182x18_sp.we" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_9182x18_sp.out" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[12:0]" output="mem_9182x18_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[17:0]" output="mem_9182x18_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_9182x18_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_9182x18_sp.out" output="memory.out[17:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_9182x18_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="mem_18194x9_dp">
|
||||
<pb_type name="mem_18194x9_dp" blif_model=".subckt dual_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr1" num_pins="14" port_class="address1"/>
|
||||
<input name="addr2" num_pins="14" port_class="address2"/>
|
||||
<input name="data1" num_pins="9" port_class="data_in1"/>
|
||||
<input name="data2" num_pins="9" port_class="data_in2"/>
|
||||
<input name="we1" num_pins="1" port_class="write_en1"/>
|
||||
<input name="we2" num_pins="1" port_class="write_en2"/>
|
||||
<output name="out1" num_pins="9" port_class="data_out1"/>
|
||||
<output name="out2" num_pins="9" port_class="data_out2"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_dp.addr1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_dp.data1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_dp.we1" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_dp.addr2" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_dp.data2" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_dp.we2" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_18194x9_dp.out1" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_18194x9_dp.out2" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[13:0]" output="mem_18194x9_dp.addr1">
|
||||
</direct>
|
||||
<direct name="address2" input="memory.addr2[13:0]" output="mem_18194x9_dp.addr2">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[8:0]" output="mem_18194x9_dp.data1">
|
||||
</direct>
|
||||
<direct name="data2" input="memory.data[17:9]" output="mem_18194x9_dp.data2">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_18194x9_dp.we1">
|
||||
</direct>
|
||||
<direct name="writeen2" input="memory.we2" output="mem_18194x9_dp.we2">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_18194x9_dp.out1" output="memory.out[8:0]">
|
||||
</direct>
|
||||
<direct name="dataout2" input="mem_18194x9_dp.out2" output="memory.out[17:9]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_18194x9_dp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<mode name="mem_18194x9_sp">
|
||||
<pb_type name="mem_18194x9_sp" blif_model=".subckt single_port_ram" class="memory" num_pb="1">
|
||||
<input name="addr" num_pins="14" port_class="address"/>
|
||||
<input name="data" num_pins="9" port_class="data_in"/>
|
||||
<input name="we" num_pins="1" port_class="write_en"/>
|
||||
<output name="out" num_pins="9" port_class="data_out"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_sp.addr" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_sp.data" clock="clk"/>
|
||||
<T_setup value="2.448e-10" port="mem_18194x9_sp.we" clock="clk"/>
|
||||
<T_clock_to_Q max="1.852e-9" port="mem_18194x9_sp.out" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="address1" input="memory.addr1[13:0]" output="mem_18194x9_sp.addr">
|
||||
</direct>
|
||||
<direct name="data1" input="memory.data[8:0]" output="mem_18194x9_sp.data">
|
||||
</direct>
|
||||
<direct name="writeen1" input="memory.we1" output="mem_18194x9_sp.we">
|
||||
</direct>
|
||||
<direct name="dataout1" input="mem_18194x9_sp.out" output="memory.out[8:0]">
|
||||
</direct>
|
||||
<direct name="clk" input="memory.clk" output="mem_18194x9_sp.clk">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
<gridlocations>
|
||||
<loc type="col" start="2" repeat="8" priority="2"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
|
||||
|
||||
<!-- fake carry-chain example -->
|
||||
<pb_type name="carry_chain_example">
|
||||
<input name="I" num_pins="15" equivalent="true"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="O" num_pins="4" equivalent="false"/>
|
||||
<output name="cout" num_pins="1" equivalent="false"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
|
||||
<!-- Describe basic logic element, with ifar delay numbers -->
|
||||
<pb_type name="ble" num_pb="4">
|
||||
<input name="in" num_pins="6"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<pb_type name="alm" blif_model=".subckt alm" num_pb="1">
|
||||
<input name="in" num_pins="6"/>
|
||||
<input name="cin" num_pins="1" chain="carry_chain_alm"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<output name="cout" num_pins="1" chain="carry_chain_alm"/>
|
||||
|
||||
|
||||
<!-- LUT timing using delay matrix -->
|
||||
<delay_matrix type="max" in_port="alm.in" out_port="alm.out">
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
2.690e-10
|
||||
</delay_matrix>
|
||||
|
||||
<!-- LUT timing using delay matrix -->
|
||||
<delay_matrix type="max" in_port="alm.cin" out_port="alm.out">
|
||||
2.690e-10
|
||||
</delay_matrix>
|
||||
|
||||
<!-- LUT timing using delay matrix -->
|
||||
<delay_matrix type="max" in_port="alm.cin" out_port="alm.cout">
|
||||
1.690e-10
|
||||
</delay_matrix>
|
||||
</pb_type>
|
||||
<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="2.448e-10" port="ff.D" clock="clk"/>
|
||||
<T_clock_to_Q max="7.732e-11" port="ff.Q" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<!-- Two ff, make ff available to only corresponding luts -->
|
||||
<complete name="complete1" input="ble.in" output="alm.in ff.D"/>
|
||||
<direct name="direct4" input="ble.clk" output="ff.clk"/>
|
||||
<direct name="direct5" input="ble.cin" output="alm.cin"/>
|
||||
<direct name="direct6" input="alm.cout" output="ble.cout"/>
|
||||
<mux name="mux1" input="ff.Q alm.out" output="ble.out"/>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<complete name="crossbar" input="carry_chain_example.I ble[3:0].out" output="ble[3:0].in">
|
||||
<delay_constant max="8.044000e-11" in_port="carry_chain_example.I" out_port="ble[3:0].in" />
|
||||
<delay_constant max="7.354000e-11" in_port="ble[3:0].out" out_port="ble[3:0].in" />
|
||||
</complete>
|
||||
<complete name="clks" input="carry_chain_example.clk" output="ble[3:0].clk">
|
||||
</complete>
|
||||
<direct name="clbouts" input="ble[3:0].out" output="carry_chain_example.O">
|
||||
</direct>
|
||||
<direct name="carry1" input="ble[0:0].cout" output="ble[1:1].cin"/>
|
||||
<direct name="carry2" input="ble[1:1].cout" output="ble[2:2].cin"/>
|
||||
<direct name="carry3" input="ble[2:2].cout" output="ble[3:3].cin"/>
|
||||
<direct name="carry4" input="ble[3:3].cout" output="carry_chain_example.cout"/>
|
||||
</interconnect>
|
||||
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
|
||||
<pinlocations pattern="spread"/>
|
||||
<gridlocations>
|
||||
<loc type="col" start="7" repeat="50" priority="7"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
<!-- This is a basic ripple-carry adder primitive
|
||||
We will take care of the carry chain for it later, for now, get something that goes through the flow so that Odin II can be tested
|
||||
-->
|
||||
<pb_type name="adder" height="1">
|
||||
<input name="a" num_pins="4"/>
|
||||
<input name="b" num_pins="4"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<output name="sumout" num_pins="4"/>
|
||||
|
||||
<mode name="sample_adder">
|
||||
<pb_type name="sample_adder" blif_model=".subckt adder" num_pb="1">
|
||||
<input name="a" num_pins="4"/>
|
||||
<input name="b" num_pins="4"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<output name="sumout" num_pins="4"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_adder.a" out_port="sample_adder.cout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_adder.b" out_port="sample_adder.cout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_adder.cin" out_port="sample_adder.cout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_adder.a" out_port="sample_adder.sumout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_adder.b" out_port="sample_adder.sumout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_adder.cin" out_port="sample_adder.sumout"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="adder.a" output="sample_adder.a">
|
||||
</direct>
|
||||
<direct name="b2b" input="adder.b" output="sample_adder.b">
|
||||
</direct>
|
||||
<direct name="c2c" input="adder.cin" output="sample_adder.cin">
|
||||
</direct>
|
||||
<direct name="cout" input="sample_adder.cout" output="adder.cout">
|
||||
</direct>
|
||||
<direct name="sumout" input="sample_adder.sumout" output="adder.sumout">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
|
||||
<gridlocations>
|
||||
<loc type="col" start="2" repeat="13" priority="10"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
|
||||
<!--
|
||||
<pb_type name="sub" height="1">
|
||||
<input name="a" num_pins="4"/>
|
||||
<input name="b" num_pins="4"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<output name="sumout" num_pins="4"/>
|
||||
|
||||
<mode name="sample_sub">
|
||||
<pb_type name="sample_sub" blif_model=".subckt sub" num_pb="1">
|
||||
<input name="a" num_pins="4"/>
|
||||
<input name="b" num_pins="4"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<output name="sumout" num_pins="4"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_sub.a" out_port="sample_sub.cout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_sub.b" out_port="sample_sub.cout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_sub.cin" out_port="sample_sub.cout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_sub.a" out_port="sample_sub.sumout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_sub.b" out_port="sample_sub.sumout"/>
|
||||
<delay_constant max="1.667e-9" in_port="sample_sub.cin" out_port="sample_sub.sumout"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="a2a" input="sub.a" output="sample_sub.a">
|
||||
</direct>
|
||||
<direct name="b2b" input="sub.b" output="sample_sub.b">
|
||||
</direct>
|
||||
<direct name="c2c" input="sub.cin" output="sample_sub.cin">
|
||||
</direct>
|
||||
<direct name="cout" input="sample_sub.cout" output="sub.cout">
|
||||
</direct>
|
||||
<direct name="sumout" input="sample_sub.sumout" output="sub.sumout">
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.125"/>
|
||||
<pinlocations pattern="spread"/>
|
||||
|
||||
<gridlocations>
|
||||
<loc type="col" start="2" repeat="13" priority="10"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
-->
|
||||
|
||||
</complexblocklist>
|
||||
|
||||
</architecture>
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
/* Xifan TANG: Spice support*/
|
||||
enum e_spice_tech_lib_type {
|
||||
SPICE_LIB_INDUSTRY,SPICE_LIB_ACADEMIA
|
||||
SPICE_LIB_INDUSTRY,
|
||||
SPICE_LIB_ACADEMIA
|
||||
};
|
||||
|
||||
enum spice_model_delay_type {
|
||||
|
@ -23,10 +24,9 @@ enum e_spice_model_type {
|
|||
SPICE_MODEL_HARDLOGIC,
|
||||
SPICE_MODEL_SCFF,
|
||||
SPICE_MODEL_IOPAD,
|
||||
SPICE_MODEL_VDD,
|
||||
SPICE_MODEL_GND,
|
||||
SPICE_MODEL_INVBUF,
|
||||
SPICE_MODEL_PASSGATE
|
||||
SPICE_MODEL_PASSGATE,
|
||||
SPICE_MODEL_GATE
|
||||
};
|
||||
|
||||
enum e_spice_model_design_tech {
|
||||
|
@ -47,13 +47,21 @@ enum e_spice_model_buffer_type {
|
|||
};
|
||||
|
||||
enum e_spice_model_pass_gate_logic_type {
|
||||
SPICE_MODEL_PASS_GATE_TRANSMISSION, SPICE_MODEL_PASS_GATE_TRANSISTOR
|
||||
SPICE_MODEL_PASS_GATE_TRANSMISSION,
|
||||
SPICE_MODEL_PASS_GATE_TRANSISTOR
|
||||
};
|
||||
|
||||
enum e_spice_model_gate_type {
|
||||
SPICE_MODEL_GATE_AND,
|
||||
SPICE_MODEL_GATE_OR
|
||||
};
|
||||
|
||||
/* Transistor-level basic informations*/
|
||||
enum e_spice_trans_type {
|
||||
SPICE_TRANS_NMOS, SPICE_TRANS_PMOS, SPICE_TRANS_IO_NMOS, SPICE_TRANS_IO_PMOS
|
||||
SPICE_TRANS_NMOS,
|
||||
SPICE_TRANS_PMOS,
|
||||
SPICE_TRANS_IO_NMOS,
|
||||
SPICE_TRANS_IO_PMOS
|
||||
};
|
||||
|
||||
enum e_wire_model_type {
|
||||
|
@ -73,6 +81,13 @@ enum e_spice_model_port_type {
|
|||
SPICE_MODEL_PORT_WLB
|
||||
};
|
||||
|
||||
/* For process corner */
|
||||
enum e_process_corner {
|
||||
BEST_CORNER,
|
||||
TYPICAL_CORNER,
|
||||
WORST_CORNER
|
||||
};
|
||||
|
||||
/* For SRAM */
|
||||
enum e_sram_orgz {
|
||||
SPICE_SRAM_STANDALONE,
|
||||
|
@ -84,24 +99,54 @@ enum e_spice_accuracy_type {
|
|||
SPICE_FRAC, SPICE_ABS
|
||||
};
|
||||
|
||||
enum e_spice_pb_port_type {
|
||||
SPICE_PB_PORT_INPUT,
|
||||
SPICE_PB_PORT_OUTPUT,
|
||||
SPICE_PB_PORT_CLOCK
|
||||
};
|
||||
|
||||
enum e_spice_ff_trigger_type {
|
||||
FF_RE, FF_FE
|
||||
};
|
||||
|
||||
enum e_spice_tb_type {
|
||||
SPICE_CB_MUX_TB,
|
||||
SPICE_SB_MUX_TB,
|
||||
SPICE_PB_MUX_TB,
|
||||
SPICE_GRID_TB,
|
||||
SPICE_SB_TB,
|
||||
SPICE_CB_TB,
|
||||
SPICE_LUT_TB,
|
||||
SPICE_IO_TB,
|
||||
SPICE_HARDLOGIC_TB
|
||||
};
|
||||
|
||||
enum e_spice_pin2pin_interc_type {
|
||||
INPUT2INPUT_INTERC,
|
||||
OUTPUT2OUTPUT_INTERC
|
||||
};
|
||||
|
||||
/* typedef of structs */
|
||||
typedef struct s_spice_transistor_type t_spice_transistor_type;
|
||||
typedef struct s_spice_tech_lib t_spice_tech_lib;
|
||||
typedef struct s_spice_model_gate t_spice_model_gate;
|
||||
typedef struct s_spice_model_rram t_spice_model_rram;
|
||||
typedef struct s_spice_model_mux t_spice_model_mux;
|
||||
typedef struct s_spice_model_lut t_spice_model_lut;
|
||||
typedef struct s_spice_model_buffer t_spice_model_buffer;
|
||||
typedef struct s_spice_model_pass_gate_logic t_spice_model_pass_gate_logic;
|
||||
typedef struct s_spice_model_port t_spice_model_port;
|
||||
typedef struct s_spice_model_wire_param t_spice_model_wire_param;
|
||||
typedef struct s_spice_model_tedge t_spice_model_tedge;
|
||||
typedef struct s_spice_model_netlist t_spice_model_netlist;
|
||||
typedef struct s_spice_model_design_tech_info t_spice_model_design_tech_info;
|
||||
typedef struct s_spice_model_delay_info t_spice_model_delay_info;
|
||||
typedef struct s_spice_model t_spice_model;
|
||||
typedef struct s_spice_meas_params t_spice_meas_params;
|
||||
typedef struct s_spice_stimulate_params t_spice_stimulate_params;
|
||||
typedef struct s_spice_mc_variation_params t_spice_mc_variation_params;
|
||||
typedef struct s_spice_model_delay_info t_spice_model_delay_info;
|
||||
typedef struct s_spice_mc_params t_spice_mc_params;
|
||||
typedef struct s_spice_params t_spice_params;
|
||||
typedef struct s_spice_model_tedge t_spice_model_tedge;
|
||||
typedef struct s_spice t_spice;
|
||||
typedef struct s_spice_mux_arch t_spice_mux_arch;
|
||||
typedef struct s_spice_mux_model t_spice_mux_model;
|
||||
|
@ -135,13 +180,15 @@ struct s_spice_tech_lib {
|
|||
|
||||
struct s_spice_model_buffer {
|
||||
int exist;
|
||||
char* spice_model_name;
|
||||
char* location_map;
|
||||
|
||||
t_spice_model* spice_model;
|
||||
enum e_spice_model_buffer_type type;
|
||||
float size;
|
||||
int tapered_buf; /*Valid only when this is a buffer*/
|
||||
int tap_buf_level;
|
||||
int f_per_stage;
|
||||
char* spice_model_name;
|
||||
t_spice_model* spice_model;
|
||||
};
|
||||
|
||||
struct s_spice_model_pass_gate_logic {
|
||||
|
@ -166,17 +213,27 @@ struct s_spice_model_port {
|
|||
enum e_spice_model_port_type type;
|
||||
int size;
|
||||
char* prefix;
|
||||
char* lib_name;
|
||||
char* inv_prefix;
|
||||
/* Mode select port properties */
|
||||
boolean mode_select;
|
||||
int default_val;
|
||||
/* Global port properties */
|
||||
boolean is_global;
|
||||
boolean is_reset;
|
||||
boolean is_set;
|
||||
boolean is_config_enable;
|
||||
boolean is_prog;
|
||||
/* The spice model that this port will be connected to */
|
||||
char* spice_model_name;
|
||||
t_spice_model* spice_model;
|
||||
char* inv_spice_model_name;
|
||||
t_spice_model* inv_spice_model;
|
||||
/* Tri-state map */
|
||||
char* tri_state_map;
|
||||
/* For frac_lut only */
|
||||
int lut_frac_level;
|
||||
int* lut_output_mask;
|
||||
/* Timing edeges linked to other t_model_ports */
|
||||
int* num_tedges; /* 1-D Array, show number of tedges of each pin */
|
||||
t_spice_model_tedge*** tedge; /* 3-D array, considering the each pin in this port, [pin_number][num_edges[iedge]] is an edge pointor */
|
||||
|
@ -194,18 +251,7 @@ struct s_spice_model_netlist {
|
|||
int included;
|
||||
};
|
||||
|
||||
struct s_spice_model_delay_info {
|
||||
enum spice_model_delay_type type;
|
||||
char* in_port_name;
|
||||
char* out_port_name;
|
||||
char* value;
|
||||
};
|
||||
|
||||
/* Information about design technology */
|
||||
struct s_spice_model_design_tech_info {
|
||||
/* Valid for SRAM technology */
|
||||
t_spice_model_buffer* buffer_info;
|
||||
t_spice_model_pass_gate_logic* pass_gate_info;
|
||||
struct s_spice_model_rram {
|
||||
/* Vaild for RRAM technology only, and this is a mux*/
|
||||
float ron;
|
||||
float roff;
|
||||
|
@ -213,12 +259,45 @@ struct s_spice_model_design_tech_info {
|
|||
float wprog_set_pmos;
|
||||
float wprog_reset_nmos;
|
||||
float wprog_reset_pmos;
|
||||
};
|
||||
|
||||
struct s_spice_model_mux {
|
||||
/* Mux information only */
|
||||
enum e_spice_model_structure structure;
|
||||
int mux_num_level;
|
||||
boolean add_const_input;
|
||||
int const_input_val;
|
||||
boolean advanced_rram_design;
|
||||
};
|
||||
|
||||
struct s_spice_model_lut {
|
||||
/* LUT information */
|
||||
boolean frac_lut;
|
||||
};
|
||||
|
||||
struct s_spice_model_gate {
|
||||
/* LUT information */
|
||||
enum e_spice_model_gate_type type;
|
||||
};
|
||||
|
||||
/* Information about design technology */
|
||||
struct s_spice_model_design_tech_info {
|
||||
/* Valid for SRAM technology */
|
||||
t_spice_model_buffer* buffer_info;
|
||||
t_spice_model_pass_gate_logic* pass_gate_info;
|
||||
t_spice_model_rram* rram_info;
|
||||
t_spice_model_mux* mux_info;
|
||||
t_spice_model_lut* lut_info;
|
||||
t_spice_model_gate* gate_info;
|
||||
/* Power gate information */
|
||||
boolean power_gated;
|
||||
boolean advanced_rram_design;
|
||||
};
|
||||
|
||||
struct s_spice_model_delay_info {
|
||||
enum spice_model_delay_type type;
|
||||
char* in_port_name;
|
||||
char* out_port_name;
|
||||
char* value;
|
||||
};
|
||||
|
||||
struct s_spice_model {
|
||||
|
@ -230,6 +309,7 @@ struct s_spice_model {
|
|||
t_spice_model_netlist* include_netlist;
|
||||
int is_default;
|
||||
boolean dump_structural_verilog;
|
||||
boolean dump_explicit_port_map;
|
||||
|
||||
/* type */
|
||||
enum e_spice_model_design_tech design_tech;
|
||||
|
@ -238,6 +318,8 @@ struct s_spice_model {
|
|||
|
||||
/* buffering information */
|
||||
t_spice_model_buffer* lut_input_buffer;
|
||||
t_spice_model_buffer* lut_input_inverter;
|
||||
t_spice_model_buffer* lut_intermediate_buffer;
|
||||
t_spice_model_buffer* input_buffer;
|
||||
t_spice_model_buffer* output_buffer;
|
||||
t_spice_model_pass_gate_logic* pass_gate_logic;
|
||||
|
@ -357,7 +439,8 @@ struct s_spice {
|
|||
/* Information needed to build a Multiplexer architecture*/
|
||||
struct s_spice_mux_arch {
|
||||
enum e_spice_model_structure structure;
|
||||
int num_input;
|
||||
int num_input; /* All Inputs including those connect to constant generator */
|
||||
int num_data_input; /* Inputs for multiplexing datapath signals*/
|
||||
int num_level;
|
||||
int num_input_basis;
|
||||
int num_input_last_level;
|
||||
|
@ -483,6 +566,8 @@ struct s_sram_orgz_info {
|
|||
t_llist* conf_bit_head;
|
||||
|
||||
/* Conf bits information per grid */
|
||||
int grid_nx; /* grid size */
|
||||
int grid_ny;
|
||||
int** grid_reserved_conf_bits;
|
||||
int** grid_conf_bits_lsb;
|
||||
int** grid_conf_bits_msb;
|
||||
|
|
|
@ -241,6 +241,7 @@ struct s_pb_type;
|
|||
* port_index_by_type index of port by type (index by input, output, or clock)
|
||||
* equivalence:
|
||||
*/
|
||||
typedef struct s_port t_port;
|
||||
struct s_port {
|
||||
char* name;
|
||||
t_model_ports *model_port;
|
||||
|
@ -262,8 +263,14 @@ struct s_port {
|
|||
/* FPGA_SPICE_model support:
|
||||
* mapped SPICE model port */
|
||||
t_spice_model_port* spice_model_port;
|
||||
char* physical_mode_pin;
|
||||
int physical_mode_pin_rotate_offset; /* The pin number will rotate by an offset unit when mapping to physical modes */
|
||||
int phy_mode_pin_rotate_offset_acc; /* The pin number will rotate by an offset unit when mapping to physical modes */
|
||||
t_port* phy_pb_type_port;
|
||||
int phy_pb_type_port_lsb;
|
||||
int phy_pb_type_port_msb;
|
||||
/* END */
|
||||
};
|
||||
typedef struct s_port t_port;
|
||||
|
||||
/**
|
||||
* Info placed between pins that can be processed later for additional information
|
||||
|
@ -310,6 +317,9 @@ struct s_interconnect {
|
|||
|
||||
char *input_string;
|
||||
char *output_string;
|
||||
/* Baudouin Chauviere: SDC generation */
|
||||
char *loop_breaker_string;
|
||||
/* END */
|
||||
|
||||
t_pin_to_pin_annotation *annotations; /* [0..num_annotations-1] */
|
||||
int num_annotations;
|
||||
|
@ -328,6 +338,7 @@ struct s_interconnect {
|
|||
int fan_in;
|
||||
int fan_out;
|
||||
int num_mux;
|
||||
int spice_model_sram_offset;
|
||||
/* END */
|
||||
|
||||
t_interconnect_power * interconnect_power;
|
||||
|
@ -376,7 +387,7 @@ struct s_mode {
|
|||
*/
|
||||
int define_idle_mode;
|
||||
int define_physical_mode;
|
||||
int disabled_in_packing;
|
||||
boolean disabled_in_packing;
|
||||
|
||||
/* Power releated members */
|
||||
t_mode_power * mode_power;
|
||||
|
@ -396,6 +407,8 @@ enum e_pb_graph_pin_type {
|
|||
PB_PIN_INPAD,
|
||||
PB_PIN_OUTPAD,
|
||||
PB_PIN_TERMINAL,
|
||||
PB_PIN_INPUT,
|
||||
PB_PIN_OUTPUT,
|
||||
PB_PIN_CLOCK
|
||||
};
|
||||
|
||||
|
@ -409,6 +422,7 @@ enum e_pb_graph_pin_type {
|
|||
* parent_node: parent pb_graph_node
|
||||
* pin_count_in_cluster: Unique number for pin inside cluster
|
||||
*/
|
||||
typedef struct s_pb_graph_pin t_pb_graph_pin;
|
||||
struct s_pb_graph_pin {
|
||||
t_port *port;
|
||||
int pin_number;
|
||||
|
@ -421,6 +435,10 @@ struct s_pb_graph_pin {
|
|||
int pin_count_in_cluster;
|
||||
/* Xifan TANG: FPGA-SPICE */
|
||||
int temp_net_num;
|
||||
int rr_node_index_physical_pb; /* rr_node in the physical pb rr_graph*/
|
||||
t_pb_graph_pin* physical_pb_graph_pin;
|
||||
char* name_mux;
|
||||
/* END */
|
||||
|
||||
int scratch_pad; /* temporary data structure useful to store traversal info */
|
||||
|
||||
|
@ -444,7 +462,6 @@ struct s_pb_graph_pin {
|
|||
|
||||
t_pb_graph_pin_power * pin_power;
|
||||
};
|
||||
typedef struct s_pb_graph_pin t_pb_graph_pin;
|
||||
|
||||
struct s_pb_graph_pin_power {
|
||||
/* Transistor-level Power Properties */
|
||||
|
@ -524,6 +541,11 @@ struct s_pb_graph_edge {
|
|||
int num_pack_patterns;
|
||||
boolean infer_pattern; /*If TRUE, infer pattern based on patterns connected to it*/
|
||||
|
||||
/* Baudouin Chauviere: SDC Generation */
|
||||
boolean is_disabled;
|
||||
int nb_mux;
|
||||
int nb_pin;
|
||||
/* END */
|
||||
};
|
||||
typedef struct s_pb_graph_edge t_pb_graph_edge;
|
||||
|
||||
|
@ -573,6 +595,10 @@ struct s_pb_graph_node {
|
|||
t_pb_graph_node_power * pb_node_power;
|
||||
t_interconnect_pins ** interconnect_pins; /* [0..num_modes-1][0..num_interconnect_in_mode] */
|
||||
|
||||
/* Xifan Tang: FPGA-SPICE */
|
||||
t_pb_graph_node* physical_pb_graph_node; /* physical pb_graph_node */
|
||||
int placement_index_in_top_node; /* index at the top-level pb_graph node */
|
||||
/* END */
|
||||
};
|
||||
|
||||
struct s_pb_graph_node_power {
|
||||
|
@ -623,6 +649,13 @@ struct s_pb_type {
|
|||
char* spice_model_name;
|
||||
t_spice_model* spice_model;
|
||||
char* mode_bits; /* Mode bits to select */
|
||||
int spice_model_sram_offset;
|
||||
char* physical_pb_type_name;
|
||||
struct s_pb_type* phy_pb_type;
|
||||
float physical_pb_type_index_factor;
|
||||
int physical_pb_type_index_offset;
|
||||
int temp_placement_index;
|
||||
/* END */
|
||||
|
||||
/* Power related members */
|
||||
t_pb_type_power * pb_type_power;
|
||||
|
@ -636,6 +669,7 @@ struct s_pb_type {
|
|||
int default_mode_num_conf_bits;
|
||||
int default_mode_num_mode_bits;
|
||||
int default_mode_num_iopads;
|
||||
/* END */
|
||||
};
|
||||
typedef struct s_pb_type t_pb_type;
|
||||
|
||||
|
|
|
@ -927,6 +927,19 @@ static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type * pb_type,
|
|||
pb_type->num_pb = GetIntProperty(Parent, "num_pb", TRUE, 0);
|
||||
}
|
||||
|
||||
/* Xifan TANG: FPGA_SPICE, multi-mode support */
|
||||
Prop = FindProperty(Parent, "physical_pb_type_name", FALSE);
|
||||
pb_type->physical_pb_type_name = my_strdup(Prop);
|
||||
ezxml_set_attr(Parent, "physical_pb_type_name", NULL);
|
||||
|
||||
pb_type->physical_pb_type_index_factor = GetFloatProperty(Parent, "physical_pb_type_index_factor", FALSE, 1.0);
|
||||
ezxml_set_attr(Parent, "physical_pb_type_index_factor", NULL);
|
||||
|
||||
pb_type->physical_pb_type_index_offset = GetIntProperty(Parent, "physical_pb_type_index_offset", FALSE, 0);
|
||||
ezxml_set_attr(Parent, "physical_pb_type_index_offset", NULL);
|
||||
|
||||
/* END */
|
||||
|
||||
assert(pb_type->num_pb > 0);
|
||||
num_ports = 0;
|
||||
num_ports += CountChildren(Parent, "input", 0);
|
||||
|
@ -1004,14 +1017,20 @@ static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type * pb_type,
|
|||
* We should have a spice_model_name if this mode defines the transistor-level circuit design
|
||||
* Since this is a leaf node
|
||||
*/
|
||||
pb_type->spice_model_name = my_strdup(FindProperty(Parent, "circuit_model_name", FALSE));
|
||||
pb_type->spice_model_name = my_strdup(FindProperty(Parent, "spice_model_name", FALSE));
|
||||
pb_type->spice_model = NULL;
|
||||
ezxml_set_attr(Parent,"circuit_model_name",NULL);
|
||||
/* We can read the mode configuration bits if they are defined */
|
||||
if (NULL != pb_type->spice_model_name) {
|
||||
pb_type->mode_bits = my_strdup(FindProperty(Parent, "mode_bits", FALSE));
|
||||
ezxml_set_attr(Parent,"mode_bits",NULL);
|
||||
}
|
||||
ezxml_set_attr(Parent, "spice_model_name", NULL);
|
||||
/* Multi-mode CLB support:
|
||||
* We can read the mode configuration bits if they are defined
|
||||
*/
|
||||
pb_type->mode_bits = my_strdup(FindProperty(Parent, "mode_bits", FALSE));
|
||||
ezxml_set_attr(Parent, "mode_bits", NULL);
|
||||
/* Multi-mode CLB support:
|
||||
* Specify the offset in sram bits of a spice_model
|
||||
* This will determine which SRAMs will be configured by this pb_type configuration bits
|
||||
*/
|
||||
pb_type->spice_model_sram_offset = GetIntProperty(Parent, "spice_model_sram_offset", FALSE, 0);
|
||||
ezxml_set_attr(Parent, "spice_model_sram_offset", NULL);
|
||||
/* End Spice Model Support*/
|
||||
|
||||
/* Determine if this is a leaf or container pb_type */
|
||||
|
@ -1090,8 +1109,17 @@ static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type * pb_type,
|
|||
* We don't need to search the spice_model_mode_name at this level.
|
||||
* There is only one mode, so it should herit.
|
||||
*/
|
||||
if (do_spice) {
|
||||
/* We need to identify the physical mode that refers to physical design interests */
|
||||
pb_type->idle_mode_name = my_strdup(FindProperty(Parent,"idle_mode_name", FALSE));
|
||||
ezxml_set_attr(Parent,"idle_mode_name",NULL);
|
||||
if (NULL == pb_type->idle_mode_name) {
|
||||
pb_type->idle_mode_name = my_strdup(pb_type->name);
|
||||
}
|
||||
/* Only when the parent mode is a physical mode, we can do this */
|
||||
pb_type->physical_mode_name = my_strdup(FindProperty(Parent, "physical_mode_name", FALSE));
|
||||
ezxml_set_attr(Parent,"physical_mode_name",NULL);
|
||||
if (((NULL == pb_type->physical_mode_name) && (NULL == pb_type->parent_mode))
|
||||
|| ((NULL == pb_type->physical_mode_name) && (NULL != pb_type->parent_mode) && (1 == pb_type->parent_mode->define_physical_mode))) {
|
||||
pb_type->physical_mode_name = my_strdup(pb_type->name);
|
||||
}
|
||||
/*END*/
|
||||
|
@ -1110,12 +1138,7 @@ static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type * pb_type,
|
|||
}
|
||||
ezxml_set_attr(Parent,"idle_mode_name",NULL);
|
||||
/* We need to identify the physical mode that refers to physical design interests */
|
||||
if (FindProperty(Parent,"physical_mode_name", do_spice)) {
|
||||
pb_type->physical_mode_name = my_strdup(FindProperty(Parent,"physical_mode_name",TRUE));
|
||||
} else if (do_spice) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d]Pb_Type has more than 1 mode, should define a physical_mode_name.\n",Parent->line);
|
||||
exit(1);
|
||||
}
|
||||
pb_type->physical_mode_name = my_strdup(FindProperty(Parent,"physical_mode_name", FALSE));
|
||||
ezxml_set_attr(Parent,"physical_mode_name",NULL);
|
||||
/*END*/
|
||||
pb_type->modes = (t_mode*) my_calloc(pb_type->num_modes,
|
||||
|
@ -1268,11 +1291,21 @@ static void ProcessPb_TypePort(INOUTP ezxml_t Parent, t_port * port,
|
|||
ezxml_set_attr(Parent, "chain", NULL);
|
||||
|
||||
port->equivalent = GetBooleanProperty(Parent, "equivalent", FALSE, FALSE);
|
||||
ezxml_set_attr(Parent, "equivalent", NULL);
|
||||
|
||||
port->num_pins = GetIntProperty(Parent, "num_pins", TRUE, 0);
|
||||
port->is_non_clock_global = GetBooleanProperty(Parent,
|
||||
"is_non_clock_global", FALSE, FALSE);
|
||||
|
||||
/* FPGA-SPICE multi-mode CLB support */
|
||||
Prop = FindProperty(Parent, "physical_mode_pin", FALSE);
|
||||
port->physical_mode_pin = my_strdup(Prop);
|
||||
ezxml_set_attr(Parent, "physical_mode_pin", NULL);
|
||||
|
||||
port->physical_mode_pin_rotate_offset = GetIntProperty(Parent, "physical_mode_pin_rotate_offset", FALSE, 0);
|
||||
ezxml_set_attr(Parent, "physical_mode_pin_rotate_offset", NULL);
|
||||
/* END */
|
||||
|
||||
if (0 == strcmp(Parent->name, "input")) {
|
||||
port->type = IN_PORT;
|
||||
port->is_clock = FALSE;
|
||||
|
@ -1330,8 +1363,9 @@ static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode * mode) {
|
|||
mode->interconnect[i].type = MUX_INTERC;
|
||||
}
|
||||
|
||||
|
||||
/* Xifan TANG: SPICE Support */
|
||||
Prop = FindProperty(Cur, "circuit_model_name", FALSE);
|
||||
Prop = FindProperty(Cur, "spice_model_name", FALSE);
|
||||
/* Default spice_model will be define later*/
|
||||
mode->interconnect[i].spice_model_name = my_strdup(Prop);
|
||||
mode->interconnect[i].spice_model = NULL;
|
||||
|
@ -1339,7 +1373,10 @@ static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode * mode) {
|
|||
mode->interconnect[i].fan_in = 0;
|
||||
mode->interconnect[i].fan_out = 0;
|
||||
mode->interconnect[i].num_mux = 0;
|
||||
ezxml_set_attr(Cur, "circuit_model_name", NULL);
|
||||
ezxml_set_attr(Cur, "spice_model_name", NULL);
|
||||
/* Get sram offset */
|
||||
mode->interconnect[i].spice_model_sram_offset = GetIntProperty(Cur, "spice_model_sram_offset", FALSE, 0);
|
||||
ezxml_set_attr(Cur, "spice_model_sram_offset", NULL);
|
||||
/* END */
|
||||
|
||||
mode->interconnect[i].line_num = Cur->line;
|
||||
|
@ -1359,6 +1396,23 @@ static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode * mode) {
|
|||
mode->interconnect[i].name = my_strdup(Prop);
|
||||
ezxml_set_attr(Cur, "name", NULL);
|
||||
|
||||
/* Baudouin Chauviere: SDC generation */
|
||||
/* Check if property exists */
|
||||
if (Prop = FindProperty(Cur, "loop_breaker", FALSE)) {
|
||||
/* Check if property exists and is true */
|
||||
/*if (0 == strcmp(Prop,"TRUE") || 0 == strcmp(Prop,"true")) {*/
|
||||
if (0 == strcmp(Cur->name, "direct")) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"[Line %d] loop_breaker not supported for '%s'.\n",
|
||||
Parent->line, Cur->name);
|
||||
exit(1);
|
||||
}
|
||||
//if (
|
||||
mode->interconnect[i].loop_breaker_string= my_strdup(Prop);
|
||||
}
|
||||
ezxml_set_attr(Cur, "loop_breaker", NULL);
|
||||
/* END */
|
||||
|
||||
/* Process delay and capacitance annotations */
|
||||
num_annotations = 0;
|
||||
num_annotations += CountChildren(Cur, "delay_constant", 0);
|
||||
|
@ -1366,7 +1420,7 @@ static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode * mode) {
|
|||
num_annotations += CountChildren(Cur, "C_constant", 0);
|
||||
num_annotations += CountChildren(Cur, "C_matrix", 0);
|
||||
num_annotations += CountChildren(Cur, "pack_pattern", 0);
|
||||
/* Xifan TANG: FPGA-SPICE, mode select description */
|
||||
/* Xifan TANG: FPGA-SPICE, mode select description for multi-mode CLB */
|
||||
num_annotations += CountChildren(Cur, "mode_select", 0);
|
||||
/* END FPGA-SPICE, mode select description */
|
||||
|
||||
|
@ -1448,31 +1502,43 @@ static void ProcessMode(INOUTP ezxml_t Parent, t_mode * mode,
|
|||
* The mode should herit the define_spice_model from its parent
|
||||
*/
|
||||
if (do_spice) {
|
||||
if (0 == strcmp(mode->name, mode->parent_pb_type->idle_mode_name)) {
|
||||
if (NULL == mode->parent_pb_type->parent_mode) {
|
||||
mode->define_idle_mode = 1;
|
||||
if (0 == strcmp(mode->name, mode->parent_pb_type->idle_mode_name)) {
|
||||
if (NULL == mode->parent_pb_type->parent_mode) {
|
||||
mode->define_idle_mode = 1;
|
||||
} else {
|
||||
mode->define_idle_mode = mode->parent_pb_type->parent_mode->define_idle_mode;
|
||||
}
|
||||
} else {
|
||||
mode->define_idle_mode = mode->parent_pb_type->parent_mode->define_idle_mode;
|
||||
mode->define_idle_mode = 0;
|
||||
}
|
||||
} else {
|
||||
mode->define_idle_mode = 0;
|
||||
}
|
||||
/* For physical design mode */
|
||||
if (0 == strcmp(mode->name, mode->parent_pb_type->physical_mode_name)) {
|
||||
if (NULL == mode->parent_pb_type->parent_mode) {
|
||||
mode->define_physical_mode = 1;
|
||||
/* For physical design mode
|
||||
* This is different from idle mode:
|
||||
* If the parent is not a physical mode, then this is definitely not a physical mode
|
||||
*/
|
||||
if (NULL == mode->parent_pb_type->physical_mode_name) {
|
||||
mode->define_physical_mode = 0;
|
||||
} else {
|
||||
mode->define_physical_mode = mode->parent_pb_type->parent_mode->define_physical_mode;
|
||||
if (0 == strcmp(mode->name, mode->parent_pb_type->physical_mode_name)) {
|
||||
if (NULL == mode->parent_pb_type->parent_mode) {
|
||||
mode->define_physical_mode = 1;
|
||||
} else {
|
||||
mode->define_physical_mode = mode->parent_pb_type->parent_mode->define_physical_mode;
|
||||
}
|
||||
} else {
|
||||
mode->define_physical_mode = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mode->define_physical_mode = 0;
|
||||
}
|
||||
}
|
||||
/* Spice Model Support: Xifan TANG
|
||||
* More option: specify if this mode is available during packing
|
||||
*/
|
||||
mode->disabled_in_packing = GetBooleanProperty(Parent, "disabled_in_packing", FALSE, FALSE);
|
||||
ezxml_set_attr(Parent, "disabled_in_packing", NULL);
|
||||
mode->disabled_in_packing = FALSE; /* Default should be FALSE */
|
||||
if (NULL != mode->parent_pb_type->parent_mode) {
|
||||
/* If the parent mode is disabled in packing, all the child mode should be disabled as well */
|
||||
mode->disabled_in_packing = mode->parent_pb_type->parent_mode->disabled_in_packing;
|
||||
}
|
||||
/* Override if the user specify */
|
||||
mode->disabled_in_packing = GetBooleanProperty(Parent, "disabled_in_packing", FALSE, mode->disabled_in_packing);
|
||||
/* END */
|
||||
|
||||
mode->num_pb_type_children = CountChildren(Parent, "pb_type", 0);
|
||||
|
@ -2220,7 +2286,10 @@ void ProcessLutClass(INOUTP t_pb_type *lut_pb_type) {
|
|||
lut_pb_type->modes[0].mode_power = (t_mode_power*) my_calloc(1,
|
||||
sizeof(t_mode_power));
|
||||
/* Xifan TANG: LUT default idle mode */
|
||||
lut_pb_type->modes[0].define_idle_mode = 1;
|
||||
lut_pb_type->modes[0].define_idle_mode = 0;
|
||||
/* Xifan TANG: LUT default physical mode: special for LUT: mode 1 should never to be true */
|
||||
lut_pb_type->modes[0].define_physical_mode = FALSE;
|
||||
/* END */
|
||||
|
||||
/* Process interconnect */
|
||||
/* TODO: add timing annotations to route-through */
|
||||
|
@ -2310,7 +2379,8 @@ void ProcessLutClass(INOUTP t_pb_type *lut_pb_type) {
|
|||
lut_pb_type->modes[1].pb_type_children);
|
||||
|
||||
/* Xifan TANG: LUT default idle mode */
|
||||
lut_pb_type->modes[1].define_idle_mode = 0;
|
||||
lut_pb_type->modes[1].define_idle_mode = 1;
|
||||
lut_pb_type->modes[1].define_physical_mode = lut_pb_type->parent_mode->define_physical_mode;
|
||||
/* moved annotations to child so delete old annotations */
|
||||
for (i = 0; i < lut_pb_type->num_annotations; i++) {
|
||||
for (j = 0; j < lut_pb_type->annotations[i].num_value_prop_pairs; j++) {
|
||||
|
@ -2452,6 +2522,7 @@ static void ProcessMemoryClass(INOUTP t_pb_type *mem_pb_type) {
|
|||
|
||||
/* Xifan TANG: Memory default idle mode */
|
||||
mem_pb_type->modes[0].define_idle_mode = 1;
|
||||
mem_pb_type->modes[0].define_physical_mode = mem_pb_type->parent_mode->define_physical_mode;
|
||||
|
||||
/* Process interconnect */
|
||||
i_inter = 0;
|
||||
|
@ -2758,7 +2829,18 @@ void XmlReadArch(INP const char *ArchFile, INP boolean timing_enabled,
|
|||
/* Xifan TANG: HSPICE Support*/
|
||||
Next = FindElement(Cur,"spice_settings", arch->read_xml_spice); // Not mandatory options but we will check it later
|
||||
if (Next) {
|
||||
ProcessSpiceSettings(Next,arch->spice);
|
||||
/* This information still needs to be read, even if it is just
|
||||
* thrown away.
|
||||
*/
|
||||
/* Allocate */
|
||||
if (TRUE == arch->read_xml_spice) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Parsing XML syntax for FPGA X2P...\n");
|
||||
ProcessSpiceSettings(Next,arch->spice);
|
||||
} else {
|
||||
t_spice* spice_fake = (t_spice*) my_calloc(1, sizeof(t_spice));
|
||||
ProcessSpiceSettings(Next, spice_fake);
|
||||
free(spice_fake);
|
||||
}
|
||||
FreeNode(Next);
|
||||
}
|
||||
/* end */
|
||||
|
@ -3056,9 +3138,9 @@ static void ProcessSegments(INOUTP ezxml_t Parent,
|
|||
(*Segs)[i].Rmetal = GetFloatProperty(Node, "Rmetal", timing_enabled, 0);
|
||||
(*Segs)[i].Cmetal = GetFloatProperty(Node, "Cmetal", timing_enabled, 0);
|
||||
/* Xifan TANG: SPICE Model Support*/
|
||||
(*Segs)[i].spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", FALSE));
|
||||
(*Segs)[i].spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", FALSE));
|
||||
(*Segs)[i].spice_model = NULL;
|
||||
ezxml_set_attr(Node, "circuit_model_name", NULL);
|
||||
ezxml_set_attr(Node, "spice_model_name", NULL);
|
||||
/* Get Power info */
|
||||
/*
|
||||
(*Segs)[i].Cmetal_per_m = GetFloatProperty(Node, "Cmetal_per_m", FALSE,
|
||||
|
@ -3334,9 +3416,9 @@ static void ProcessSwitches(INOUTP ezxml_t Parent,
|
|||
FALSE, 1);
|
||||
|
||||
/* Xifan TANG: Spice Model Support */
|
||||
(*Switches)[i].spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", FALSE));
|
||||
(*Switches)[i].spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", FALSE));
|
||||
(*Switches)[i].spice_model = NULL;
|
||||
ezxml_set_attr(Node, "circuit_model_name", NULL);
|
||||
ezxml_set_attr(Node, "spice_model_name", NULL);
|
||||
/* Xifan TANG : Read in MUX structure*/
|
||||
/* Default, we use tree */
|
||||
structure_type = FindProperty(Node, "structure", FALSE);
|
||||
|
@ -3449,9 +3531,9 @@ static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs,
|
|||
/* Spice Model Support: Xifan TANG
|
||||
* We should have a spice_model_name for this direct connection
|
||||
*/
|
||||
(*Directs)[i].spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", FALSE));
|
||||
(*Directs)[i].spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", FALSE));
|
||||
(*Directs)[i].spice_model = NULL;
|
||||
ezxml_set_attr(Node,"circuit_model_name",NULL);
|
||||
ezxml_set_attr(Node,"spice_model_name",NULL);
|
||||
|
||||
|
||||
(*Directs)[i].line = Node->line;
|
||||
|
|
|
@ -451,8 +451,8 @@ static void ProcessSpiceModelBuffer(ezxml_t Node,
|
|||
read_spice_model = FALSE;
|
||||
}
|
||||
|
||||
buffer->spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", read_spice_model));
|
||||
ezxml_set_attr(Node, "circuit_model_name", NULL);
|
||||
buffer->spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", read_spice_model));
|
||||
ezxml_set_attr(Node, "spice_model_name", NULL);
|
||||
|
||||
/*Find Type*/
|
||||
Prop = my_strdup(FindProperty(Node, "topology", read_buf_info));
|
||||
|
@ -475,9 +475,9 @@ static void ProcessSpiceModelBuffer(ezxml_t Node,
|
|||
if (0 == strcmp(Prop,"on")) {
|
||||
buffer->tapered_buf = 1;
|
||||
/* Try to dig more properites ...*/
|
||||
buffer->tap_buf_level = GetIntProperty(Node, "tap_drive_level", TRUE, 1);
|
||||
buffer->tap_buf_level = GetIntProperty(Node, "tap_buf_level", TRUE, 1);
|
||||
buffer->f_per_stage = GetIntProperty(Node, "f_per_stage", FALSE, 4);
|
||||
ezxml_set_attr(Node, "tap_drive_level", NULL);
|
||||
ezxml_set_attr(Node, "tap_buf_level", NULL);
|
||||
ezxml_set_attr(Node, "f_per_stage", NULL);
|
||||
} else if (0 == strcmp(FindProperty(Node,"tapered",TRUE),"off")) {
|
||||
buffer->tapered_buf = 0;
|
||||
|
@ -493,6 +493,10 @@ static void ProcessSpiceModelBuffer(ezxml_t Node,
|
|||
buffer->size = GetFloatProperty(Node, "size", read_buf_info, 0.);
|
||||
ezxml_set_attr(Node, "size", NULL);
|
||||
|
||||
/* Read location map */
|
||||
buffer->location_map = my_strdup(FindProperty(Node, "location_map", FALSE));
|
||||
ezxml_set_attr(Node, "location_map", NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -521,8 +525,151 @@ static void ProcessSpiceModelPassGateLogic(ezxml_t Node,
|
|||
return;
|
||||
}
|
||||
|
||||
static void ProcessSpiceModelRRAM(ezxml_t Node,
|
||||
t_spice_model_rram* rram_info) {
|
||||
rram_info->ron = GetFloatProperty(Node,"ron",TRUE,0);
|
||||
ezxml_set_attr(Node, "ron", NULL);
|
||||
|
||||
rram_info->roff = GetFloatProperty(Node,"roff",TRUE,0);
|
||||
ezxml_set_attr(Node, "roff", NULL);
|
||||
|
||||
rram_info->wprog_set_nmos = GetFloatProperty(Node,"wprog_set_nmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_set_nmos", NULL);
|
||||
|
||||
rram_info->wprog_set_pmos = GetFloatProperty(Node,"wprog_set_pmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_set_nmos", NULL);
|
||||
|
||||
rram_info->wprog_reset_nmos = GetFloatProperty(Node,"wprog_reset_nmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_reset_nmos", NULL);
|
||||
|
||||
rram_info->wprog_reset_pmos = GetFloatProperty(Node,"wprog_reset_pmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_reset_pmos", NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ProcessSpiceModelMUX(ezxml_t Node,
|
||||
t_spice_model* spice_model,
|
||||
t_spice_model_mux* mux_info) {
|
||||
/* Default: tree, no const_inputs */
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
mux_info->add_const_input = FALSE;
|
||||
mux_info->const_input_val = 0;
|
||||
|
||||
if (0 == strcmp(FindProperty(Node,"structure",TRUE),"tree")) {
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
} else if (0 == strcmp(FindProperty(Node,"structure",TRUE),"one-level")) {
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
|
||||
} else if (0 == strcmp(FindProperty(Node,"structure",TRUE),"multi-level")) {
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_MULTILEVEL;
|
||||
/* New Structure: crossbar
|
||||
} else if (0 == strcmp(FindProperty(Node,"structure",TRUE),"crossbar")) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_CROSSBAR;
|
||||
*/
|
||||
} else {
|
||||
/* Set default to RRAM MUX */
|
||||
if (SPICE_MODEL_DESIGN_RRAM == spice_model->design_tech) {
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
|
||||
} else {
|
||||
/* Set default to SRAM MUX */
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
}
|
||||
}
|
||||
/* Parse the const inputs */
|
||||
mux_info->add_const_input = GetBooleanProperty(Node, "add_const_input", FALSE, FALSE);
|
||||
mux_info->const_input_val = GetIntProperty(Node, "const_input_val", FALSE, 0);
|
||||
|
||||
ezxml_set_attr(Node, "structure", NULL);
|
||||
ezxml_set_attr(Node, "add_const_input", NULL);
|
||||
ezxml_set_attr(Node, "const_input_val", NULL);
|
||||
|
||||
if (SPICE_MODEL_STRUCTURE_MULTILEVEL == mux_info->structure) {
|
||||
mux_info->mux_num_level = GetIntProperty(Node,"num_level",TRUE,1);
|
||||
/* For num_level == 1, auto convert to one-level structure */
|
||||
if (1 == mux_info->mux_num_level) {
|
||||
mux_info->structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
|
||||
vpr_printf(TIO_MESSAGE_INFO,"[LINE%d] Automatically convert structure of spice model(%s) to one-level.\n",
|
||||
Node->line, spice_model->name);
|
||||
}
|
||||
} else if (SPICE_MODEL_STRUCTURE_ONELEVEL == mux_info->structure) {
|
||||
/* Set mux_num_level for other structure: one-level and tree */
|
||||
mux_info->mux_num_level = 1;
|
||||
}
|
||||
ezxml_set_attr(Node, "num_level", NULL);
|
||||
/* Specify if should use the advanced 4T1R MUX design */
|
||||
mux_info->advanced_rram_design = GetBooleanProperty(Node,"advanced_rram_design", FALSE, FALSE);
|
||||
ezxml_set_attr(Node, "advanced_rram_design", NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ProcessSpiceModelLUT(ezxml_t Node,
|
||||
t_spice_model_lut* lut_info) {
|
||||
lut_info->frac_lut = GetBooleanProperty(Node,"fracturable_lut", FALSE, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ProcessSpiceModelGate(ezxml_t Node,
|
||||
t_spice_model_gate* gate_info) {
|
||||
if (0 == strcmp(FindProperty(Node,"topology",TRUE),"AND")) {
|
||||
gate_info->type = SPICE_MODEL_GATE_AND;
|
||||
} else if (0 == strcmp(FindProperty(Node,"topology",TRUE),"OR")) {
|
||||
gate_info->type = SPICE_MODEL_GATE_OR;
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid topology of gates. Should be [AND|OR].\n",
|
||||
Node->line);
|
||||
exit(1);
|
||||
}
|
||||
ezxml_set_attr(Node, "topology", NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ProcessSpiceModelPortLutOutputMask(ezxml_t Node,
|
||||
t_spice_model_port* port) {
|
||||
|
||||
const char* Prop = NULL;
|
||||
int ipin;
|
||||
char* Prop_cpy = NULL;
|
||||
char* pch = NULL;
|
||||
|
||||
port->lut_output_mask = (int*) my_malloc (sizeof(int) * port->size);
|
||||
|
||||
Prop = FindProperty(Node, "lut_output_mask", FALSE);
|
||||
|
||||
if (NULL == Prop) {
|
||||
/* give a default value */
|
||||
for (ipin = 0; ipin < port->size; ipin++) {
|
||||
port->lut_output_mask[ipin] = ipin;
|
||||
}
|
||||
} else {
|
||||
/* decode the output_maski, split the string by "," */
|
||||
ipin = 0;
|
||||
Prop_cpy = my_strdup(Prop);
|
||||
pch = strtok(Prop_cpy, ",");
|
||||
while (NULL != pch) {
|
||||
port->lut_output_mask[ipin] = my_atoi(pch);
|
||||
ipin++;
|
||||
pch = strtok(NULL, ",");
|
||||
}
|
||||
/* Error out, fail to match the port size*/
|
||||
if (ipin != port->size) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid lut_output_mask(%s): Fail to match the port size (%d).\n",
|
||||
Node->line, Prop, port->size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ezxml_set_attr(Node, "lut_output_mask", NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void ProcessSpiceModelPort(ezxml_t Node,
|
||||
t_spice_model_port* port) {
|
||||
|
||||
if (0 == strcmp(FindProperty(Node,"type",TRUE),"input")) {
|
||||
port->type = SPICE_MODEL_PORT_INPUT;
|
||||
} else if (0 == strcmp(FindProperty(Node,"type",TRUE),"output")) {
|
||||
|
@ -548,9 +695,19 @@ static void ProcessSpiceModelPort(ezxml_t Node,
|
|||
}
|
||||
ezxml_set_attr(Node, "type", NULL);
|
||||
/* Assign prefix and size*/
|
||||
port->prefix = my_strdup(FindProperty(Node,"prefix",TRUE));
|
||||
port->prefix = my_strdup(FindProperty(Node, "prefix", TRUE));
|
||||
ezxml_set_attr(Node, "prefix", NULL);
|
||||
port->size = GetIntProperty(Node,"size",TRUE,1);
|
||||
/* Assign port name in the std library
|
||||
* Ff not found, it will be by default the same as prefix */
|
||||
port->lib_name = my_strdup(FindProperty(Node, "lib_name", FALSE));
|
||||
ezxml_set_attr(Node, "lib_name", NULL);
|
||||
if (NULL == port->lib_name) {
|
||||
port->lib_name = my_strdup(port->prefix);
|
||||
}
|
||||
/* Create an inverter prefix to ease the mapping to standard cells */
|
||||
port->inv_prefix = my_strdup(FindProperty(Node, "inv_prefix", FALSE));
|
||||
ezxml_set_attr(Node, "inv_prefix", NULL);
|
||||
port->size = GetIntProperty(Node, "size", TRUE, 1);
|
||||
ezxml_set_attr(Node, "size", NULL);
|
||||
|
||||
/* See if this is a mode selector.
|
||||
|
@ -564,6 +721,17 @@ static void ProcessSpiceModelPort(ezxml_t Node,
|
|||
port->default_val = GetIntProperty(Node, "default_val", FALSE, 0);
|
||||
ezxml_set_attr(Node, "default_val", NULL);
|
||||
|
||||
/* Tri-state map */
|
||||
port->tri_state_map = my_strdup(FindProperty(Node, "tri_state_map", FALSE));
|
||||
ezxml_set_attr(Node, "tri_state_map", NULL);
|
||||
|
||||
/* fracturable LUT: define at which level the output should be fractured */
|
||||
port->lut_frac_level = GetIntProperty(Node, "lut_frac_level", FALSE, -1);
|
||||
ezxml_set_attr(Node, "lut_frac_level", NULL);
|
||||
|
||||
/* Output mast of a fracturable LUT, which is to identify which intermediate LUT output will be connected to outputs */
|
||||
ProcessSpiceModelPortLutOutputMask(Node, port);
|
||||
|
||||
/* See if this is a global signal
|
||||
* We assume that global signals are shared by all the SPICE Model/blocks.
|
||||
* We need to check if other SPICE model has the same port name
|
||||
|
@ -584,51 +752,49 @@ static void ProcessSpiceModelPort(ezxml_t Node,
|
|||
ezxml_set_attr(Node, "is_config_enable", NULL);
|
||||
|
||||
/* Check if this port is linked to another spice_model*/
|
||||
port->spice_model_name = my_strdup(FindProperty(Node,"circuit_model_name",FALSE));
|
||||
ezxml_set_attr(Node, "circuit_model_name", NULL);
|
||||
port->spice_model_name = my_strdup(FindProperty(Node,"spice_model_name",FALSE));
|
||||
ezxml_set_attr(Node, "spice_model_name", NULL);
|
||||
|
||||
/* For BL/WL, BLB/WLB ports, we need to get the spice_model for inverters */
|
||||
if ((SPICE_MODEL_PORT_BL == port->type)
|
||||
||(SPICE_MODEL_PORT_WL == port->type)
|
||||
||(SPICE_MODEL_PORT_BLB == port->type)
|
||||
||(SPICE_MODEL_PORT_WLB == port->type)) {
|
||||
port->inv_spice_model_name = my_strdup(FindProperty(Node, "inv_circuit_model_name", FALSE));
|
||||
ezxml_set_attr(Node, "inv_circuit_model_name", NULL);
|
||||
port->inv_spice_model_name = my_strdup(FindProperty(Node, "inv_spice_model_name", FALSE));
|
||||
ezxml_set_attr(Node, "inv_spice_model_name", NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void ProcessSpiceModelDelayInfo(ezxml_t Node,
|
||||
t_spice_model_delay_info* cur_delay_info) {
|
||||
char* delay_str = NULL;
|
||||
static
|
||||
void ProcessSpiceModelDelayInfo(ezxml_t Node,
|
||||
t_spice_model_delay_info* cur_delay_info) {
|
||||
/* Find the type */
|
||||
if (0 == strcmp(FindProperty(Node, "type", TRUE), "rise")) {
|
||||
cur_delay_info->type = SPICE_MODEL_DELAY_RISE;
|
||||
} else if (0 == strcmp(FindProperty(Node, "type", TRUE), "fall")) {
|
||||
cur_delay_info->type = SPICE_MODEL_DELAY_FALL;
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid type of delay_info. Should be [rise|fall].\n",
|
||||
Node->line);
|
||||
exit(1);
|
||||
}
|
||||
ezxml_set_attr(Node, "type", NULL);
|
||||
|
||||
/* Find the type */
|
||||
if (0 == strcmp(FindProperty(Node, "type", TRUE), "rise")) {
|
||||
cur_delay_info->type = SPICE_MODEL_DELAY_RISE;
|
||||
} else if (0 == strcmp(FindProperty(Node, "type", TRUE), "fall")) {
|
||||
cur_delay_info->type = SPICE_MODEL_DELAY_FALL;
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid type of delay_info. Should be [rise|fall].\n",
|
||||
Node->line);
|
||||
exit(1);
|
||||
}
|
||||
ezxml_set_attr(Node, "type", NULL);
|
||||
/* Find the input and output ports */
|
||||
cur_delay_info->in_port_name = my_strdup(FindProperty(Node, "in_port", TRUE));
|
||||
ezxml_set_attr(Node, "in_port", NULL);
|
||||
|
||||
/* Find the input and output ports */
|
||||
cur_delay_info->in_port_name = my_strdup(FindProperty(Node, "in_port", TRUE));
|
||||
ezxml_set_attr(Node, "in_port", NULL);
|
||||
cur_delay_info->out_port_name = my_strdup(FindProperty(Node, "out_port", TRUE));
|
||||
ezxml_set_attr(Node, "out_port", NULL);
|
||||
|
||||
cur_delay_info->out_port_name = my_strdup(FindProperty(Node, "out_port", TRUE));
|
||||
ezxml_set_attr(Node, "out_port", NULL);
|
||||
/* Find delay matrix */
|
||||
cur_delay_info->value = my_strdup(Node->txt);
|
||||
ezxml_set_txt(Node, "");
|
||||
|
||||
/* Find delay matrix */
|
||||
cur_delay_info->value = my_strdup(Node->txt);
|
||||
ezxml_set_txt(Node, "");
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void ProcessSpiceModelWireParam(ezxml_t Parent,
|
||||
t_spice_model_wire_param* wire_param) {
|
||||
|
@ -667,8 +833,6 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
spice_model->type = SPICE_MODEL_CHAN_WIRE;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"wire")) {
|
||||
spice_model->type = SPICE_MODEL_WIRE;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"hard_logic")) {
|
||||
spice_model->type = SPICE_MODEL_HARDLOGIC;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"lut")) {
|
||||
spice_model->type = SPICE_MODEL_LUT;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"ff")) {
|
||||
|
@ -681,16 +845,14 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
spice_model->type = SPICE_MODEL_SCFF;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"iopad")) {
|
||||
spice_model->type = SPICE_MODEL_IOPAD;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"wire_vdd")) {
|
||||
spice_model->type = SPICE_MODEL_VDD;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"wire_gnd")) {
|
||||
spice_model->type = SPICE_MODEL_GND;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"inv_buf")) {
|
||||
spice_model->type = SPICE_MODEL_INVBUF;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"pass_gate")) {
|
||||
spice_model->type = SPICE_MODEL_PASSGATE;
|
||||
} else if (0 == strcmp(FindProperty(Parent,"type",TRUE),"gate")) {
|
||||
spice_model->type = SPICE_MODEL_GATE;
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid type of spice model(%s). Should be [mux|lut|ff|io|sram|hard_logic|sff].\n",
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid type of spice model(%s). Should be [chan_wire|wire|mux|lut|ff|sram|hard_logic|sff|iopad|inv_buf|pass_gate|gate].\n",
|
||||
Parent->line, FindProperty(Parent, "type", TRUE));
|
||||
exit(1);
|
||||
}
|
||||
|
@ -719,6 +881,10 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
/* Find a verilog_netlist path if we can*/
|
||||
spice_model->dump_structural_verilog = GetBooleanProperty(Parent,"dump_structural_verilog", FALSE, FALSE);
|
||||
ezxml_set_attr(Parent, "dump_structural_verilog", NULL);
|
||||
|
||||
/* Find a verilog_netlist path if we can*/
|
||||
spice_model->dump_explicit_port_map = GetBooleanProperty(Parent,"dump_explicit_port_map", FALSE, FALSE);
|
||||
ezxml_set_attr(Parent, "dump_explicit_port_map", NULL);
|
||||
|
||||
/* Check the design technology settings*/
|
||||
Node = ezxml_child(Parent, "design_technology");
|
||||
|
@ -748,80 +914,64 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
}
|
||||
} else if (0 == strcmp(FindProperty(Node,"type",TRUE),"rram")) {
|
||||
spice_model->design_tech = SPICE_MODEL_DESIGN_RRAM;
|
||||
/* RRAM tech. We need more properties*/
|
||||
spice_model->design_tech_info.ron = GetFloatProperty(Node,"ron",TRUE,0);
|
||||
ezxml_set_attr(Node, "ron", NULL);
|
||||
spice_model->design_tech_info.roff = GetFloatProperty(Node,"roff",TRUE,0);
|
||||
ezxml_set_attr(Node, "roff", NULL);
|
||||
spice_model->design_tech_info.wprog_set_nmos = GetFloatProperty(Node,"wprog_set_nmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_set_nmos", NULL);
|
||||
spice_model->design_tech_info.wprog_set_pmos = GetFloatProperty(Node,"wprog_set_pmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_set_nmos", NULL);
|
||||
spice_model->design_tech_info.wprog_reset_nmos = GetFloatProperty(Node,"wprog_reset_nmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_reset_nmos", NULL);
|
||||
spice_model->design_tech_info.wprog_reset_pmos = GetFloatProperty(Node,"wprog_reset_pmos",TRUE,0);
|
||||
ezxml_set_attr(Node, "wprog_reset_pmos", NULL);
|
||||
/* Malloc RRAM info */
|
||||
spice_model->design_tech_info.rram_info = (t_spice_model_rram*)my_malloc(sizeof(t_spice_model_rram));
|
||||
/* Fill information */
|
||||
ProcessSpiceModelRRAM(Node, spice_model->design_tech_info.rram_info);
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] Invalid value for design_technology in spice model(%s). Should be [cmos|rram].\n",
|
||||
Node->line,spice_model->name);
|
||||
exit(1);
|
||||
}
|
||||
ezxml_set_attr(Node, "type", NULL);
|
||||
|
||||
/* Read in the structure if defined */
|
||||
spice_model->design_tech_info.mux_info = NULL;
|
||||
if (SPICE_MODEL_MUX == spice_model->type) {
|
||||
if (0 == strcmp(FindProperty(Node,"structure",TRUE),"tree")) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
} else if (0 == strcmp(FindProperty(Node,"structure",TRUE),"one-level")) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
|
||||
} else if (0 == strcmp(FindProperty(Node,"structure",TRUE),"multi-level")) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_MULTILEVEL;
|
||||
/* New Structure: crossbar
|
||||
} else if (0 == strcmp(FindProperty(Node,"structure",TRUE),"crossbar")) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_CROSSBAR;
|
||||
*/
|
||||
} else {
|
||||
/* Set default to RRAM MUX */
|
||||
if (SPICE_MODEL_DESIGN_RRAM == spice_model->design_tech) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
|
||||
} else {
|
||||
/* Set default to SRAM MUX */
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Default: tree */
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
/* Malloc */
|
||||
spice_model->design_tech_info.mux_info = (t_spice_model_mux*)my_malloc(sizeof(t_spice_model_mux));
|
||||
/* Fill information */
|
||||
ProcessSpiceModelMUX(Node, spice_model, spice_model->design_tech_info.mux_info);
|
||||
}
|
||||
ezxml_set_attr(Node, "structure", NULL);
|
||||
if (SPICE_MODEL_STRUCTURE_MULTILEVEL == spice_model->design_tech_info.structure) {
|
||||
spice_model->design_tech_info.mux_num_level = GetIntProperty(Node,"num_level",TRUE,1);
|
||||
/* For num_level == 1, auto convert to one-level structure */
|
||||
if (1 == spice_model->design_tech_info.mux_num_level) {
|
||||
spice_model->design_tech_info.structure = SPICE_MODEL_STRUCTURE_ONELEVEL;
|
||||
vpr_printf(TIO_MESSAGE_INFO,"[LINE%d] Automatically convert structure of spice model(%s) to one-level.\n",
|
||||
Node->line, spice_model->name);
|
||||
}
|
||||
} else if (SPICE_MODEL_STRUCTURE_ONELEVEL == spice_model->design_tech_info.structure) {
|
||||
/* Set mux_num_level for other structure: one-level and tree */
|
||||
spice_model->design_tech_info.mux_num_level = 1;
|
||||
|
||||
/* If this is a LUT, more options are available */
|
||||
spice_model->design_tech_info.lut_info = NULL;
|
||||
if (SPICE_MODEL_LUT == spice_model->type) {
|
||||
/* Malloc */
|
||||
spice_model->design_tech_info.lut_info = (t_spice_model_lut*)my_malloc(sizeof(t_spice_model_lut));
|
||||
/* Fill information */
|
||||
ProcessSpiceModelLUT(Node, spice_model->design_tech_info.lut_info);
|
||||
/* Malloc */
|
||||
spice_model->design_tech_info.mux_info = (t_spice_model_mux*)my_malloc(sizeof(t_spice_model_mux));
|
||||
/* Fill information */
|
||||
/* Default: tree, no const_inputs */
|
||||
spice_model->design_tech_info.mux_info->structure = SPICE_MODEL_STRUCTURE_TREE;
|
||||
spice_model->design_tech_info.mux_info->add_const_input = FALSE;
|
||||
spice_model->design_tech_info.mux_info->const_input_val = 0;
|
||||
}
|
||||
ezxml_set_attr(Node, "num_level", NULL);
|
||||
/* Specify if should use the advanced 4T1R MUX design */
|
||||
spice_model->design_tech_info.advanced_rram_design = GetBooleanProperty(Node,"advanced_rram_design", FALSE, FALSE);
|
||||
ezxml_set_attr(Node, "advanced_rram_design", NULL);
|
||||
FreeNode(Node);
|
||||
ezxml_set_attr(Node, "fracturable_lut", NULL);
|
||||
|
||||
|
||||
spice_model->design_tech_info.gate_info = NULL;
|
||||
if (SPICE_MODEL_GATE == spice_model->type) {
|
||||
/* Malloc */
|
||||
spice_model->design_tech_info.gate_info = (t_spice_model_gate*)my_calloc(1, sizeof(t_spice_model_gate));
|
||||
/* Fill information */
|
||||
ProcessSpiceModelGate(Node, spice_model->design_tech_info.gate_info);
|
||||
}
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] design_technology is expected in spice_model(%s).\n",
|
||||
Node->line,spice_model->name);
|
||||
exit(1);
|
||||
}
|
||||
FreeNode(Node);
|
||||
|
||||
/* LUT input_buffers */
|
||||
Node = ezxml_child(Parent, "lut_input_buffer");
|
||||
spice_model->lut_input_buffer = NULL;
|
||||
if (Node) {
|
||||
/* Malloc the lut_input_buffer */
|
||||
spice_model->lut_input_buffer = (t_spice_model_buffer*)my_malloc(sizeof(t_spice_model_buffer));
|
||||
spice_model->lut_input_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
|
||||
ProcessSpiceModelBuffer(Node,spice_model->lut_input_buffer);
|
||||
FreeNode(Node);
|
||||
} else if (SPICE_MODEL_LUT == spice_model->type) {
|
||||
|
@ -829,6 +979,37 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
Parent->line, spice_model->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* LUT input_buffers */
|
||||
Node = ezxml_child(Parent, "lut_input_inverter");
|
||||
spice_model->lut_input_inverter = NULL;
|
||||
if (Node) {
|
||||
/* Malloc the lut_input_buffer */
|
||||
spice_model->lut_input_inverter = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
|
||||
ProcessSpiceModelBuffer(Node,spice_model->lut_input_inverter);
|
||||
FreeNode(Node);
|
||||
} else if (SPICE_MODEL_LUT == spice_model->type) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"[LINE %d] lut_input_inverter is expected in spice_model(%s).\n",
|
||||
Parent->line, spice_model->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* LUT intermediate buffers */
|
||||
Node = ezxml_child(Parent, "lut_intermediate_buffer");
|
||||
spice_model->lut_intermediate_buffer = (t_spice_model_buffer*)my_calloc(1, sizeof(t_spice_model_buffer));
|
||||
if (Node) {
|
||||
/* Malloc the lut_input_buffer */
|
||||
ProcessSpiceModelBuffer(Node,spice_model->lut_intermediate_buffer);
|
||||
FreeNode(Node);
|
||||
} else if ((SPICE_MODEL_LUT == spice_model->type)
|
||||
|| (SPICE_MODEL_MUX == spice_model->type)) {
|
||||
/* Assign default values */
|
||||
spice_model->lut_intermediate_buffer->exist = 0;
|
||||
spice_model->lut_intermediate_buffer->spice_model = NULL;
|
||||
spice_model->lut_intermediate_buffer->location_map = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Input Buffers*/
|
||||
Node = ezxml_child(Parent, "input_buffer");
|
||||
spice_model->input_buffer = NULL;
|
||||
|
@ -861,8 +1042,8 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
if (Node) {
|
||||
spice_model->pass_gate_logic = (t_spice_model_pass_gate_logic*)my_malloc(sizeof(t_spice_model_pass_gate_logic));
|
||||
/* Find spice_model_name */
|
||||
spice_model->pass_gate_logic->spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", TRUE));
|
||||
ezxml_set_attr(Node, "circuit_model_name", NULL);
|
||||
spice_model->pass_gate_logic->spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", TRUE));
|
||||
ezxml_set_attr(Node, "spice_model_name", NULL);
|
||||
FreeNode(Node);
|
||||
} else if ((SPICE_MODEL_MUX == spice_model->type)
|
||||
||(SPICE_MODEL_LUT == spice_model->type)) {
|
||||
|
@ -897,16 +1078,16 @@ static void ProcessSpiceModel(ezxml_t Parent,
|
|||
FreeNode(Node);
|
||||
}
|
||||
|
||||
/* Find delay info */
|
||||
spice_model->num_delay_info = CountChildren(Parent, "delay_matrix", 0);
|
||||
/*Alloc*/
|
||||
spice_model->delay_info = (t_spice_model_delay_info*) my_malloc(spice_model->num_delay_info * sizeof(t_spice_model_delay_info));
|
||||
/* Assign each found spice model*/
|
||||
for (i = 0; i < spice_model->num_delay_info; i++) {
|
||||
Cur = FindFirstElement(Parent, "delay_matrix", TRUE);
|
||||
ProcessSpiceModelDelayInfo(Cur, &(spice_model->delay_info[i]));
|
||||
FreeNode(Cur);
|
||||
}
|
||||
/* Find delay info */
|
||||
spice_model->num_delay_info = CountChildren(Parent, "delay_matrix", 0);
|
||||
/*Alloc*/
|
||||
spice_model->delay_info = (t_spice_model_delay_info*) my_malloc(spice_model->num_delay_info * sizeof(t_spice_model_delay_info));
|
||||
/* Assign each found spice model*/
|
||||
for (i = 0; i < spice_model->num_delay_info; i++) {
|
||||
Cur = FindFirstElement(Parent, "delay_matrix", TRUE);
|
||||
ProcessSpiceModelDelayInfo(Cur, &(spice_model->delay_info[i]));
|
||||
FreeNode(Cur);
|
||||
}
|
||||
|
||||
/* Initialize the counter*/
|
||||
spice_model->cnt = 0;
|
||||
|
@ -925,9 +1106,9 @@ void ProcessSpiceSRAMOrganization(INOUTP ezxml_t Node,
|
|||
return;
|
||||
}
|
||||
|
||||
cur_sram_inf_orgz->spice_model_name = my_strdup(FindProperty(Node, "circuit_model_name", required));
|
||||
cur_sram_inf_orgz->spice_model_name = my_strdup(FindProperty(Node, "spice_model_name", required));
|
||||
cur_sram_inf_orgz->spice_model = NULL;
|
||||
ezxml_set_attr(Node, "circuit_model_name", NULL);
|
||||
ezxml_set_attr(Node, "spice_model_name", NULL);
|
||||
|
||||
/* read organization type*/
|
||||
Prop = FindProperty(Node, "organization", required);
|
||||
|
@ -935,7 +1116,7 @@ void ProcessSpiceSRAMOrganization(INOUTP ezxml_t Node,
|
|||
cur_sram_inf_orgz->type = SPICE_SRAM_STANDALONE; /* Default */
|
||||
} else if (0 == strcmp("scan-chain", Prop)) {
|
||||
cur_sram_inf_orgz->type = SPICE_SRAM_SCAN_CHAIN;
|
||||
} else if (0 == strcmp("memory_bank", Prop)) {
|
||||
} else if (0 == strcmp("memory-bank", Prop)) {
|
||||
cur_sram_inf_orgz->type = SPICE_SRAM_MEMORY_BANK;
|
||||
} else if (0 == strcmp("standalone", Prop)) {
|
||||
cur_sram_inf_orgz->type = SPICE_SRAM_STANDALONE;
|
||||
|
@ -1094,24 +1275,24 @@ static void check_spice_models(int num_spice_model,
|
|||
}
|
||||
/* Check the I/O transistors are defined when RRAM MUX is selected */
|
||||
if (SPICE_MODEL_DESIGN_RRAM == spice_models[i].design_tech) {
|
||||
if (!(0. < spice_models[i].design_tech_info.wprog_set_nmos)) {
|
||||
if (!(0. < spice_models[i].design_tech_info.rram_info->wprog_set_nmos)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "wprog_set_nmos(%g) should be >0 for a RRAM MUX SPICE model (%s)!\n",
|
||||
spice_models[i].design_tech_info.wprog_set_nmos, spice_models[i].name);
|
||||
spice_models[i].design_tech_info.rram_info->wprog_set_nmos, spice_models[i].name);
|
||||
exit(1);
|
||||
}
|
||||
if (!(0. < spice_models[i].design_tech_info.wprog_set_pmos)) {
|
||||
if (!(0. < spice_models[i].design_tech_info.rram_info->wprog_set_pmos)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "wprog_set_pmos(%g) should be >0 for a RRAM MUX SPICE model (%s)!\n",
|
||||
spice_models[i].design_tech_info.wprog_set_pmos, spice_models[i].name);
|
||||
spice_models[i].design_tech_info.rram_info->wprog_set_pmos, spice_models[i].name);
|
||||
exit(1);
|
||||
}
|
||||
if (!(0. < spice_models[i].design_tech_info.wprog_reset_nmos)) {
|
||||
if (!(0. < spice_models[i].design_tech_info.rram_info->wprog_reset_nmos)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "wprog_reset_nmos(%g) should be >0 for a RRAM MUX SPICE model (%s)!\n",
|
||||
spice_models[i].design_tech_info.wprog_reset_nmos, spice_models[i].name);
|
||||
spice_models[i].design_tech_info.rram_info->wprog_reset_nmos, spice_models[i].name);
|
||||
exit(1);
|
||||
}
|
||||
if (!(0. < spice_models[i].design_tech_info.wprog_reset_pmos)) {
|
||||
if (!(0. < spice_models[i].design_tech_info.rram_info->wprog_reset_pmos)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "wprog_reset_pmos(%g) should be >0 for a RRAM MUX SPICE model (%s)!\n",
|
||||
spice_models[i].design_tech_info.wprog_reset_pmos, spice_models[i].name);
|
||||
spice_models[i].design_tech_info.rram_info->wprog_reset_pmos, spice_models[i].name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -1154,6 +1335,28 @@ static void check_spice_models(int num_spice_model,
|
|||
exit(1);
|
||||
}
|
||||
}
|
||||
/* Check scan-chain dff has input and output, clock ports*/
|
||||
if (SPICE_MODEL_SCFF == spice_models[i].type) {
|
||||
has_sram = 1;
|
||||
has_clock_port = 0;
|
||||
has_in_port = 0;
|
||||
has_out_port = 0;
|
||||
for (j = 0; j < spice_models[i].num_port; j++) {
|
||||
if (SPICE_MODEL_PORT_INPUT == spice_models[i].ports[j].type) {
|
||||
has_in_port = 1;
|
||||
} else if (SPICE_MODEL_PORT_OUTPUT == spice_models[i].ports[j].type) {
|
||||
has_out_port = 1;
|
||||
} else if (SPICE_MODEL_PORT_CLOCK == spice_models[i].ports[j].type) {
|
||||
has_clock_port = 1;
|
||||
}
|
||||
}
|
||||
/* Check if we have two ports*/
|
||||
if ((0 == has_in_port)||(0 == has_out_port)||(0 == has_clock_port)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"FF Spice model(%s) does not have input|output|clock port\n",spice_models[i].name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check lut has input and output, clock ports*/
|
||||
if (SPICE_MODEL_LUT == spice_models[i].type) {
|
||||
has_sram_port = 0;
|
||||
|
@ -1301,14 +1504,14 @@ void ProcessSpiceSettings(ezxml_t Parent,
|
|||
ProcessSpiceTechLibTransistors(Parent, &(spice->tech_lib));
|
||||
|
||||
/* module spice models*/
|
||||
Node = FindElement(Parent, "module_circuit_models", FALSE);
|
||||
Node = FindElement(Parent, "module_spice_models", FALSE);
|
||||
if (Node) {
|
||||
spice->num_spice_model = CountChildren(Node, "circuit_model", 1);
|
||||
spice->num_spice_model = CountChildren(Node, "spice_model", 1);
|
||||
/*Alloc*/
|
||||
spice->spice_models = (t_spice_model*)my_malloc(spice->num_spice_model*sizeof(t_spice_model));
|
||||
/* Assign each found spice model*/
|
||||
for (imodel = 0; imodel < spice->num_spice_model; imodel++) {
|
||||
Cur = FindFirstElement(Node, "circuit_model", TRUE);
|
||||
Cur = FindFirstElement(Node, "spice_model", TRUE);
|
||||
ProcessSpiceModel(Cur, &(spice->spice_models[imodel]));
|
||||
FreeNode(Cur);
|
||||
}
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
* Beta Version released on 2/22/06
|
||||
|
||||
* PTM 130nm NMOS
|
||||
|
||||
.model nmos nmos level = 54
|
||||
|
||||
+version = 4.0 binunit = 1 paramchk= 1 mobmod = 0
|
||||
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
|
||||
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
|
||||
+permod = 1 acnqsmod= 0 trnqsmod= 0
|
||||
|
||||
+tnom = 27 toxe = 2.25e-9 toxp = 1.6e-9 toxm = 2.25e-9
|
||||
+dtox = 0.65e-9 epsrox = 3.9 wint = 5e-009 lint = 10.5e-009
|
||||
+ll = 0 wl = 0 lln = 1 wln = 1
|
||||
+lw = 0 ww = 0 lwn = 1 wwn = 1
|
||||
+lwl = 0 wwl = 0 xpart = 0 toxref = 2.25e-9
|
||||
+xl = -60e-9
|
||||
+vth0 = 0.3782 k1 = 0.4 k2 = 0.01 k3 = 0
|
||||
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
|
||||
+dvt2 = -0.032 dvt0w = 0 dvt1w = 0 dvt2w = 0
|
||||
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1.2e-010
|
||||
+dvtp1 = 0.1 lpe0 = 0 lpeb = 0 xj = 3.92e-008
|
||||
+ngate = 2e+020 ndep = 1.54e+018 nsd = 2e+020 phin = 0
|
||||
+cdsc = 0.0002 cdscb = 0 cdscd = 0 cit = 0
|
||||
+voff = -0.13 nfactor = 1.5 eta0 = 0.0092 etab = 0
|
||||
+vfb = -0.55 u0 = 0.05928 ua = 6e-010 ub = 1.2e-018
|
||||
+uc = 0 vsat = 100370 a0 = 1 ags = 1e-020
|
||||
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
|
||||
+keta = 0.04 dwg = 0 dwb = 0 pclm = 0.06
|
||||
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = -0.005 drout = 0.5
|
||||
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 1e-007
|
||||
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2.3e+006
|
||||
+rsh = 5 rdsw = 200 rsw = 100 rdw = 100
|
||||
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
|
||||
+prwb = 6.8e-011 wr = 1 alpha0 = 0.074 alpha1 = 0.005
|
||||
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
|
||||
+egidl = 0.8
|
||||
|
||||
+aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
|
||||
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
|
||||
+eigbinv = 1.1 nigbinv = 3 aigc = 0.012 bigc = 0.0028
|
||||
+cigc = 0.002 aigsd = 0.012 bigsd = 0.0028 cigsd = 0.002
|
||||
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
|
||||
|
||||
+xrcrg1 = 12 xrcrg2 = 5
|
||||
+cgso = 2.4e-010 cgdo = 2.4e-010 cgbo = 2.56e-011 cgdl = 2.653e-10
|
||||
+cgsl = 2.653e-10 ckappas = 0.03 ckappad = 0.03 acde = 1
|
||||
+moin = 15 noff = 0.9 voffcv = 0.02
|
||||
|
||||
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
|
||||
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
|
||||
+at = 33000
|
||||
|
||||
+fnoimod = 1 tnoimod = 0
|
||||
|
||||
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
|
||||
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
|
||||
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
|
||||
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
|
||||
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
|
||||
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
|
||||
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
|
||||
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
|
||||
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
|
||||
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
|
||||
+xtis = 3 xtid = 3
|
||||
|
||||
+dmcg = 0e-006 dmci = 0e-006 dmdg = 0e-006 dmcgt = 0e-007
|
||||
+dwj = 0.0e-008 xgw = 0e-007 xgl = 0e-008
|
||||
|
||||
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
|
||||
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
|
||||
|
||||
* PTM 130nm PMOS
|
||||
|
||||
.model pmos pmos level = 54
|
||||
|
||||
+version = 4.0 binunit = 1 paramchk= 1 mobmod = 0
|
||||
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
|
||||
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
|
||||
+permod = 1 acnqsmod= 0 trnqsmod= 0
|
||||
|
||||
+tnom = 27 toxe = 2.35e-009 toxp = 1.6e-009 toxm = 2.35e-009
|
||||
+dtox = 0.75e-9 epsrox = 3.9 wint = 5e-009 lint = 10.5e-009
|
||||
+ll = 0 wl = 0 lln = 1 wln = 1
|
||||
+lw = 0 ww = 0 lwn = 1 wwn = 1
|
||||
+lwl = 0 wwl = 0 xpart = 0 toxref = 2.35e-009
|
||||
+xl = -60e-9
|
||||
+vth0 = -0.321 k1 = 0.4 k2 = -0.01 k3 = 0
|
||||
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
|
||||
+dvt2 = -0.032 dvt0w = 0 dvt1w = 0 dvt2w = 0
|
||||
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-009
|
||||
+dvtp1 = 0.05 lpe0 = 0 lpeb = 0 xj = 3.92e-008
|
||||
+ngate = 2e+020 ndep = 1.14e+018 nsd = 2e+020 phin = 0
|
||||
+cdsc = 0.000258 cdscb = 0 cdscd = 6.1e-008 cit = 0
|
||||
+voff = -0.126 nfactor = 1.5 eta0 = 0.0092 etab = 0
|
||||
+vfb = 0.55 u0 = 0.00835 ua = 2.0e-009 ub = 0.5e-018
|
||||
+uc = -3e-011 vsat = 70000 a0 = 1.0 ags = 1e-020
|
||||
+a1 = 0 a2 = 1 b0 = -1e-020 b1 = 0
|
||||
+keta = -0.047 dwg = 0 dwb = 0 pclm = 0.12
|
||||
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = 3.4e-008 drout = 0.56
|
||||
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 9.58e-007
|
||||
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2.3e+006
|
||||
+rsh = 5 rdsw = 240 rsw = 120 rdw = 120
|
||||
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 3.22e-008
|
||||
+prwb = 6.8e-011 wr = 1 alpha0 = 0.074 alpha1 = 0.005
|
||||
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
|
||||
+egidl = 0.8
|
||||
|
||||
+aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
|
||||
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
|
||||
+eigbinv = 1.1 nigbinv = 3 aigc = 0.69 bigc = 0.0012
|
||||
+cigc = 0.0008 aigsd = 0.0087 bigsd = 0.0012 cigsd = 0.0008
|
||||
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
|
||||
|
||||
+xrcrg1 = 12 xrcrg2 = 5
|
||||
+cgso = 2.4e-010 cgdo = 2.4e-010 cgbo = 2.56e-011 cgdl = 2.653e-10
|
||||
+cgsl = 2.653e-10 ckappas = 0.03 ckappad = 0.03 acde = 1
|
||||
+moin = 15 noff = 0.9 voffcv = 0.02
|
||||
|
||||
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
|
||||
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
|
||||
+at = 33000
|
||||
|
||||
+fnoimod = 1 tnoimod = 0
|
||||
|
||||
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
|
||||
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
|
||||
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
|
||||
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
|
||||
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
|
||||
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
|
||||
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
|
||||
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
|
||||
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
|
||||
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
|
||||
+xtis = 3 xtid = 3
|
||||
|
||||
+dmcg = 0e-006 dmci = 0e-006 dmdg = 0e-006 dmcgt = 0e-007
|
||||
+dwj = 0.0e-008 xgw = 0e-007 xgl = 0e-008
|
||||
|
||||
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
|
||||
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
|||
This technology file was generated using the Nano-CMOS tool from http://ptm.asu.edu/
|
||||
|
||||
The following default parameters were used:
|
||||
|
||||
NMOS
|
||||
Leff=49 nm 10%
|
||||
Vth=0.18 V 30mV
|
||||
Vdd=1.3 V
|
||||
Tox=1.6 nm
|
||||
Rdsw=200 Ohm
|
||||
|
||||
PMOS
|
||||
Leff=49 nm 10%
|
||||
Vth=-0.18 V 30mV
|
||||
Vdd=1.3 V
|
||||
Tox=1.6 nm
|
||||
Rdsw=240 Ohm
|
|
@ -1,140 +0,0 @@
|
|||
* PTM High Performance 22nm Metal Gate / High-K / Strained-Si
|
||||
* nominal Vdd = 0.8V
|
||||
|
||||
.model nmos nmos level = 54
|
||||
|
||||
+version = 4.0 binunit = 1 paramchk= 1 mobmod = 0
|
||||
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
|
||||
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
|
||||
+permod = 1 acnqsmod= 0 trnqsmod= 0
|
||||
|
||||
+tnom = 27 toxe = 1.05e-009 toxp = 8e-010 toxm = 1.05e-009
|
||||
+dtox = 2.5e-010 epsrox = 3.9 wint = 5e-009 lint = 2e-009
|
||||
+ll = 0 wl = 0 lln = 1 wln = 1
|
||||
+lw = 0 ww = 0 lwn = 1 wwn = 1
|
||||
+lwl = 0 wwl = 0 xpart = 0 toxref = 1.05e-009
|
||||
+xl = -9e-9
|
||||
|
||||
+vth0 = 0.50308 k1 = 0.4 k2 = 0 k3 = 0
|
||||
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
|
||||
+dvt2 = 0 dvt0w = 0 dvt1w = 0 dvt2w = 0
|
||||
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-011
|
||||
+dvtp1 = 0.1 lpe0 = 0 lpeb = 0 xj = 7.2e-009
|
||||
+ngate = 1e+023 ndep = 5.5e+018 nsd = 2e+020 phin = 0
|
||||
+cdsc = 0 cdscb = 0 cdscd = 0 cit = 0
|
||||
+voff = -0.13 nfactor = 2.3 eta0 = 0.004 etab = 0
|
||||
+vfb = -0.55 u0 = 0.04 ua = 6e-010 ub = 1.2e-018
|
||||
+uc = 0 vsat = 250000 a0 = 1 ags = 0
|
||||
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
|
||||
+keta = 0.04 dwg = 0 dwb = 0 pclm = 0.02
|
||||
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = -0.005 drout = 0.5
|
||||
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 1e-007
|
||||
+fprout = 0.2 pdits = 0.01 pditsd = 0.23 pditsl = 2300000
|
||||
+rsh = 5 rdsw = 145 rsw = 75 rdw = 75
|
||||
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
|
||||
+prwb = 0 wr = 1 alpha0 = 0.074 alpha1 = 0.005
|
||||
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
|
||||
+egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
|
||||
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
|
||||
+eigbinv = 1.1 nigbinv = 3 aigc = 0.0213 bigc = 0.0025889
|
||||
+cigc = 0.002 aigsd = 0.0213 bigsd = 0.0025889 cigsd = 0.002
|
||||
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
|
||||
+xrcrg1 = 12 xrcrg2 = 5
|
||||
|
||||
+cgso = 6.5e-011 cgdo = 6.5e-011 cgbo = 2.56e-011 cgdl = 2.653e-010
|
||||
+cgsl = 2.653e-010 ckappas = 0.03 ckappad = 0.03 acde = 1
|
||||
+moin = 15 noff = 0.9 voffcv = 0.02
|
||||
|
||||
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
|
||||
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
|
||||
+at = 33000
|
||||
|
||||
+fnoimod = 1 tnoimod = 0
|
||||
|
||||
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
|
||||
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
|
||||
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
|
||||
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
|
||||
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
|
||||
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
|
||||
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
|
||||
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
|
||||
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
|
||||
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
|
||||
+xtis = 3 xtid = 3
|
||||
|
||||
+dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0
|
||||
+dwj = 0 xgw = 0 xgl = 0
|
||||
|
||||
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
|
||||
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
|
||||
|
||||
|
||||
|
||||
.model pmos pmos level = 54
|
||||
|
||||
+version = 4.0 binunit = 1 paramchk= 1 mobmod = 0
|
||||
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
|
||||
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
|
||||
+permod = 1 acnqsmod= 0 trnqsmod= 0
|
||||
|
||||
+tnom = 27 toxe = 1.1e-009 toxp = 8e-010 toxm = 1.1e-009
|
||||
+dtox = 3e-010 epsrox = 3.9 wint = 5e-009 lint = 2e-009
|
||||
+ll = 0 wl = 0 lln = 1 wln = 1
|
||||
+lw = 0 ww = 0 lwn = 1 wwn = 1
|
||||
+lwl = 0 wwl = 0 xpart = 0 toxref = 1.1e-009
|
||||
+xl = -9e-9
|
||||
|
||||
+vth0 = -0.4606 k1 = 0.4 k2 = -0.01 k3 = 0
|
||||
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
|
||||
+dvt2 = -0.032 dvt0w = 0 dvt1w = 0 dvt2w = 0
|
||||
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-011
|
||||
+dvtp1 = 0.05 lpe0 = 0 lpeb = 0 xj = 7.2e-009
|
||||
+ngate = 1e+023 ndep = 4.4e+018 nsd = 2e+020 phin = 0
|
||||
+cdsc = 0 cdscb = 0 cdscd = 0 cit = 0
|
||||
+voff = -0.126 nfactor = 2.1 eta0 = 0.0038 etab = 0
|
||||
+vfb = 0.55 u0 = 0.0095 ua = 2e-009 ub = 5e-019
|
||||
+uc = 0 vsat = 210000 a0 = 1 ags = 1e-020
|
||||
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
|
||||
+keta = -0.047 dwg = 0 dwb = 0 pclm = 0.12
|
||||
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = 3.4e-008 drout = 0.56
|
||||
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 9.58e-007
|
||||
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2300000
|
||||
+rsh = 5 rdsw = 145 rsw = 72.5 rdw = 72.5
|
||||
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
|
||||
+prwb = 0 wr = 1 alpha0 = 0.074 alpha1 = 0.005
|
||||
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
|
||||
+egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
|
||||
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
|
||||
+eigbinv = 1.1 nigbinv = 3 aigc = 0.0213 bigc = 0.0025889
|
||||
+cigc = 0.002 aigsd = 0.0213 bigsd = 0.0025889 cigsd = 0.002
|
||||
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
|
||||
+xrcrg1 = 12 xrcrg2 = 5
|
||||
|
||||
+cgso = 6.5e-011 cgdo = 6.5e-011 cgbo = 2.56e-011 cgdl = 2.653e-010
|
||||
+cgsl = 2.653e-010 ckappas = 0.03 ckappad = 0.03 acde = 1
|
||||
+moin = 15 noff = 0.9 voffcv = 0.02
|
||||
|
||||
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
|
||||
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
|
||||
+at = 33000
|
||||
|
||||
+fnoimod = 1 tnoimod = 0
|
||||
|
||||
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
|
||||
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
|
||||
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
|
||||
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
|
||||
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
|
||||
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
|
||||
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
|
||||
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
|
||||
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
|
||||
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
|
||||
+xtis = 3 xtid = 3
|
||||
|
||||
+dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0
|
||||
+dwj = 0 xgw = 0 xgl = 0
|
||||
|
||||
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
|
||||
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
|
File diff suppressed because it is too large
Load Diff
|
@ -1,2 +0,0 @@
|
|||
This technology file was obtained here:
|
||||
http://ptm.asu.edu/modelcard/LP/22nm_LP.pm
|
|
@ -1,141 +0,0 @@
|
|||
* PTM High Performance 45nm Metal Gate / High-K / Strained-Si
|
||||
* nominal Vdd = 1.0V
|
||||
|
||||
.model nmos nmos level = 54
|
||||
|
||||
+version = 4.0 binunit = 1 paramchk= 1 mobmod = 0
|
||||
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
|
||||
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
|
||||
+permod = 1 acnqsmod= 0 trnqsmod= 0
|
||||
|
||||
+tnom = 27 toxe = 1.25e-009 toxp = 1e-009 toxm = 1.25e-009
|
||||
+dtox = 2.5e-010 epsrox = 3.9 wint = 5e-009 lint = 3.75e-009
|
||||
+ll = 0 wl = 0 lln = 1 wln = 1
|
||||
+lw = 0 ww = 0 lwn = 1 wwn = 1
|
||||
+lwl = 0 wwl = 0 xpart = 0 toxref = 1.25e-009
|
||||
+xl = -20e-9
|
||||
|
||||
+vth0 = 0.46893 k1 = 0.4 k2 = 0 k3 = 0
|
||||
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
|
||||
+dvt2 = 0 dvt0w = 0 dvt1w = 0 dvt2w = 0
|
||||
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-010
|
||||
+dvtp1 = 0.1 lpe0 = 0 lpeb = 0 xj = 1.4e-008
|
||||
+ngate = 1e+023 ndep = 3.24e+018 nsd = 2e+020 phin = 0
|
||||
+cdsc = 0 cdscb = 0 cdscd = 0 cit = 0
|
||||
+voff = -0.13 nfactor = 2.22 eta0 = 0.0055 etab = 0
|
||||
+vfb = -0.55 u0 = 0.054 ua = 6e-010 ub = 1.2e-018
|
||||
+uc = 0 vsat = 170000 a0 = 1 ags = 0
|
||||
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
|
||||
+keta = 0.04 dwg = 0 dwb = 0 pclm = 0.02
|
||||
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = -0.005 drout = 0.5
|
||||
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 1e-007
|
||||
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2300000
|
||||
+rsh = 5 rdsw = 155 rsw = 80 rdw = 80
|
||||
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
|
||||
+prwb = 0 wr = 1 alpha0 = 0.074 alpha1 = 0.005
|
||||
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
|
||||
+egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
|
||||
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
|
||||
+eigbinv = 1.1 nigbinv = 3 aigc = 0.02 bigc = 0.0025
|
||||
+cigc = 0.002 aigsd = 0.02 bigsd = 0.0025 cigsd = 0.002
|
||||
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
|
||||
+xrcrg1 = 12 xrcrg2 = 5
|
||||
|
||||
+cgso = 1.1e-010 cgdo = 1.1e-010 cgbo = 2.56e-011 cgdl = 2.653e-010
|
||||
+cgsl = 2.653e-010 ckappas = 0.03 ckappad = 0.03 acde = 1
|
||||
+moin = 15 noff = 0.9 voffcv = 0.02
|
||||
|
||||
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
|
||||
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
|
||||
+at = 33000
|
||||
|
||||
+fnoimod = 1 tnoimod = 0
|
||||
|
||||
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
|
||||
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
|
||||
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
|
||||
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
|
||||
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
|
||||
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
|
||||
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
|
||||
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
|
||||
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
|
||||
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
|
||||
+xtis = 3 xtid = 3
|
||||
|
||||
+dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0
|
||||
+dwj = 0 xgw = 0 xgl = 0
|
||||
|
||||
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
|
||||
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
|
||||
|
||||
|
||||
|
||||
.model pmos pmos level = 54
|
||||
|
||||
+version = 4.0 binunit = 1 paramchk= 1 mobmod = 0
|
||||
+capmod = 2 igcmod = 1 igbmod = 1 geomod = 1
|
||||
+diomod = 1 rdsmod = 0 rbodymod= 1 rgatemod= 1
|
||||
+permod = 1 acnqsmod= 0 trnqsmod= 0
|
||||
|
||||
+tnom = 27 toxe = 1.3e-009 toxp = 1e-009 toxm = 1.3e-009
|
||||
+dtox = 3e-010 epsrox = 3.9 wint = 5e-009 lint = 3.75e-009
|
||||
+ll = 0 wl = 0 lln = 1 wln = 1
|
||||
+lw = 0 ww = 0 lwn = 1 wwn = 1
|
||||
+lwl = 0 wwl = 0 xpart = 0 toxref = 1.3e-009
|
||||
+xl = -20e-9
|
||||
|
||||
+vth0 = -0.49158 k1 = 0.4 k2 = -0.01 k3 = 0
|
||||
+k3b = 0 w0 = 2.5e-006 dvt0 = 1 dvt1 = 2
|
||||
+dvt2 = -0.032 dvt0w = 0 dvt1w = 0 dvt2w = 0
|
||||
+dsub = 0.1 minv = 0.05 voffl = 0 dvtp0 = 1e-011
|
||||
+dvtp1 = 0.05 lpe0 = 0 lpeb = 0 xj = 1.4e-008
|
||||
+ngate = 1e+023 ndep = 2.44e+018 nsd = 2e+020 phin = 0
|
||||
+cdsc = 0 cdscb = 0 cdscd = 0 cit = 0
|
||||
+voff = -0.126 nfactor = 2.1 eta0 = 0.0055 etab = 0
|
||||
+vfb = 0.55 u0 = 0.02 ua = 2e-009 ub = 5e-019
|
||||
+uc = 0 vsat = 150000 a0 = 1 ags = 1e-020
|
||||
+a1 = 0 a2 = 1 b0 = 0 b1 = 0
|
||||
+keta = -0.047 dwg = 0 dwb = 0 pclm = 0.12
|
||||
+pdiblc1 = 0.001 pdiblc2 = 0.001 pdiblcb = 3.4e-008 drout = 0.56
|
||||
+pvag = 1e-020 delta = 0.01 pscbe1 = 8.14e+008 pscbe2 = 9.58e-007
|
||||
+fprout = 0.2 pdits = 0.08 pditsd = 0.23 pditsl = 2300000
|
||||
+rsh = 5 rdsw = 155 rsw = 75 rdw = 75
|
||||
+rdswmin = 0 rdwmin = 0 rswmin = 0 prwg = 0
|
||||
+prwb = 0 wr = 1 alpha0 = 0.074 alpha1 = 0.005
|
||||
+beta0 = 30 agidl = 0.0002 bgidl = 2.1e+009 cgidl = 0.0002
|
||||
+egidl = 0.8 aigbacc = 0.012 bigbacc = 0.0028 cigbacc = 0.002
|
||||
+nigbacc = 1 aigbinv = 0.014 bigbinv = 0.004 cigbinv = 0.004
|
||||
+eigbinv = 1.1 nigbinv = 3 aigc = 0.010687 bigc = 0.0012607
|
||||
+cigc = 0.0008 aigsd = 0.010687 bigsd = 0.0012607 cigsd = 0.0008
|
||||
+nigc = 1 poxedge = 1 pigcd = 1 ntox = 1
|
||||
+xrcrg1 = 12 xrcrg2 = 5
|
||||
|
||||
+cgso = 1.1e-010 cgdo = 1.1e-010 cgbo = 2.56e-011 cgdl = 2.653e-010
|
||||
+cgsl = 2.653e-010 ckappas = 0.03 ckappad = 0.03 acde = 1
|
||||
+moin = 15 noff = 0.9 voffcv = 0.02
|
||||
|
||||
+kt1 = -0.11 kt1l = 0 kt2 = 0.022 ute = -1.5
|
||||
+ua1 = 4.31e-009 ub1 = 7.61e-018 uc1 = -5.6e-011 prt = 0
|
||||
+at = 33000
|
||||
|
||||
+fnoimod = 1 tnoimod = 0
|
||||
|
||||
+jss = 0.0001 jsws = 1e-011 jswgs = 1e-010 njs = 1
|
||||
+ijthsfwd= 0.01 ijthsrev= 0.001 bvs = 10 xjbvs = 1
|
||||
+jsd = 0.0001 jswd = 1e-011 jswgd = 1e-010 njd = 1
|
||||
+ijthdfwd= 0.01 ijthdrev= 0.001 bvd = 10 xjbvd = 1
|
||||
+pbs = 1 cjs = 0.0005 mjs = 0.5 pbsws = 1
|
||||
+cjsws = 5e-010 mjsws = 0.33 pbswgs = 1 cjswgs = 3e-010
|
||||
+mjswgs = 0.33 pbd = 1 cjd = 0.0005 mjd = 0.5
|
||||
+pbswd = 1 cjswd = 5e-010 mjswd = 0.33 pbswgd = 1
|
||||
+cjswgd = 5e-010 mjswgd = 0.33 tpb = 0.005 tcj = 0.001
|
||||
+tpbsw = 0.005 tcjsw = 0.001 tpbswg = 0.005 tcjswg = 0.001
|
||||
+xtis = 3 xtid = 3
|
||||
|
||||
+dmcg = 0 dmci = 0 dmdg = 0 dmcgt = 0
|
||||
+dwj = 0 xgw = 0 xgl = 0
|
||||
|
||||
+rshg = 0.4 gbmin = 1e-010 rbpb = 5 rbpd = 15
|
||||
+rbps = 15 rbdb = 15 rbsb = 15 ngcon = 1
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
|||
This technology file was generated using the Nano-CMOS tool from http://ptm.asu.edu/
|
||||
|
||||
The following default parameters were used:
|
||||
|
||||
NMOS
|
||||
Leff=17.5 nm 10%
|
||||
Vth=0.18 V 30mV
|
||||
Vdd=1 V
|
||||
Tox=1.1 nm
|
||||
Rdsw=155 Ohm
|
||||
|
||||
PMOS
|
||||
Leff=17.5 nm 10%
|
||||
Vth=-0.18 V 30mV
|
||||
Vdd=1 V
|
||||
Tox=1.1 nm
|
||||
Rdsw=155 Ohm
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,882 +0,0 @@
|
|||
<!--
|
||||
Flagship Heterogeneous Architecture with Carry Chains for VTR 7.0.
|
||||
|
||||
- 40 nm technology
|
||||
- General purpose logic block:
|
||||
K = 6, N = 10, fracturable 6 LUTs (can operate as one 6-LUT or two 5-LUTs with all 5 inputs shared)
|
||||
with optionally registered outputs
|
||||
Each 5-LUT has an arithemtic mode that converts it to a single-bit adder with both inputs driven by 4-LUTs (both 4-LUTs share all 4 inputs)
|
||||
Carry chain links to vertically adjacent logic blocks
|
||||
- Memory size 32 Kbits, memory aspect ratios vary from a data width of 1 to data width of 64.
|
||||
Height = 6, found on every (8n+2)th column
|
||||
- Multiplier modes: one 36x36, two 18x18, each 18x18 can also operate as two 9x9.
|
||||
Height = 4, found on every (8n+6)th column
|
||||
- Routing architecture: L = 4, fc_in = 0.15, Fc_out = 0.1
|
||||
|
||||
Details on Modelling:
|
||||
|
||||
The electrical design of the architecture described here is NOT from an
|
||||
optimized, SPICED architecture. Instead, we attempt to create a reasonable
|
||||
architecture file by using an existing commercial FPGA to approximate the area,
|
||||
delay, and power of the underlying components. This is combined with a reasonable 40 nm
|
||||
model of wiring and circuit design for low-level routing components, where available.
|
||||
The resulting architecture has delays that roughly match a commercial 40 nm FPGA, but also
|
||||
has wiring electrical parameters that allow the wire lengths and switch patterns to be
|
||||
modified and you will still get reasonable delay results for the new architecture.
|
||||
The following describes, in detail, how we obtained the various electrical values for this
|
||||
architecture.
|
||||
|
||||
Rmin for nmos and pmos, routing buffer sizes, and I/O pad delays are from the ifar
|
||||
architecture created by Ian Kuon: K06 N10 45nm fc 0.15 area-delay optimized architecture.
|
||||
(n10k06l04.fc15.area1delay1.cmos45nm.bptm.cmos45nm.xml)
|
||||
This routing architecture was optimized for 45 nm, and we have scaled it linearly to 40 nm to
|
||||
match the overall target (a 40 nm FPGA).
|
||||
|
||||
We obtain delay numbers by measuring delays of routing, soft logic blocks,
|
||||
memories, and multipliers from test circuits on a Stratix IV GX device
|
||||
(EP4SGX230DF29C2X, i.e. fastest speed grade). For routing, we took the average delay of H4 and V4
|
||||
wires. Rmetal and Cmetal values for the routing wires were obtained from work done by Charles
|
||||
Chiasson. We use a 96 nm half-pitch (corresponding to mid-level metal stack 40 nm routing) and
|
||||
take the R and C data from the ITRS roadmap.
|
||||
|
||||
For the general purpose logic block, we assume that the area and delays of the Stratix IV
|
||||
crossbar is close enough to the crossbar modelled here. We use 40 inputs and 20 feedback lines in
|
||||
the cluster and a full crossbar, leading to 53:1 multiplexers in front of each BLE input.
|
||||
Stratix IV uses 52 inputs and 20 feedback lines, but only a half-populated crossbar, leading to
|
||||
36:1 multiplexers. We require 60 such multiplexers, while Stratix IV requires 88 for its more
|
||||
complex fracturable BLEs + the extra control signals. We justify this rough approximation as follows:
|
||||
The Stratix IV crossbar has more inputs (72 vs. 60) and
|
||||
outputs (88 vs. 60) than our full crossbar which should increase its area and delay, but the
|
||||
Stratix IV crossbar is also 50% sparse (each mux is 36:1 instead of 53:1) which should reduce its
|
||||
area and delay. The total number of crossbar switch points is roughly similar between the two
|
||||
architectures (3160 for SIV and 3600 for the academic architecture below), so we use the area
|
||||
& delay of the Stratix IV crossbar as a rough approximation of our crossbar.
|
||||
|
||||
For LUTs, we include LUT
|
||||
delays measured from Stratix IV which is dependant on the input used (ie. some
|
||||
LUT inputs are faster than others). The CAD tools at the time of VTR 7 does
|
||||
not consider differences in LUT input delays.
|
||||
|
||||
Adder delays obtained as approximate values from a Stratix IV EP4SE230F29C3 device.
|
||||
Delay obtained by compiling a 256 bit adder (registered inputs and outputs,
|
||||
all pins except clock virtual) then measuring the delays in chip-planner,
|
||||
sumout delay = 0.271ns to 0.348 ns, intra-block carry delay = 0.011 ns,
|
||||
inter-block carry delay = 0.327 ns. Given this data, I will approximate
|
||||
sumout 0.3 ns, intra-block carry-delay = 0.01 ns, and
|
||||
inter-block carry-delay = 0.16 ns (since Altera inter-block carry delay has
|
||||
overhead that we don't have, I'll approximate the delay of a simpler chain at
|
||||
one half what they have. This is very rough, anything from 0.01ns to 0.327ns
|
||||
can be justified).
|
||||
|
||||
Logic block area numbers obtained by scaling overall tile area of a 65nm
|
||||
Stratix III device, (as given in Wong, Betz and Rose, FPGA 2011) to 40 nm, then subtracting out
|
||||
routing area at a channel width of 300. We use a channel width of 300 because it can route
|
||||
all the VTR 6.0 benchmark circuits with an approximately 20% safety margin, and is also close to the
|
||||
total channel width of Stratix IV. Hence this channel width is close to the commercial practice of
|
||||
choosing a width that provides high routability. The architecture can be routed at different channel
|
||||
widths, but we estimate the tile size and hence the physical length of routing wires assuming
|
||||
a channel width of 300.
|
||||
|
||||
Sanity checks employed:
|
||||
1. We confirmed the routing buffer delay is ~1/3rd of total routing delay at L = 4. This matches
|
||||
common electrical design.
|
||||
|
||||
|
||||
Authors: Jason Luu, Jeff Goeders, Vaughn Betz
|
||||
-->
|
||||
|
||||
|
||||
<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>
|
||||
<model name="io">
|
||||
<input_ports>
|
||||
<port name="outpad"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="inpad"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
<model name="adder">
|
||||
<input_ports>
|
||||
<port name="a"/>
|
||||
<port name="b"/>
|
||||
<port name="cin"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="cout"/>
|
||||
<port name="sumout"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
<model name="frac_lut6">
|
||||
<input_ports>
|
||||
<port name="in"/>
|
||||
</input_ports>
|
||||
<output_ports>
|
||||
<port name="lut6_out"/>
|
||||
<port name="lut5_out"/>
|
||||
<port name="lut4_out"/>
|
||||
</output_ports>
|
||||
</model>
|
||||
</models>
|
||||
<!-- ODIN II specific config ends -->
|
||||
|
||||
<!-- Physical descriptions begin -->
|
||||
<layout width="2" height="2"/>
|
||||
<spice_settings>
|
||||
<parameters>
|
||||
<options sim_temp="25" post="off" captab="off" fast="on"/>
|
||||
<monte_carlo mc_sim="off" num_mc_points="2" cmos_variation="off" rram_variation="off">
|
||||
<cmos abs_variation="0.1" num_sigma="3"/>
|
||||
<rram abs_variation="0.1" num_sigma="3"/>
|
||||
</monte_carlo>
|
||||
<measure sim_num_clock_cycle="auto" accuracy="1e-13" accuracy_type="abs">
|
||||
<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>
|
||||
</measure>
|
||||
<stimulate>
|
||||
<clock op_freq="auto" sim_slack="0.2" prog_freq="2.5e6">
|
||||
<rise slew_time="20e-12" slew_type="abs"/>
|
||||
<fall slew_time="20e-12" slew_type="abs"/>
|
||||
</clock>
|
||||
<input>
|
||||
<rise slew_time="25e-12" slew_type="abs"/>
|
||||
<fall slew_time="25e-12" slew_type="abs"/>
|
||||
</input>
|
||||
</stimulate>
|
||||
</parameters>
|
||||
<tech_lib lib_type="industry" transistor_type="TOP_TT" lib_path="/research/ece/lnis/USERS/tang/tangxifan-eda-tools/branches/subvt_fpga/process/tsmc40nm/toplevel.l" nominal_vdd="0.9" io_vdd="2.5"/>
|
||||
<transistors pn_ratio="2" model_ref="M">
|
||||
<nmos model_name="nch" chan_length="40e-9" min_width="140e-9"/>
|
||||
<pmos model_name="pch" chan_length="40e-9" min_width="140e-9"/>
|
||||
<io_nmos model_name="nch_25" chan_length="270e-9" min_width="320e-9"/>
|
||||
<io_pmos model_name="pch_25" chan_length="270e-9" min_width="320e-9"/>
|
||||
</transistors>
|
||||
<module_circuit_models>
|
||||
<circuit_model type="inv_buf" name="inv1" prefix="inv1" is_default="1">
|
||||
<design_technology type="cmos" topology="inverter" size="1" tapered="off"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="inv_buf" name="buf4" prefix="buf4" is_default="0">
|
||||
<design_technology type="cmos" topology="buffer" size="1" tapered="on" tap_drive_level="2" f_per_stage="4"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="inv_buf" name="tap_inv4" prefix="tap_inv4" is_default="0">
|
||||
<design_technology type="cmos" topology="buffer" size="1" tapered="on" tap_drive_level="3" f_per_stage="4"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="pass_gate" name="tgate" prefix="tgate" is_default="1">
|
||||
<design_technology type="cmos" topology="transmission_gate" nmos_size="1" pmos_size="2"/>
|
||||
<input_buffer exist="off"/>
|
||||
<output_buffer exist="off"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="input" prefix="sel" size="1"/>
|
||||
<port type="input" prefix="selb" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in sel selb" out_port="out">
|
||||
10e-12 0e-12 0e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in sel selb" out_port="out">
|
||||
10e-12 0e-12 0e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="gate" name="or2" prefix="or2" is_default="1" verilog_netlist="/research/ece/lnis/USERS/alacchi/clone_github/tangxifan-eda-tools/branches/vpr7_rram/vpr/VerilogNetlists/sram.v/VerilogNetlists/essential_gates.v">
|
||||
<design_technology type="cmos" topology="OR"/>
|
||||
<input_buffer exist="off"/>
|
||||
<output_buffer exist="off"/>
|
||||
<port type="input" prefix="in" size="2"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<delay_matrix type="rise" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
<delay_matrix type="fall" in_port="in" out_port="out">
|
||||
10e-12
|
||||
</delay_matrix>
|
||||
</circuit_model>
|
||||
<circuit_model type="chan_wire" name="chan_segment" prefix="track_seg" is_default="1">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="off"/>
|
||||
<output_buffer exist="off"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<wire_param model_type="pie" res_val="101" cap_val="22.5e-15" level="1"/> <!-- model_type could be T, res_val and cap_val DON'T CARE -->
|
||||
</circuit_model>
|
||||
<circuit_model type="wire" name="direct_interc" prefix="direct_interc" is_default="1">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="off"/>
|
||||
<output_buffer exist="off"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<wire_param model_type="pie" res_val="0" cap_val="0" level="1"/> <!-- model_type could be T, res_val cap_val should be defined -->
|
||||
</circuit_model>
|
||||
<circuit_model type="mux" name="mux_tree_like" prefix="mux_tree_like" dump_structural_verilog="true">
|
||||
<design_technology type="cmos" structure="tree-like" add_const_input="true" const_input_val="1"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<!--mux2to1 subckt_name="mux2to1"/-->
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="mux" name="mux_tree_like_tapbuf" prefix="mux_tree_like_tapbuf" dump_structural_verilog="true" is_default="0">
|
||||
<design_technology type="cmos" structure="tree-like" add_const_input="true" const_input_val="1"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="tap_inv4"/>
|
||||
<!--mux2to1 subckt_name="mux2to1"/-->
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="mux" name="mux_1level_tapbuf" prefix="mux_1level_tapbuf" is_default="1" dump_structural_verilog="true">
|
||||
<design_technology type="cmos" structure="tree-like" add_const_input="true" const_input_val="1"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="tap_inv4"/>
|
||||
<!--mux2to1 subckt_name="mux2to1"/-->
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="1"/>
|
||||
<port type="sram" prefix="sram" size="1"/>
|
||||
</circuit_model>
|
||||
<!--DFF subckt ports should be defined as <D> <Q> <CLK> <RESET> <SET> -->
|
||||
<circuit_model type="ff" name="static_dff" prefix="dff" spice_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/SpiceNetlists/ff.sp" verilog_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/VerilogNetlists/ff.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="D" size="1"/>
|
||||
<port type="input" prefix="Set" size="1" is_global="true" default_val="0" is_set="true"/>
|
||||
<port type="input" prefix="Reset" size="1" is_global="true" default_val="1" is_reset="true"/>
|
||||
<port type="output" prefix="Q" size="1"/>
|
||||
<port type="clock" prefix="clk" size="1" is_global="true" default_val="0" />
|
||||
</circuit_model>
|
||||
<circuit_model type="lut" name="frac_lut6" prefix="frac_lut6" dump_structural_verilog="true">
|
||||
<design_technology type="cmos" fracturable_lut="true"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<lut_input_buffer exist="on" circuit_model_name="buf4"/>
|
||||
<lut_input_inverter exist="on" circuit_model_name="inv1"/>
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="in" size="6" tri_state_map="----11" circuit_model_name="or2"/>
|
||||
<port type="output" prefix="lut4_out" size="4" lut_frac_level="4" lut_output_mask="0,1,2,3"/>
|
||||
<port type="output" prefix="lut5_out" size="2" lut_frac_level="5" lut_output_mask="0,1"/>
|
||||
<port type="output" prefix="lut6_out" size="1" lut_output_mask="0"/>
|
||||
<port type="sram" prefix="sram" size="64"/>
|
||||
<port type="sram" prefix="mode" size="2" mode_select="true" circuit_model_name="sc_dff_compact" default_val="1"/>
|
||||
</circuit_model>
|
||||
<!--Scan-chain DFF subckt ports should be defined as <D> <Q> <Qb> <CLK> <RESET> <SET> -->
|
||||
<circuit_model type="sff" name="sc_dff_compact" prefix="scff" spice_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/SpiceNetlists/ff.sp" verilog_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/VerilogNetlists/ff.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="pReset" size="1" is_global="true" default_val="1" is_reset="true" is_prog="true"/>
|
||||
<port type="input" prefix="pSet" size="1" is_global="true" default_val="0" is_set="true" is_prog="true"/>
|
||||
<port type="input" prefix="D" size="1"/>
|
||||
<port type="output" prefix="Q" size="1"/>
|
||||
<port type="output" prefix="Qb" size="1"/>
|
||||
<port type="clock" prefix="prog_clk" size="1" is_global="true" default_val="0" is_prog="true"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="iopad" name="iopad" prefix="iopad" spice_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/SpiceNetlists/io.sp" verilog_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/VerilogNetlists/io.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="inout" prefix="pad" size="1"/>
|
||||
<port type="sram" prefix="en" size="1" mode_select="true" circuit_model_name="sc_dff_compact" default_val="1"/>
|
||||
<!--port type="sram" prefix="enb" size="1" mode_select="true" circuit_model_name="sc_dff_compact" default_val="0"/-->
|
||||
<port type="input" prefix="outpad" size="1"/>
|
||||
<!-- <port type="input" prefix="zin" size="1" is_global="true" default_val="0" /> -->
|
||||
<port type="output" prefix="inpad" size="1"/>
|
||||
</circuit_model>
|
||||
<!-- Hard logic definition for heterogenous blocks -->
|
||||
<circuit_model type="hard_logic" name="adder_1bit" prefix="adder" spice_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/SpiceNetlists/adder.sp" verilog_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/VerilogNetlists/adder.v">
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<port type="input" prefix="a" size="1"/>
|
||||
<port type="input" prefix="b" size="1"/>
|
||||
<port type="input" prefix="cin" size="1"/>
|
||||
<port type="output" prefix="sumout" size="1"/>
|
||||
<port type="output" prefix="cout" size="1"/>
|
||||
</circuit_model>
|
||||
<circuit_model type="sram" name="sram6T" prefix="sram" spice_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/SpiceNetlists/sram.sp" verilog_netlist="/research/ece/lnis/USERS/alacchi/Current_release/OpenFPGA/vpr7_x2p/vpr/VerilogNetlists/sram.v" >
|
||||
<design_technology type="cmos"/>
|
||||
<input_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<output_buffer exist="on" circuit_model_name="inv1"/>
|
||||
<pass_gate_logic circuit_model_name="tgate"/>
|
||||
<port type="input" prefix="in" size="1"/>
|
||||
<port type="output" prefix="out" size="2"/>
|
||||
</circuit_model>
|
||||
|
||||
</module_circuit_models>
|
||||
</spice_settings>
|
||||
<device>
|
||||
<!-- VB & JL: Using Ian Kuon's transistor sizing and drive strength data for routing, at 40 nm. Ian used BPTM
|
||||
models. We are modifying the delay values however, to include metal C and R, which allows more architecture
|
||||
experimentation. We are also modifying the relative resistance of PMOS to be 1.8x that of NMOS
|
||||
(vs. Ian's 3x) as 1.8x lines up with Jeff G's data from a 45 nm process (and is more typical of
|
||||
45 nm in general). I'm upping the Rmin_nmos from Ian's just over 6k to nearly 9k, and dropping
|
||||
RminW_pmos from 18k to 16k to hit this 1.8x ratio, while keeping the delays of buffers approximately
|
||||
lined up with Stratix IV.
|
||||
We are using Jeff G.'s capacitance data for 45 nm (in tech/ptm_45nm).
|
||||
Jeff's tables list C in for transistors with widths in multiples of the minimum feature size (45 nm).
|
||||
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply drive strength sizes in this file
|
||||
by 2.5x when looking up in Jeff's tables.
|
||||
The delay values are lined up with Stratix IV, which has an architecture similar to this
|
||||
proposed FPGA, and which is also 40 nm
|
||||
C_ipin_cblock: input capacitance of a track buffer, which VPR assumes is a single-stage
|
||||
4x minimum drive strength buffer. -->
|
||||
|
||||
<sizing R_minW_nmos="8926" R_minW_pmos="16067" ipin_mux_trans_size="9"/>
|
||||
<timing C_ipin_cblock="596e-18" T_ipin_cblock="77.93e-12"/>
|
||||
|
||||
<!-- 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"/>
|
||||
<sram area="6">
|
||||
<verilog organization="scan-chain" circuit_model_name="sc_dff_compact"/>
|
||||
<!--verilog organization="memory-bank" circuit_model_name="sram6T_blwl"/-->
|
||||
<spice organization="standalone" circuit_model_name="sram6T" />
|
||||
</sram>
|
||||
<chan_width_distr>
|
||||
<io width="1.000000"/>
|
||||
<x distr="uniform" peak="1.000000"/>
|
||||
<y distr="uniform" peak="1.000000"/>
|
||||
</chan_width_distr>
|
||||
<switch_block type="wilton" fs="3"/>
|
||||
</device>
|
||||
|
||||
<cblocks>
|
||||
<switch type="mux" name="cb_mux" R="0" Cin="596e-18" Cout="0" Tdel="77.93e-12" mux_trans_size="3" buf_size="63" circuit_model_name="mux_tree_like_tapbuf" structure="tree-like" num_level="2">
|
||||
</switch>
|
||||
</cblocks>
|
||||
<switchlist>
|
||||
<!-- VB: the mux_trans_size and buf_size data below is in minimum width transistor *areas*, assuming the purple
|
||||
book area formula. This means the mux transistors are about 5x minimum drive strength.
|
||||
We assume the first stage of the buffer is 3x min drive strength to be reasonable given the large
|
||||
mux transistors, and this gives a reasonable stage ratio of a bit over 5x to the second stage. We assume
|
||||
the n and p transistors in the first stage are equal-sized to lower the buffer trip point, since it's fed
|
||||
by a pass transistor mux. We can then reverse engineer the buffer second stage to hit the specified
|
||||
buf_size (really buffer area) - 16.2x minimum drive nmos and 1.8*16.2 = 29.2x minimum drive.
|
||||
I then took the data from Jeff G.'s PTM modeling of 45 nm to get the Cin (gate of first stage) and Cout
|
||||
(diff of second stage) listed below. Jeff's models are in tech/ptm_45nm, and are in min feature multiples.
|
||||
The minimum contactable transistor is 2.5 * 45 nm, so I need to multiply the drive strength sizes above by
|
||||
2.5x when looking up in Jeff's tables.
|
||||
Finally, we choose a switch delay (58 ps) that leads to length 4 wires having a delay equal to that of SIV of 126 ps.
|
||||
This also leads to the switch being 46% of the total wire delay, which is reasonable. -->
|
||||
<switch type="mux" name="sb_mux_L4" R="105" Cin="596e-18" Cout="0e-15" Tdel="47.2e-12" mux_trans_size="3" buf_size="63" circuit_model_name="mux_tree_like_tapbuf" structure="tree-like" num_level="1">
|
||||
</switch>
|
||||
<switch type="mux" name="sb_mux_L2" R="115" Cin="596e-18" Cout="0e-15" Tdel="47.2e-12" mux_trans_size="3" buf_size="63" circuit_model_name="mux_tree_like_tapbuf" structure="tree-like" num_level="1">
|
||||
</switch>
|
||||
<switch type="mux" name="sb_mux_L1" R="128" Cin="596e-18" Cout="0e-15" Tdel="47.2e-12" mux_trans_size="3" buf_size="63" circuit_model_name="mux_tree_like_tapbuf" structure="tree-like" num_level="1">
|
||||
</switch>
|
||||
</switchlist>
|
||||
<segmentlist>
|
||||
<!--- VB & JL: using ITRS metal stack data, 96 nm half pitch wires, which are intermediate metal width/space.
|
||||
With the 96 nm half pitch, such wires would take 60 um of height, vs. a 90 nm high (approximated as square) Stratix IV tile so this seems
|
||||
reasonable. Using a tile length of 90 nm, corresponding to the length of a Stratix IV tile if it were square. -->
|
||||
<segment freq="0.4" length="4" type="unidir" Rmetal="101" Cmetal="22.5e-15" circuit_model_name="chan_segment">
|
||||
<mux name="sb_mux_L4"/>
|
||||
<sb type="pattern">1 1 1 1 1</sb>
|
||||
<cb type="pattern">1 1 1 1</cb>
|
||||
</segment>
|
||||
<segment freq="0.3" length="2" type="unidir" Rmetal="101" Cmetal="22.5e-15" circuit_model_name="chan_segment">
|
||||
<mux name="sb_mux_L4"/>
|
||||
<sb type="pattern">1 1 1</sb>
|
||||
<cb type="pattern">1 1 </cb>
|
||||
</segment>
|
||||
<segment freq="0.3" length="1" type="unidir" Rmetal="101" Cmetal="22.5e-15" circuit_model_name="chan_segment">
|
||||
<mux name="sb_mux_L4"/>
|
||||
<sb type="pattern">1 1</sb>
|
||||
<cb type="pattern">1</cb>
|
||||
</segment>
|
||||
</segmentlist>
|
||||
<!--switch_segment_patterns>
|
||||
<pattern type="unbuf_sb" seg_length="1" seg_type="unidir" pattern_length="2">
|
||||
<unbuf_mux name="1"/>
|
||||
<sb type ="pattern">0 1</sb>
|
||||
</pattern>
|
||||
</switch_segment_patterns-->
|
||||
|
||||
<complexblocklist>
|
||||
|
||||
<!-- Define I/O pads begin -->
|
||||
<!-- Capacity is a unique property of I/Os, it is the maximum number of I/Os that can be placed at the same (X,Y) location on the FPGA -->
|
||||
<!-- Not sure of the area of an I/O (varies widely), and it's not relevant to the design of the FPGA core, so we're setting it to 0. -->
|
||||
<pb_type name="io" capacity="7" area="0" idle_mode_name="inpad" physical_mode_name="io_phy">
|
||||
<input name="outpad" num_pins="1"/>
|
||||
<output name="inpad" num_pins="1"/>
|
||||
|
||||
<!-- physical design description -->
|
||||
<mode name="io_phy" disabled_in_packing="true">
|
||||
<pb_type name="iopad" blif_model=".subckt io" num_pb="1" circuit_model_name="iopad" mode_bits="1">
|
||||
<input name="outpad" num_pins="1"/>
|
||||
<output name="inpad" num_pins="1"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="inpad" input="iopad.inpad" output="io.inpad">
|
||||
<delay_constant max="0e-11" in_port="iopad.inpad" out_port="io.inpad"/>
|
||||
</direct>
|
||||
<direct name="outpad" input="io.outpad" output="iopad.outpad">
|
||||
<delay_constant max="0e-11" in_port="io.outpad" out_port="iopad.outpad"/>
|
||||
</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" physical_pb_type_name="iopad" mode_bits="1">
|
||||
<output name="inpad" num_pins="1" physical_mode_pin="inpad"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="inpad" input="inpad.inpad" output="io.inpad">
|
||||
<delay_constant max="0e-11" in_port="inpad.inpad" out_port="io.inpad"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="outpad">
|
||||
<pb_type name="outpad" blif_model=".output" num_pb="1" physical_pb_type_name="iopad" mode_bits="0">
|
||||
<input name="outpad" num_pins="1" physical_mode_pin="outpad"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="outpad" input="io.outpad" output="outpad.outpad">
|
||||
<delay_constant max="0e-11" in_port="io.outpad" out_port="outpad.outpad"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode>
|
||||
|
||||
<!-- 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 -->
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.10"/>
|
||||
|
||||
<!-- IOs go on the periphery of the FPGA, for consistency,
|
||||
make it physically equivalent on all sides so that only one definition of I/Os is needed.
|
||||
If I do not make a physically equivalent definition, then I need to define 4 different I/Os, one for each side of the FPGA
|
||||
-->
|
||||
<pinlocations pattern="custom">
|
||||
<loc side="left">io.outpad io.inpad</loc>
|
||||
<loc side="top">io.outpad io.inpad</loc>
|
||||
<loc side="right">io.outpad io.inpad</loc>
|
||||
<loc side="bottom">io.outpad io.inpad</loc>
|
||||
</pinlocations>
|
||||
|
||||
<!-- Place I/Os on the sides of the FPGA -->
|
||||
<gridlocations>
|
||||
<loc type="perimeter" priority="10"/>
|
||||
</gridlocations>
|
||||
|
||||
<power method="ignore"/>
|
||||
</pb_type>
|
||||
<!-- Define I/O pads ends -->
|
||||
|
||||
|
||||
<!-- Define general purpose logic block (CLB) begin -->
|
||||
<!--- Area calculation: Total Stratix IV tile area is about 8100 um^2, and a minimum width transistor
|
||||
area is 60 L^2 yields a tile area of 84375 MWTAs.
|
||||
Routing at W=300 is 30481 MWTAs, leaving us with a total of 53000 MWTAs for logic block area
|
||||
This means that only 37% of our area is in the general routing, and 63% is inside the logic
|
||||
block. Note that the crossbar / local interconnect is considered part of the logic block
|
||||
area in this analysis. That is a lower proportion of of routing area than most academics
|
||||
assume, but note that the total routing area really includes the crossbar, which would push
|
||||
routing area up significantly, we estimate into the ~70% range.
|
||||
-->
|
||||
<pb_type name="clb" area="53894">
|
||||
<input name="I" num_pins="40" equivalent="true"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="O" num_pins="20" equivalent="false"/>
|
||||
<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="10" physical_mode_name="fle_phy" idle_mode_name="n2_lut5">
|
||||
<input name="in" num_pins="6"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="out" num_pins="2"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
|
||||
<mode name="fle_phy" disabled_in_packing="true">
|
||||
<pb_type name="frac_logic" num_pb="1">
|
||||
<input name="in" num_pins="6"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="out" num_pins="2"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<pb_type name="frac_lut6" blif_model=".frac_lut6" mode_bits="11" num_pb="1" circuit_model_name="frac_lut6">
|
||||
<input name="in" num_pins="6"/>
|
||||
<output name="lut4_out" num_pins="4"/>
|
||||
<output name="lut5_out" num_pins="2"/>
|
||||
<output name="lut6_out" num_pins="1"/>
|
||||
</pb_type>
|
||||
<pb_type name="adder_phy" blif_model=".subckt adder" num_pb="2" circuit_model_name="adder_1bit">
|
||||
<input name="a" num_pins="1"/>
|
||||
<input name="b" num_pins="1"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<output name="sumout" num_pins="1"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct_fraclut_in" input="frac_logic.in[5:0]" output="frac_lut6.in[5:0]"/>
|
||||
<direct name="direct_cin" input="frac_logic.cin" output="adder_phy[0].cin"/>
|
||||
<direct name="direct_carry" input="adder_phy[0].cout" output="adder_phy[1].cin"/>
|
||||
<direct name="direct_cout" input="adder_phy[1].cout" output="frac_logic.cout"/>
|
||||
<direct name="direct_lut4carry0" input="frac_lut6.lut4_out[0]" output="adder_phy[0].a"/>
|
||||
<direct name="direct_lut4carry1" input="frac_lut6.lut4_out[1]" output="adder_phy[0].b"/>
|
||||
<direct name="direct_lut4carry2" input="frac_lut6.lut4_out[2]" output="adder_phy[1].a"/>
|
||||
<direct name="direct_lut4carry3" input="frac_lut6.lut4_out[3]" output="adder_phy[1].b"/>
|
||||
<mux name="mux1" input="adder_phy[0].sumout frac_lut6.lut5_out[0]" output="frac_logic.out[0]">
|
||||
<mode_select mode_name="n2_lut5.arithmetic" in_port="adder_phy[0].sumout" out_port="frac_logic.out[0]"/>
|
||||
<mode_select mode_name="n2_lut5.blut5" in_port="frac_lut6.lut5_out[0]" out_port="frac_logic.out[0]"/>
|
||||
<mode_select mode_name="n1_lut6" in_port="frac_lut6.lut5_out[0]" out_port="frac_logic.out[0]"/>
|
||||
</mux>
|
||||
<mux name="mux2" input="adder_phy[1].sumout frac_lut6.lut5_out[1] frac_lut6.lut6_out[0]" output="frac_logic.out[1]">
|
||||
<mode_select mode_name="n2_lut5.arithmetic" in_port="adder_phy[1].sumout" out_port="frac_logic.out[1]"/>
|
||||
<mode_select mode_name="n2_lut5.blut5" in_port="frac_lut6.lut5_out[1]" out_port="frac_logic.out[1]"/>
|
||||
<mode_select mode_name="n1_lut6" in_port="frac_lut6.lut6_out[0]" out_port="frac_logic.out[1]"/>
|
||||
</mux>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<pb_type name="ff_phy" blif_model=".latch" num_pb="2" class="flipflop" circuit_model_name="static_dff">
|
||||
<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="66e-12" port="ff_phy.D" clock="clk"/>
|
||||
<T_clock_to_Q max="124e-12" port="ff_phy.Q" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<complete name="direct_clk" input="fle.clk" output="ff_phy[1:0].clk"/>
|
||||
<direct name="direct_in" input="fle.in[5:0]" output="frac_logic.in[5:0]"/>
|
||||
<direct name="direct_cin" input="fle.cin" output="frac_logic.cin"/>
|
||||
<direct name="direct_cout" input="frac_logic.cout" output="fle.cout"/>
|
||||
<direct name="direct_frac_out1" input="frac_logic.out[0]" output="ff_phy[0].D"/>
|
||||
<direct name="direct_frac_out2" input="frac_logic.out[1]" output="ff_phy[1].D"/>
|
||||
<mux name="mux1" input="ff_phy[0].Q frac_logic.out[0]" output="fle.out[0]">
|
||||
</mux>
|
||||
<mux name="mux2" input="ff_phy[1].Q frac_logic.out[1]" output="fle.out[1]">
|
||||
</mux>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="n2_lut5" disabled_in_packing="false">
|
||||
<!-- multi-mode support -->
|
||||
<pb_type name="lut5inter" num_pb="1">
|
||||
<input name="in" num_pins="5"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="out" num_pins="2"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<pb_type name="ble5" num_pb="2" idle_mode_name="blut5">
|
||||
<input name="in" num_pins="5"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<mode name="blut5">
|
||||
<pb_type name="flut5" num_pb="1">
|
||||
<input name="in" num_pins="5"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<!-- Regular LUT mode -->
|
||||
<pb_type name="lut5" blif_model=".names" num_pb="1" class="lut" mode_bits="01" physical_pb_type_name="frac_lut6" physical_pb_type_index_factor="0.5">
|
||||
<input name="in" num_pins="5" port_class="lut_in" physical_mode_pin="in[5:0]"/>
|
||||
<output name="out" num_pins="1" port_class="lut_out" physical_mode_pin="lut5_out" physical_mode_pin_rotate_offset="1"/>
|
||||
<!-- LUT timing using delay matrix -->
|
||||
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
|
||||
we instead take the average of these numbers to get more stable results
|
||||
82e-12
|
||||
173e-12
|
||||
261e-12
|
||||
263e-12
|
||||
398e-12
|
||||
-->
|
||||
<delay_matrix type="max" in_port="lut5.in" out_port="lut5.out">
|
||||
235e-12
|
||||
235e-12
|
||||
235e-12
|
||||
235e-12
|
||||
235e-12
|
||||
</delay_matrix>
|
||||
</pb_type>
|
||||
|
||||
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop" physical_pb_type_name="ff_phy">
|
||||
<input name="D" num_pins="1" port_class="D" physical_mode_pin="D"/>
|
||||
<output name="Q" num_pins="1" port_class="Q" physical_mode_pin="Q"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock" physical_mode_pin="clk"/>
|
||||
<T_setup value="66e-12" port="ff.D" clock="clk"/>
|
||||
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="flut5.in" output="lut5.in"/>
|
||||
<direct name="direct2" input="lut5.out" output="ff.D">
|
||||
<pack_pattern name="ble5" in_port="lut5.out" out_port="ff.D"/>
|
||||
</direct>
|
||||
<direct name="direct3" input="flut5.clk" output="ff.clk"/>
|
||||
<mux name="mux1" input="ff.Q lut5.out" output="flut5.out" spice_model_sram_offset="0">
|
||||
<delay_constant max="25e-12" in_port="lut5.out" out_port="flut5.out" />
|
||||
<delay_constant max="45e-12" in_port="ff.Q" out_port="flut5.out" />
|
||||
</mux>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="ble5.in" output="flut5.in"/>
|
||||
<direct name="direct2" input="ble5.clk" output="flut5.clk"/>
|
||||
<direct name="direct3" input="flut5.out" output="ble5.out"/>
|
||||
</interconnect>
|
||||
</mode>
|
||||
<mode name="arithmetic">
|
||||
<pb_type name="arithmetic" num_pb="1">
|
||||
<input name="in" num_pins="4"/>
|
||||
<input name="cin" num_pins="1"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<output name="cout" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<!-- Special dual-LUT mode that drives adder only -->
|
||||
<pb_type name="lut4" blif_model=".names" num_pb="2" class="lut" mode_bits="11" physical_pb_type_name="frac_lut6" physical_pb_type_index_factor="0.25">
|
||||
<input name="in" num_pins="4" port_class="lut_in" physical_mode_pin="in[4:0]"/>
|
||||
<output name="out" num_pins="1" port_class="lut_out" physical_mode_pin="lut4_out" physical_mode_pin_rotate_offset="1"/>
|
||||
<!-- LUT timing using delay matrix -->
|
||||
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
|
||||
we instead take the average of these numbers to get more stable results
|
||||
82e-12
|
||||
173e-12
|
||||
261e-12
|
||||
263e-12
|
||||
-->
|
||||
<delay_matrix type="max" in_port="lut4.in" out_port="lut4.out">
|
||||
195e-12
|
||||
195e-12
|
||||
195e-12
|
||||
195e-12
|
||||
</delay_matrix>
|
||||
</pb_type>
|
||||
<pb_type name="adder" blif_model=".subckt adder" num_pb="1" physical_pb_type_name="adder_phy">
|
||||
<input name="a" num_pins="1" physical_mode_pin="a"/>
|
||||
<input name="b" num_pins="1" physical_mode_pin="b"/>
|
||||
<input name="cin" num_pins="1" physical_mode_pin="cin"/>
|
||||
<output name="cout" num_pins="1" physical_mode_pin="cout"/>
|
||||
<output name="sumout" num_pins="1" physical_mode_pin="sumout"/>
|
||||
<delay_constant max="0.3e-9" in_port="adder.a" out_port="adder.sumout"/>
|
||||
<delay_constant max="0.3e-9" in_port="adder.b" out_port="adder.sumout"/>
|
||||
<delay_constant max="0.3e-9" in_port="adder.cin" out_port="adder.sumout"/>
|
||||
<delay_constant max="0.3e-9" in_port="adder.a" out_port="adder.cout"/>
|
||||
<delay_constant max="0.3e-9" in_port="adder.b" out_port="adder.cout"/>
|
||||
<delay_constant max="0.01e-9" in_port="adder.cin" out_port="adder.cout"/>
|
||||
</pb_type>
|
||||
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop" physical_pb_type_name="ff_phy">
|
||||
<input name="D" num_pins="1" port_class="D" physical_mode_pin="D"/>
|
||||
<output name="Q" num_pins="1" port_class="Q" physical_mode_pin="Q"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock" physical_mode_pin="clk"/>
|
||||
<T_setup value="66e-12" port="ff.D" clock="clk"/>
|
||||
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="clock" input="arithmetic.clk" output="ff.clk"/>
|
||||
<direct name="lut_in1" input="arithmetic.in[3:0]" output="lut4[0:0].in[3:0]"/>
|
||||
<direct name="lut_in2" input="arithmetic.in[3:0]" output="lut4[1:1].in[3:0]"/>
|
||||
<direct name="lut_to_add1" input="lut4[0:0].out" output="adder.a">
|
||||
</direct>
|
||||
<direct name="lut_to_add2" input="lut4[1:1].out" output="adder.b">
|
||||
</direct>
|
||||
<direct name="add_to_ff" input="adder.sumout" output="ff.D">
|
||||
<pack_pattern name="chain" in_port="adder.sumout" out_port="ff.D"/>
|
||||
</direct>
|
||||
<direct name="carry_in" input="arithmetic.cin" output="adder.cin">
|
||||
<pack_pattern name="chain" in_port="arithmetic.cin" out_port="adder.cin"/>
|
||||
</direct>
|
||||
<direct name="carry_out" input="adder.cout" output="arithmetic.cout">
|
||||
<pack_pattern name="chain" in_port="adder.cout" out_port="arithmetic.cout"/>
|
||||
</direct>
|
||||
<mux name="sumout" input="ff.Q adder.sumout" output="arithmetic.out">
|
||||
<delay_constant max="25e-12" in_port="adder.sumout" out_port="arithmetic.out"/>
|
||||
<delay_constant max="45e-12" in_port="ff.Q" out_port="arithmetic.out" />
|
||||
</mux>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="direct1" input="ble5.in[3:0]" output="arithmetic.in"/>
|
||||
<direct name="carry_in" input="ble5.cin" output="arithmetic.cin">
|
||||
<pack_pattern name="chain" in_port="ble5.cin" out_port="arithmetic.cin"/>
|
||||
</direct>
|
||||
<direct name="carry_out" input="arithmetic.cout" output="ble5.cout">
|
||||
<pack_pattern name="chain" in_port="arithmetic.cout" out_port="ble5.cout"/>
|
||||
</direct>
|
||||
<direct name="direct2" input="ble5.clk" output="arithmetic.clk"/>
|
||||
<direct name="direct3" input="arithmetic.out" output="ble5.out"/>
|
||||
</interconnect>
|
||||
</mode>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="lut5inter.in" output="ble5[0:0].in"/>
|
||||
<direct name="direct2" input="lut5inter.in" output="ble5[1:1].in"/>
|
||||
<direct name="direct3" input="ble5[1:0].out" output="lut5inter.out"/>
|
||||
<direct name="carry_in" input="lut5inter.cin" output="ble5[0:0].cin">
|
||||
<pack_pattern name="chain" in_port="lut5inter.cin" out_port="ble5[0:0].cin"/>
|
||||
</direct>
|
||||
<direct name="carry_out" input="ble5[1:1].cout" output="lut5inter.cout">
|
||||
<pack_pattern name="chain" in_port="ble5[1:1].cout" out_port="lut5inter.cout"/>
|
||||
</direct>
|
||||
<direct name="carry_link" input="ble5[0:0].cout" output="ble5[1:1].cin">
|
||||
<pack_pattern name="chain" in_port="ble5[0:0].cout" out_port="ble5[1:1].cout"/>
|
||||
</direct>
|
||||
<complete name="complete1" input="lut5inter.clk" output="ble5[1:0].clk"/>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="fle.in[4:0]" output="lut5inter.in"/>
|
||||
<direct name="direct2" input="lut5inter.out" output="fle.out"/>
|
||||
<direct name="direct3" input="fle.clk" output="lut5inter.clk"/>
|
||||
<direct name="carry_in" input="fle.cin" output="lut5inter.cin">
|
||||
<pack_pattern name="chain" in_port="fle.cin" out_port="lut5inter.cin"/>
|
||||
</direct>
|
||||
<direct name="carry_out" input="lut5inter.cout" output="fle.cout">
|
||||
<pack_pattern name="chain" in_port="lut5inter.cout" out_port="fle.cout"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
</mode> <!-- n2_lut5 -->
|
||||
<mode name="n1_lut6">
|
||||
<pb_type name="ble6" num_pb="1">
|
||||
<input name="in" num_pins="6"/>
|
||||
<output name="out" num_pins="1"/>
|
||||
<clock name="clk" num_pins="1"/>
|
||||
<pb_type name="lut6" blif_model=".names" num_pb="1" class="lut" mode_bits="00" physical_pb_type_name="frac_lut6" spice_model_sram_offset="0">
|
||||
<input name="in" num_pins="6" port_class="lut_in" physical_mode_pin="in[5:0]"/>
|
||||
<output name="out" num_pins="1" port_class="lut_out" physical_mode_pin="lut6_out[0]"/>
|
||||
<!-- LUT timing using delay matrix -->
|
||||
<!-- These are the physical delay inputs on a Stratix IV LUT but because VPR cannot do LUT rebalancing,
|
||||
we instead take the average of these numbers to get more stable results
|
||||
82e-12
|
||||
173e-12
|
||||
261e-12
|
||||
263e-12
|
||||
398e-12
|
||||
397e-12
|
||||
-->
|
||||
<delay_matrix type="max" in_port="lut6.in" out_port="lut6.out">
|
||||
261e-12
|
||||
261e-12
|
||||
261e-12
|
||||
261e-12
|
||||
261e-12
|
||||
261e-12
|
||||
</delay_matrix>
|
||||
</pb_type>
|
||||
<pb_type name="ff" blif_model=".latch" num_pb="1" class="flipflop" physical_pb_type_name="ff_phy" physical_pb_type_index_factor="2" physical_pb_type_index_offset="1">
|
||||
<input name="D" num_pins="1" port_class="D" physical_mode_pin="D"/>
|
||||
<output name="Q" num_pins="1" port_class="Q" physical_mode_pin="Q"/>
|
||||
<clock name="clk" num_pins="1" port_class="clock" physical_mode_pin="clk"/>
|
||||
<T_setup value="66e-12" port="ff.D" clock="clk"/>
|
||||
<T_clock_to_Q max="124e-12" port="ff.Q" clock="clk"/>
|
||||
</pb_type>
|
||||
|
||||
<interconnect>
|
||||
<direct name="direct1" input="ble6.in" output="lut6[0:0].in"/>
|
||||
<direct name="direct2" input="lut6.out" output="ff.D">
|
||||
<pack_pattern name="ble6" in_port="lut6.out" out_port="ff.D"/>
|
||||
</direct>
|
||||
<direct name="direct3" input="ble6.clk" output="ff.clk"/>
|
||||
<mux name="mux1" input="ff.Q lut6.out" output="ble6.out">
|
||||
<delay_constant max="25e-12" in_port="lut6.out" out_port="ble6.out" />
|
||||
<delay_constant max="45e-12" in_port="ff.Q" out_port="ble6.out" />
|
||||
</mux>
|
||||
</interconnect>
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<direct name="direct1" input="fle.in" output="ble6.in"/>
|
||||
<direct name="direct2" input="ble6.out" output="fle.out[1:1]"/>
|
||||
<direct name="direct3" input="fle.clk" output="ble6.clk"/>
|
||||
</interconnect>
|
||||
</mode> <!-- n1_lut6 -->
|
||||
</pb_type>
|
||||
<interconnect>
|
||||
<!-- We use a full crossbar to get logical equivalence at inputs of CLB
|
||||
The delays below come from Stratix IV. the delay through a connection block
|
||||
input mux + the crossbar in Stratix IV is 167 ps. We already have a 72 ps
|
||||
delay on the connection block input mux (modeled by Ian Kuon), so the remaining
|
||||
delay within the crossbar is 95 ps.
|
||||
The delays of cluster feedbacks in Stratix IV is 100 ps, when driven by a LUT.
|
||||
Since all our outputs LUT outputs go to a BLE output, and have a delay of
|
||||
25 ps to do so, we subtract 25 ps from the 100 ps delay of a feedback
|
||||
to get the part that should be marked on the crossbar. -->
|
||||
<complete name="crossbar" input="clb.I fle[9:0].out" output="fle[9:0].in" circuit_model_name="mux_tree_like">
|
||||
<delay_constant max="95e-12" in_port="clb.I" out_port="fle[9:0].in" />
|
||||
<delay_constant max="75e-12" in_port="fle[9:0].out" out_port="fle[9:0].in" />
|
||||
</complete>
|
||||
<complete name="clks" input="clb.clk" output="fle[9:0].clk">
|
||||
</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[9:0].out[0:0]" output="clb.O[9:0]"/>
|
||||
<direct name="clbouts2" input="fle[9:0].out[1:1]" output="clb.O[19:10]"/>
|
||||
|
||||
<!-- Carry chain links -->
|
||||
<direct name="carry_in" input="clb.cin" output="fle[0:0].cin">
|
||||
<!-- Put all inter-block carry chain delay on this one edge -->
|
||||
<delay_constant max="0.16e-9" in_port="clb.cin" out_port="fle[0:0].cin"/>
|
||||
<pack_pattern name="chain" in_port="clb.cin" out_port="fle[0:0].cin"/>
|
||||
</direct>
|
||||
<direct name="carry_out" input="fle[9:9].cout" output="clb.cout">
|
||||
<pack_pattern name="chain" in_port="fle[9:9].cout" out_port="clb.cout"/>
|
||||
</direct>
|
||||
<direct name="carry_link" input="fle[8:0].cout" output="fle[9:1].cin">
|
||||
<pack_pattern name="chain" in_port="fle[8:0].cout" out_port="fle[9:1].cin"/>
|
||||
</direct>
|
||||
</interconnect>
|
||||
|
||||
<fc default_in_type="frac" default_in_val="0.15" default_out_type="frac" default_out_val="0.10">
|
||||
<pin name="cin" fc_type="frac" fc_val="0"/>
|
||||
<pin name="cout" fc_type="frac" fc_val="0"/>
|
||||
</fc>
|
||||
|
||||
<pinlocations pattern="spread"/>
|
||||
<gridlocations>
|
||||
<loc type="fill" priority="1"/>
|
||||
</gridlocations>
|
||||
</pb_type>
|
||||
<!-- Define general purpose logic block (CLB) ends -->
|
||||
</complexblocklist>
|
||||
<power>
|
||||
<local_interconnect C_wire="2.5e-10"/>
|
||||
<mux_transistor_size mux_transistor_size="3"/>
|
||||
<FF_size FF_size="4"/>
|
||||
<LUT_transistor_size LUT_transistor_size="4"/>
|
||||
</power>
|
||||
<clocks>
|
||||
<clock buffer_size="auto" C_wire="2.5e-10"/>
|
||||
</clocks>
|
||||
</architecture>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,67 +0,0 @@
|
|||
rst 0.001 0.206600
|
||||
clk 0.486400 0.198400
|
||||
data_in 0.5 0.2
|
||||
int_reg[0] 0.257400 0.190800
|
||||
int_reg[1] 0.202800 0.149200
|
||||
int_reg[2] 0.160800 0.115200
|
||||
int_reg[3] 0.130400 0.090800
|
||||
int_reg[4] 0.106200 0.072000
|
||||
int_reg[5] 0.085800 0.056400
|
||||
int_reg[6] 0.070200 0.048000
|
||||
int_reg[7] 0.055800 0.039200
|
||||
int_reg[8] 0.043600 0.031600
|
||||
int_reg[9] 0.033400 0.023200
|
||||
int_reg[10] 0.026000 0.016800
|
||||
int_reg[11] 0.021400 0.014800
|
||||
int_reg[12] 0.016400 0.010000
|
||||
int_reg[13] 0.013600 0.007600
|
||||
int_reg[14] 0.011800 0.006400
|
||||
int_reg[15] 0.010200 0.005600
|
||||
int_reg[16] 0.008400 0.004800
|
||||
int_reg[17] 0.006800 0.004400
|
||||
int_reg[18] 0.005200 0.004000
|
||||
int_reg[19] 0.003600 0.002800
|
||||
int_reg[20] 0.002400 0.002000
|
||||
int_reg[21] 0.001400 0.000800
|
||||
int_reg[22] 0.001000 0.000400
|
||||
int_reg[23] 0.000800 0.000400
|
||||
int_reg[24] 0.000600 0.000400
|
||||
int_reg[25] 0.000400 0.000400
|
||||
int_reg[26] 0.000200 0.000400
|
||||
int_reg[27] 0.000000 0.000000
|
||||
int_reg[28] 0.000000 0.000000
|
||||
int_reg[29] 0.000000 0.000000
|
||||
int_reg[30] 0.000000 0.000000
|
||||
data_out 0.000000 0.000000
|
||||
n64 0.021400 0.003732
|
||||
n69 0.016400 0.004289
|
||||
n74 0.013600 0.004355
|
||||
n79 0.011800 0.004449
|
||||
n84 0.010200 0.004579
|
||||
n89 0.008400 0.004751
|
||||
n94 0.006800 0.004964
|
||||
n99 0.005200 0.005218
|
||||
n104 0.003600 0.005473
|
||||
n109 0.002400 0.005561
|
||||
n114 0.001400 0.005648
|
||||
n119 0.001000 0.005609
|
||||
n124 0.000800 0.005610
|
||||
n129 0.000600 0.005652
|
||||
n134 0.000400 0.005695
|
||||
n139 0.000200 0.005737
|
||||
n144 0.000000 0.005779
|
||||
n149 0.000000 0.005738
|
||||
n154 0.000000 0.005738
|
||||
n159 0.000000 0.005738
|
||||
n164 0.000000 0.005738
|
||||
n9 0.257400 0.049974
|
||||
n14 0.202800 0.087932
|
||||
n19 0.160800 0.092067
|
||||
n24 0.130400 0.094679
|
||||
n29 0.106200 0.096468
|
||||
n34 0.085800 0.097926
|
||||
n39 0.070200 0.099152
|
||||
n44 0.055800 0.000744
|
||||
n49 0.043600 0.002005
|
||||
n54 0.033400 0.003037
|
||||
n59 0.026000 0.003481
|
|
@ -1,103 +0,0 @@
|
|||
# Benchmark "fifo_1bit" written by ABC on Wed Dec 12 14:34:26 2018
|
||||
.model fifo_1bit
|
||||
.inputs rst clk data_in
|
||||
.outputs data_out
|
||||
|
||||
.latch n9 int_reg[0] re clk 0
|
||||
.latch n14 int_reg[1] re clk 0
|
||||
.latch n19 int_reg[2] re clk 0
|
||||
.latch n24 int_reg[3] re clk 0
|
||||
.latch n29 int_reg[4] re clk 0
|
||||
.latch n34 int_reg[5] re clk 0
|
||||
.latch n39 int_reg[6] re clk 0
|
||||
.latch n44 int_reg[7] re clk 0
|
||||
.latch n49 int_reg[8] re clk 0
|
||||
.latch n54 int_reg[9] re clk 0
|
||||
.latch n59 int_reg[10] re clk 0
|
||||
.latch n64 int_reg[11] re clk 0
|
||||
.latch n69 int_reg[12] re clk 0
|
||||
.latch n74 int_reg[13] re clk 0
|
||||
.latch n79 int_reg[14] re clk 0
|
||||
.latch n84 int_reg[15] re clk 0
|
||||
.latch n89 int_reg[16] re clk 0
|
||||
.latch n94 int_reg[17] re clk 0
|
||||
.latch n99 int_reg[18] re clk 0
|
||||
.latch n104 int_reg[19] re clk 0
|
||||
.latch n109 int_reg[20] re clk 0
|
||||
.latch n114 int_reg[21] re clk 0
|
||||
.latch n119 int_reg[22] re clk 0
|
||||
.latch n124 int_reg[23] re clk 0
|
||||
.latch n129 int_reg[24] re clk 0
|
||||
.latch n134 int_reg[25] re clk 0
|
||||
.latch n139 int_reg[26] re clk 0
|
||||
.latch n144 int_reg[27] re clk 0
|
||||
.latch n149 int_reg[28] re clk 0
|
||||
.latch n154 int_reg[29] re clk 0
|
||||
.latch n159 int_reg[30] re clk 0
|
||||
.latch n164 data_out re clk 0
|
||||
|
||||
.names int_reg[10] rst n64
|
||||
10 1
|
||||
.names int_reg[11] rst n69
|
||||
10 1
|
||||
.names int_reg[12] rst n74
|
||||
10 1
|
||||
.names int_reg[13] rst n79
|
||||
10 1
|
||||
.names int_reg[14] rst n84
|
||||
10 1
|
||||
.names int_reg[15] rst n89
|
||||
10 1
|
||||
.names int_reg[16] rst n94
|
||||
10 1
|
||||
.names int_reg[17] rst n99
|
||||
10 1
|
||||
.names int_reg[18] rst n104
|
||||
10 1
|
||||
.names int_reg[19] rst n109
|
||||
10 1
|
||||
.names int_reg[20] rst n114
|
||||
10 1
|
||||
.names int_reg[21] rst n119
|
||||
10 1
|
||||
.names int_reg[22] rst n124
|
||||
10 1
|
||||
.names int_reg[23] rst n129
|
||||
10 1
|
||||
.names int_reg[24] rst n134
|
||||
10 1
|
||||
.names int_reg[25] rst n139
|
||||
10 1
|
||||
.names int_reg[26] rst n144
|
||||
10 1
|
||||
.names int_reg[27] rst n149
|
||||
10 1
|
||||
.names int_reg[28] rst n154
|
||||
10 1
|
||||
.names int_reg[29] rst n159
|
||||
10 1
|
||||
.names int_reg[30] rst n164
|
||||
10 1
|
||||
.names data_in rst n9
|
||||
10 1
|
||||
.names int_reg[0] rst n14
|
||||
10 1
|
||||
.names int_reg[1] rst n19
|
||||
10 1
|
||||
.names int_reg[2] rst n24
|
||||
10 1
|
||||
.names int_reg[3] rst n29
|
||||
10 1
|
||||
.names int_reg[4] rst n34
|
||||
10 1
|
||||
.names int_reg[5] rst n39
|
||||
10 1
|
||||
.names int_reg[6] rst n44
|
||||
10 1
|
||||
.names int_reg[7] rst n49
|
||||
10 1
|
||||
.names int_reg[8] rst n54
|
||||
10 1
|
||||
.names int_reg[9] rst n59
|
||||
10 1
|
||||
.end
|
|
@ -1,32 +0,0 @@
|
|||
///////////////////////////////
|
||||
// //
|
||||
// fifo_1bit benchmark //
|
||||
// //
|
||||
///////////////////////////////
|
||||
|
||||
module fifo_1bit(
|
||||
rst,
|
||||
clk,
|
||||
data_in,
|
||||
data_out );
|
||||
|
||||
input rst;
|
||||
input clk;
|
||||
input data_in;
|
||||
output data_out;
|
||||
|
||||
reg[31:0] int_reg;
|
||||
|
||||
assign data_out = int_reg[31];
|
||||
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
int_reg <= 32'h00;
|
||||
end
|
||||
else begin
|
||||
int_reg[0] <= data_in;
|
||||
int_reg[32:1] = int_reg[31:0];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,19 +0,0 @@
|
|||
#read design
|
||||
read_verilog -nolatches ../vpr7_x2p/vpr/Circuits/fifo_1bit.v
|
||||
|
||||
# synth
|
||||
hierarchy -top fifo_1bit
|
||||
proc
|
||||
|
||||
# Tech map
|
||||
techmap -D NO_LUT -map ./techlibs/common/adff2dff.v
|
||||
synth -top fifo_1bit -flatten
|
||||
clean
|
||||
|
||||
abc -lut 6
|
||||
|
||||
synth -run check
|
||||
|
||||
opt_clean -purge
|
||||
write_blif ../vpr7_x2p/vpr/Circuits/fifo_1bit.blif
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
rst 0.001 0.2
|
||||
clk 0.506200 0.198800
|
||||
a_0 0.507000 0.197200
|
||||
a_1 0.502800 0.201000
|
||||
a_2 0.498400 0.196600
|
||||
a_3 0.510600 0.196600
|
||||
a_4 0.514000 0.208000
|
||||
a_5 0.517000 0.198400
|
||||
a_6 0.491200 0.201400
|
||||
a_7 0.516000 0.196400
|
||||
b_0 0.502800 0.209400
|
||||
b_1 0.490800 0.193600
|
||||
b_2 0.508000 0.194200
|
||||
b_3 0.464000 0.200600
|
||||
b_4 0.492200 0.204200
|
||||
b_5 0.505200 0.188600
|
||||
b_6 0.496400 0.193400
|
||||
b_7 0.513600 0.193000
|
||||
cin 0.499400 0.208200
|
||||
reg0_a[0] 0.238400 0.176800
|
||||
reg0_a[1] 0.246200 0.176000
|
||||
reg0_a[2] 0.225800 0.172000
|
||||
reg0_a[3] 0.233600 0.175200
|
||||
reg0_a[4] 0.241200 0.174400
|
||||
reg0_a[5] 0.241400 0.170000
|
||||
reg0_a[6] 0.236200 0.171200
|
||||
reg0_a[7] 0.244800 0.175200
|
||||
reg1_a[0] 0.185400 0.133600
|
||||
reg1_a[1] 0.194400 0.138400
|
||||
reg1_a[2] 0.177200 0.139600
|
||||
reg1_a[3] 0.183600 0.137600
|
||||
reg1_a[4] 0.191200 0.140800
|
||||
reg1_a[5] 0.191800 0.132000
|
||||
reg1_a[6] 0.189200 0.137600
|
||||
reg1_a[7] 0.192800 0.140800
|
||||
reg2_a[0] 0.148600 0.108000
|
||||
reg2_a[1] 0.154800 0.113200
|
||||
reg2_a[2] 0.138600 0.111600
|
||||
reg2_a[3] 0.145400 0.110800
|
||||
reg2_a[4] 0.149200 0.113200
|
||||
reg2_a[5] 0.153200 0.108800
|
||||
reg2_a[6] 0.151600 0.111600
|
||||
reg2_a[7] 0.152200 0.116000
|
||||
reg0_b[0] 0.236800 0.178800
|
||||
reg0_b[1] 0.233800 0.163200
|
||||
reg0_b[2] 0.243600 0.167600
|
||||
reg0_b[3] 0.215600 0.173200
|
||||
reg0_b[4] 0.226400 0.169200
|
||||
reg0_b[5] 0.240000 0.174800
|
||||
reg0_b[6] 0.224800 0.177600
|
||||
reg0_b[7] 0.245000 0.173200
|
||||
reg1_b[0] 0.188000 0.140800
|
||||
reg1_b[1] 0.185800 0.130800
|
||||
reg1_b[2] 0.193800 0.135200
|
||||
reg1_b[3] 0.165600 0.134000
|
||||
reg1_b[4] 0.180600 0.134400
|
||||
reg1_b[5] 0.188400 0.139600
|
||||
reg1_b[6] 0.174200 0.134400
|
||||
reg1_b[7] 0.193400 0.136000
|
||||
reg2_b[0] 0.149200 0.115200
|
||||
reg2_b[1] 0.145600 0.103200
|
||||
reg2_b[2] 0.151600 0.107200
|
||||
reg2_b[3] 0.128000 0.102800
|
||||
reg2_b[4] 0.142200 0.108400
|
||||
reg2_b[5] 0.147400 0.110400
|
||||
reg2_b[6] 0.138400 0.106800
|
||||
reg2_b[7] 0.152600 0.105600
|
||||
reg0_cin 0.224800 0.178400
|
||||
reg1_cin 0.174400 0.140000
|
||||
reg2_cin 0.137400 0.109200
|
||||
cout 0.119200 0.105600
|
||||
sumout_0 0.111400 0.121200
|
||||
sumout_1 0.115800 0.124000
|
||||
sumout_2 0.115600 0.126000
|
||||
sumout_3 0.115200 0.128000
|
||||
sumout_4 0.115800 0.128000
|
||||
sumout_5 0.107800 0.119200
|
||||
sumout_6 0.117000 0.129200
|
||||
sumout_7 0.115200 0.132400
|
||||
n340 0.117000 0.060696
|
||||
n212_1 0.849800 0.107643
|
||||
n213 0.062800 0.025828
|
||||
n214 0.850000 0.007413
|
||||
n215 0.138200 0.024548
|
||||
n216 0.076600 0.000554
|
||||
n344 0.115200 0.059006
|
||||
n218 0.852400 0.025645
|
||||
n57 0.238400 0.039829
|
||||
n62 0.246200 0.040694
|
||||
n67 0.225800 0.040876
|
||||
n72 0.233600 0.039321
|
||||
n77 0.241200 0.039861
|
||||
n82 0.241400 0.038668
|
||||
n87 0.236200 0.042234
|
||||
n92 0.244800 0.038625
|
||||
n97 0.185400 0.078023
|
||||
n102 0.194400 0.076567
|
||||
n107 0.177200 0.079580
|
||||
n112 0.183600 0.078646
|
||||
n117 0.191200 0.077219
|
||||
n122 0.191800 0.076600
|
||||
n127 0.189200 0.077659
|
||||
n132 0.192800 0.076702
|
||||
n137 0.148600 0.081354
|
||||
n142 0.154800 0.080450
|
||||
n147 0.138600 0.083670
|
||||
n152 0.145400 0.082242
|
||||
n157 0.149200 0.081352
|
||||
n162 0.153200 0.080003
|
||||
n167 0.151600 0.081252
|
||||
n172 0.152200 0.081070
|
||||
n177 0.236800 0.041425
|
||||
n182 0.233800 0.041591
|
||||
n187 0.243600 0.039443
|
||||
n192 0.215600 0.045786
|
||||
n197 0.226400 0.042352
|
||||
n202 0.240000 0.039313
|
||||
n207 0.224800 0.040852
|
||||
n212 0.245000 0.038637
|
||||
n217 0.188000 0.078569
|
||||
n222 0.185800 0.077003
|
||||
n227 0.193800 0.075904
|
||||
n232 0.165600 0.081545
|
||||
n237 0.180600 0.079096
|
||||
n242 0.188400 0.077479
|
||||
n247 0.174200 0.080515
|
||||
n252 0.193400 0.076404
|
||||
n257 0.149200 0.081918
|
||||
n262 0.145600 0.080884
|
||||
n267 0.151600 0.080104
|
||||
n272 0.128000 0.084941
|
||||
n277 0.142200 0.082317
|
||||
n282 0.147400 0.081677
|
||||
n287 0.138400 0.083456
|
||||
n292 0.152600 0.080287
|
||||
n297 0.224800 0.041763
|
||||
n302 0.174400 0.080624
|
||||
n307 0.137400 0.084229
|
||||
n312 0.119200 0.071604
|
||||
n316 0.111400 0.060180
|
||||
n320 0.115800 0.033704
|
||||
n324 0.115600 0.059988
|
||||
n328 0.115200 0.062886
|
||||
n275 0.853600 0.140779
|
||||
n336 0.107800 0.062509
|
||||
n332 0.115800 0.006673
|
|
@ -1,264 +0,0 @@
|
|||
# Benchmark "pip_add" written by ABC on Fri Dec 7 14:18:10 2018
|
||||
.model pip_add
|
||||
.inputs rst clk a_0 a_1 a_2 a_3 a_4 a_5 a_6 a_7 b_0 b_1 b_2 b_3 b_4 b_5 b_6 \
|
||||
b_7 cin
|
||||
.outputs sumout_0 sumout_1 sumout_2 sumout_3 sumout_4 sumout_5 sumout_6 \
|
||||
sumout_7 cout
|
||||
|
||||
.latch n57 reg0_a[0] re clk 0
|
||||
.latch n62 reg0_a[1] re clk 0
|
||||
.latch n67 reg0_a[2] re clk 0
|
||||
.latch n72 reg0_a[3] re clk 0
|
||||
.latch n77 reg0_a[4] re clk 0
|
||||
.latch n82 reg0_a[5] re clk 0
|
||||
.latch n87 reg0_a[6] re clk 0
|
||||
.latch n92 reg0_a[7] re clk 0
|
||||
.latch n97 reg1_a[0] re clk 0
|
||||
.latch n102 reg1_a[1] re clk 0
|
||||
.latch n107 reg1_a[2] re clk 0
|
||||
.latch n112 reg1_a[3] re clk 0
|
||||
.latch n117 reg1_a[4] re clk 0
|
||||
.latch n122 reg1_a[5] re clk 0
|
||||
.latch n127 reg1_a[6] re clk 0
|
||||
.latch n132 reg1_a[7] re clk 0
|
||||
.latch n137 reg2_a[0] re clk 0
|
||||
.latch n142 reg2_a[1] re clk 0
|
||||
.latch n147 reg2_a[2] re clk 0
|
||||
.latch n152 reg2_a[3] re clk 0
|
||||
.latch n157 reg2_a[4] re clk 0
|
||||
.latch n162 reg2_a[5] re clk 0
|
||||
.latch n167 reg2_a[6] re clk 0
|
||||
.latch n172 reg2_a[7] re clk 0
|
||||
.latch n177 reg0_b[0] re clk 0
|
||||
.latch n182 reg0_b[1] re clk 0
|
||||
.latch n187 reg0_b[2] re clk 0
|
||||
.latch n192 reg0_b[3] re clk 0
|
||||
.latch n197 reg0_b[4] re clk 0
|
||||
.latch n202 reg0_b[5] re clk 0
|
||||
.latch n207 reg0_b[6] re clk 0
|
||||
.latch n212 reg0_b[7] re clk 0
|
||||
.latch n217 reg1_b[0] re clk 0
|
||||
.latch n222 reg1_b[1] re clk 0
|
||||
.latch n227 reg1_b[2] re clk 0
|
||||
.latch n232 reg1_b[3] re clk 0
|
||||
.latch n237 reg1_b[4] re clk 0
|
||||
.latch n242 reg1_b[5] re clk 0
|
||||
.latch n247 reg1_b[6] re clk 0
|
||||
.latch n252 reg1_b[7] re clk 0
|
||||
.latch n257 reg2_b[0] re clk 0
|
||||
.latch n262 reg2_b[1] re clk 0
|
||||
.latch n267 reg2_b[2] re clk 0
|
||||
.latch n272 reg2_b[3] re clk 0
|
||||
.latch n277 reg2_b[4] re clk 0
|
||||
.latch n282 reg2_b[5] re clk 0
|
||||
.latch n287 reg2_b[6] re clk 0
|
||||
.latch n292 reg2_b[7] re clk 0
|
||||
.latch n297 reg0_cin re clk 0
|
||||
.latch n302 reg1_cin re clk 0
|
||||
.latch n307 reg2_cin re clk 0
|
||||
.latch n312 cout re clk 0
|
||||
.latch n316 sumout_0 re clk 0
|
||||
.latch n320 sumout_1 re clk 0
|
||||
.latch n324 sumout_2 re clk 0
|
||||
.latch n328 sumout_3 re clk 0
|
||||
.latch n332 sumout_4 re clk 0
|
||||
.latch n336 sumout_5 re clk 0
|
||||
.latch n340 sumout_6 re clk 0
|
||||
.latch n344 sumout_7 re clk 0
|
||||
|
||||
.names reg2_a[6] reg2_b[6] n212_1 rst n340
|
||||
0000 1
|
||||
0110 1
|
||||
1010 1
|
||||
1100 1
|
||||
.names n216 n213 reg2_a[5] reg2_b[5] n212_1
|
||||
000- 1
|
||||
00-0 1
|
||||
--00 1
|
||||
.names n215 reg2_a[2] reg2_b[2] reg2_a[3] reg2_b[3] n214 n213
|
||||
1111-- 1
|
||||
111-1- 1
|
||||
11-1-0 1
|
||||
11--10 1
|
||||
1-11-0 1
|
||||
1-1-10 1
|
||||
1--11- 1
|
||||
.names reg2_a[1] reg2_cin reg2_a[0] reg2_b[0] reg2_b[1] n214
|
||||
000-- 1
|
||||
00-0- 1
|
||||
0-00- 1
|
||||
0---0 1
|
||||
-00-0 1
|
||||
-0-00 1
|
||||
--000 1
|
||||
.names reg2_a[4] reg2_b[4] n215
|
||||
01 1
|
||||
10 1
|
||||
.names reg2_a[4] reg2_b[4] n216
|
||||
11 1
|
||||
.names reg2_a[7] reg2_b[7] n218 rst n344
|
||||
0000 1
|
||||
0110 1
|
||||
1010 1
|
||||
1100 1
|
||||
.names n213 n216 reg2_a[6] reg2_a[5] reg2_b[5] reg2_b[6] n218
|
||||
0000-- 1
|
||||
000-0- 1
|
||||
00-0-0 1
|
||||
00--00 1
|
||||
--000- 1
|
||||
--0--0 1
|
||||
---000 1
|
||||
.names a_0 rst n57
|
||||
10 1
|
||||
.names a_1 rst n62
|
||||
10 1
|
||||
.names a_2 rst n67
|
||||
10 1
|
||||
.names a_3 rst n72
|
||||
10 1
|
||||
.names a_4 rst n77
|
||||
10 1
|
||||
.names a_5 rst n82
|
||||
10 1
|
||||
.names a_6 rst n87
|
||||
10 1
|
||||
.names a_7 rst n92
|
||||
10 1
|
||||
.names reg0_a[0] rst n97
|
||||
10 1
|
||||
.names reg0_a[1] rst n102
|
||||
10 1
|
||||
.names reg0_a[2] rst n107
|
||||
10 1
|
||||
.names reg0_a[3] rst n112
|
||||
10 1
|
||||
.names reg0_a[4] rst n117
|
||||
10 1
|
||||
.names reg0_a[5] rst n122
|
||||
10 1
|
||||
.names reg0_a[6] rst n127
|
||||
10 1
|
||||
.names reg0_a[7] rst n132
|
||||
10 1
|
||||
.names reg1_a[0] rst n137
|
||||
10 1
|
||||
.names reg1_a[1] rst n142
|
||||
10 1
|
||||
.names reg1_a[2] rst n147
|
||||
10 1
|
||||
.names reg1_a[3] rst n152
|
||||
10 1
|
||||
.names reg1_a[4] rst n157
|
||||
10 1
|
||||
.names reg1_a[5] rst n162
|
||||
10 1
|
||||
.names reg1_a[6] rst n167
|
||||
10 1
|
||||
.names reg1_a[7] rst n172
|
||||
10 1
|
||||
.names b_0 rst n177
|
||||
10 1
|
||||
.names b_1 rst n182
|
||||
10 1
|
||||
.names b_2 rst n187
|
||||
10 1
|
||||
.names b_3 rst n192
|
||||
10 1
|
||||
.names b_4 rst n197
|
||||
10 1
|
||||
.names b_5 rst n202
|
||||
10 1
|
||||
.names b_6 rst n207
|
||||
10 1
|
||||
.names b_7 rst n212
|
||||
10 1
|
||||
.names reg0_b[0] rst n217
|
||||
10 1
|
||||
.names reg0_b[1] rst n222
|
||||
10 1
|
||||
.names reg0_b[2] rst n227
|
||||
10 1
|
||||
.names reg0_b[3] rst n232
|
||||
10 1
|
||||
.names reg0_b[4] rst n237
|
||||
10 1
|
||||
.names reg0_b[5] rst n242
|
||||
10 1
|
||||
.names reg0_b[6] rst n247
|
||||
10 1
|
||||
.names reg0_b[7] rst n252
|
||||
10 1
|
||||
.names reg1_b[0] rst n257
|
||||
10 1
|
||||
.names reg1_b[1] rst n262
|
||||
10 1
|
||||
.names reg1_b[2] rst n267
|
||||
10 1
|
||||
.names reg1_b[3] rst n272
|
||||
10 1
|
||||
.names reg1_b[4] rst n277
|
||||
10 1
|
||||
.names reg1_b[5] rst n282
|
||||
10 1
|
||||
.names reg1_b[6] rst n287
|
||||
10 1
|
||||
.names reg1_b[7] rst n292
|
||||
10 1
|
||||
.names cin rst n297
|
||||
10 1
|
||||
.names reg0_cin rst n302
|
||||
10 1
|
||||
.names reg1_cin rst n307
|
||||
10 1
|
||||
.names rst reg2_a[7] reg2_b[7] n218 n312
|
||||
011- 1
|
||||
01-0 1
|
||||
0-10 1
|
||||
.names reg2_cin reg2_a[0] reg2_b[0] rst n316
|
||||
0010 1
|
||||
0100 1
|
||||
1000 1
|
||||
1110 1
|
||||
.names reg2_a[1] reg2_b[1] rst reg2_cin reg2_a[0] reg2_b[0] n320
|
||||
00011- 1
|
||||
0001-1 1
|
||||
000-11 1
|
||||
01000- 1
|
||||
0100-0 1
|
||||
010-00 1
|
||||
10000- 1
|
||||
1000-0 1
|
||||
100-00 1
|
||||
11011- 1
|
||||
1101-1 1
|
||||
110-11 1
|
||||
.names reg2_a[2] reg2_b[2] n214 rst n324
|
||||
0000 1
|
||||
0110 1
|
||||
1010 1
|
||||
1100 1
|
||||
.names reg2_a[3] reg2_b[3] n275 rst n328
|
||||
0000 1
|
||||
0110 1
|
||||
1010 1
|
||||
1100 1
|
||||
.names reg2_a[2] reg2_b[2] n214 n275
|
||||
00- 1
|
||||
0-1 1
|
||||
-01 1
|
||||
.names reg2_a[5] reg2_b[5] rst n216 n213 n336
|
||||
0001- 1
|
||||
000-1 1
|
||||
01000 1
|
||||
10000 1
|
||||
1101- 1
|
||||
110-1 1
|
||||
.names n215 rst reg2_a[3] reg2_b[3] n275 n332
|
||||
0011- 1
|
||||
001-0 1
|
||||
00-10 1
|
||||
1000- 1
|
||||
100-1 1
|
||||
10-01 1
|
||||
.end
|
|
@ -1,142 +0,0 @@
|
|||
////////////////////////////////////////
|
||||
// //
|
||||
// Pipelined adder benchmark //
|
||||
// //
|
||||
////////////////////////////////////////
|
||||
|
||||
module pip_add(
|
||||
rst,
|
||||
clk,
|
||||
a_0,
|
||||
a_1,
|
||||
a_2,
|
||||
a_3,
|
||||
a_4,
|
||||
a_5,
|
||||
a_6,
|
||||
a_7,
|
||||
b_0,
|
||||
b_1,
|
||||
b_2,
|
||||
b_3,
|
||||
b_4,
|
||||
b_5,
|
||||
b_6,
|
||||
b_7,
|
||||
cin,
|
||||
sumout_0,
|
||||
sumout_1,
|
||||
sumout_2,
|
||||
sumout_3,
|
||||
sumout_4,
|
||||
sumout_5,
|
||||
sumout_6,
|
||||
sumout_7,
|
||||
cout);
|
||||
|
||||
input rst;
|
||||
input clk;
|
||||
input a_0;
|
||||
input a_1;
|
||||
input a_2;
|
||||
input a_3;
|
||||
input a_4;
|
||||
input a_5;
|
||||
input a_6;
|
||||
input a_7;
|
||||
input b_0;
|
||||
input b_1;
|
||||
input b_2;
|
||||
input b_3;
|
||||
input b_4;
|
||||
input b_5;
|
||||
input b_6;
|
||||
input b_7;
|
||||
input cin;
|
||||
output sumout_0;
|
||||
output sumout_1;
|
||||
output sumout_2;
|
||||
output sumout_3;
|
||||
output sumout_4;
|
||||
output sumout_5;
|
||||
output sumout_6;
|
||||
output sumout_7;
|
||||
output reg cout;
|
||||
|
||||
reg[7:0] reg0_a;
|
||||
reg[7:0] reg0_b;
|
||||
reg[7:0] reg1_a;
|
||||
reg[7:0] reg1_b;
|
||||
reg[7:0] reg2_a;
|
||||
reg[7:0] reg2_b;
|
||||
reg reg0_cin;
|
||||
reg reg1_cin;
|
||||
reg reg2_cin;
|
||||
wire[8:0] int_sum;
|
||||
wire int_cout;
|
||||
wire[7:0] a;
|
||||
wire[7:0] b;
|
||||
reg[7:0] sumout;
|
||||
|
||||
assign a = {a_7, a_6, a_5, a_4, a_3, a_2, a_1, a_0};
|
||||
assign b = {b_7, b_6, b_5, b_4, b_3, b_2, b_1, b_0};
|
||||
assign int_sum = reg2_a + reg2_b + reg2_cin;
|
||||
assign int_cout = int_sum[8] || 1'b0;
|
||||
assign sumout_0 = sumout[0];
|
||||
assign sumout_1 = sumout[1];
|
||||
assign sumout_2 = sumout[2];
|
||||
assign sumout_3 = sumout[3];
|
||||
assign sumout_4 = sumout[4];
|
||||
assign sumout_5 = sumout[5];
|
||||
assign sumout_6 = sumout[6];
|
||||
assign sumout_7 = sumout[7];
|
||||
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
reg0_a <= 8'h00;
|
||||
reg0_b <= 8'h00;
|
||||
reg0_cin <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
reg0_a <= a;
|
||||
reg0_b <= b;
|
||||
reg0_cin <= cin;
|
||||
end
|
||||
end
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
reg1_a <= 8'h00;
|
||||
reg1_b <= 8'h00;
|
||||
reg1_cin <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
reg1_a <= reg0_a;
|
||||
reg1_b <= reg0_b;
|
||||
reg1_cin <= reg0_cin;
|
||||
end
|
||||
end
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
reg2_a <= 8'h00;
|
||||
reg2_b <= 8'h00;
|
||||
reg2_cin <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
reg2_a <= reg1_a;
|
||||
reg2_b <= reg1_b;
|
||||
reg2_cin <= reg1_cin;
|
||||
end
|
||||
end
|
||||
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
sumout <= 8'h00;
|
||||
cout <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
sumout <= int_sum[7:0];
|
||||
cout <= int_cout;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,42 +0,0 @@
|
|||
G0 0.515200 0.186400
|
||||
G1 0.514800 0.193600
|
||||
G2 0.486200 0.195800
|
||||
clk 0.490200 0.198400
|
||||
G10 0.267600 0.534800
|
||||
G11 0.222000 0.243600
|
||||
G12 0.166600 0.110400
|
||||
G13 0.043600 0.050400
|
||||
G14 0.181000 0.214400
|
||||
G15 0.047800 0.016000
|
||||
G16 0.012800 0.018400
|
||||
G17 0.880200 0.057600
|
||||
G18 0.925000 0.038400
|
||||
G19 0.046400 0.081200
|
||||
G20 0.033600 0.066400
|
||||
G21 0.044800 0.043200
|
||||
G22 0.193800 0.272200
|
||||
G23 0.212000 0.292800
|
||||
n21 0.267600 0.136672
|
||||
n26 0.222000 0.010724
|
||||
n31 0.166600 0.005271
|
||||
n36 0.043600 0.088128
|
||||
n41 0.181000 0.010995
|
||||
n57 0.679400 0.039608
|
||||
n46 0.047800 0.000597
|
||||
n59 0.941600 0.000356
|
||||
n51 0.012800 0.001040
|
||||
n56 0.880200 0.082925
|
||||
n61 0.925000 0.075430
|
||||
n66_1 0.046400 0.002953
|
||||
n64 0.047600 0.072462
|
||||
n71 0.033600 0.005766
|
||||
n66 0.099400 0.025568
|
||||
n76 0.044800 0.001108
|
||||
n81 0.193800 0.038591
|
||||
n86 0.212000 0.041397
|
||||
G117 0.924800 0.035520
|
||||
G132 0.033600 0.002231
|
||||
G66 0.012800 0.000236
|
||||
G118 0.046400 0.003768
|
||||
G133 0.044800 0.001935
|
||||
G67 0.880000 0.050700
|
|
@ -1,104 +0,0 @@
|
|||
# Benchmark "s298.bench" written by ABC on Thu Jul 26 11:12:10 2018
|
||||
.model s298.bench
|
||||
.inputs G0 G1 G2 clk
|
||||
.outputs G117 G132 G66 G118 G133 G67
|
||||
|
||||
.latch n21 G10 re clk 0
|
||||
.latch n26 G11 re clk 0
|
||||
.latch n31 G12 re clk 0
|
||||
.latch n36 G13 re clk 0
|
||||
.latch n41 G14 re clk 0
|
||||
.latch n46 G15 re clk 0
|
||||
.latch n51 G16 re clk 0
|
||||
.latch n56 G17 re clk 0
|
||||
.latch n61 G18 re clk 0
|
||||
.latch n66_1 G19 re clk 0
|
||||
.latch n71 G20 re clk 0
|
||||
.latch n76 G21 re clk 0
|
||||
.latch n81 G22 re clk 0
|
||||
.latch n86 G23 re clk 0
|
||||
|
||||
.names G0 G10 n21
|
||||
00 1
|
||||
.names G0 G10 G11 G12 G13 n26
|
||||
001-- 1
|
||||
0101- 1
|
||||
010-0 1
|
||||
.names G0 G10 G11 G12 n31
|
||||
00-1 1
|
||||
0110 1
|
||||
0-01 1
|
||||
.names G0 G10 G11 G12 G13 n36
|
||||
00--1 1
|
||||
01110 1
|
||||
0-011 1
|
||||
0-101 1
|
||||
.names G0 G10 G13 G14 G23 n57 n41
|
||||
00-10- 1
|
||||
0110-1 1
|
||||
0-010- 1
|
||||
0--01- 1
|
||||
0--100 1
|
||||
.names G11 G12 n57
|
||||
00 1
|
||||
.names G0 n59 n46
|
||||
00 1
|
||||
.names G11 G12 G13 G14 G15 G22 n59
|
||||
1010-0 1
|
||||
1---0- 1
|
||||
-1--0- 1
|
||||
--0-0- 1
|
||||
---10- 1
|
||||
----00 1
|
||||
.names G12 G13 G14 G16 n59 n51
|
||||
1-111 1
|
||||
-10-1 1
|
||||
-1-11 1
|
||||
.names G11 G12 G13 G14 G17 n59 n56
|
||||
0-00-1 1
|
||||
100--1 1
|
||||
-1-111 1
|
||||
--1111 1
|
||||
.names G11 G12 G13 G14 G18 n59 n61
|
||||
100--1 1
|
||||
-1-111 1
|
||||
--00-1 1
|
||||
--1111 1
|
||||
.names G10 n59 n64 n66_1
|
||||
00- 1
|
||||
-11 1
|
||||
.names G11 G12 G13 G14 G19 n64
|
||||
0001- 1
|
||||
-1-11 1
|
||||
--10- 1
|
||||
--1-1 1
|
||||
.names G10 G12 G13 G20 n59 n66 n71
|
||||
0---0- 1
|
||||
-00-11 1
|
||||
---111 1
|
||||
.names G11 G12 G13 G14 n66
|
||||
100- 0
|
||||
---0 0
|
||||
.names G11 G12 G13 G14 G21 n59 n76
|
||||
1100-1 1
|
||||
-1-111 1
|
||||
--1111 1
|
||||
.names G0 G2 G22 n81
|
||||
001 1
|
||||
010 1
|
||||
.names G0 G1 G23 n86
|
||||
001 1
|
||||
010 1
|
||||
.names G18 G117
|
||||
1 1
|
||||
.names G20 G132
|
||||
1 1
|
||||
.names G16 G66
|
||||
1 1
|
||||
.names G19 G118
|
||||
1 1
|
||||
.names G21 G133
|
||||
1 1
|
||||
.names G17 G67
|
||||
1 1
|
||||
.end
|
|
@ -1,40 +0,0 @@
|
|||
clk 0.511800 0.202800
|
||||
rst 0.00001 0.198000
|
||||
a0 0.465000 0.196200
|
||||
a1 0.476000 0.196200
|
||||
a2 0.480800 0.203200
|
||||
a3 0.523200 0.203400
|
||||
b0 0.502800 0.211200
|
||||
b1 0.479200 0.208400
|
||||
b2 0.495200 0.197000
|
||||
b3 0.521000 0.204800
|
||||
cin 0.490400 0.194600
|
||||
reg_b[3] 0.250800 0.189200
|
||||
reg_cin 0.241600 0.168200
|
||||
cout 0.197600 0.171000
|
||||
sumout0 0.197400 0.197200
|
||||
sumout1 0.195200 0.205800
|
||||
sumout2 0.202000 0.213000
|
||||
sumout3 0.191600 0.207600
|
||||
reg_a[0] 0.229800 0.171000
|
||||
reg_a[1] 0.236000 0.170200
|
||||
reg_a[2] 0.230000 0.174400
|
||||
reg_a[3] 0.258400 0.179800
|
||||
reg_b[0] 0.250600 0.180400
|
||||
reg_b[1] 0.238600 0.177800
|
||||
reg_b[2] 0.248000 0.177400
|
||||
n83 0.250600 0.044471
|
||||
n88 0.238600 0.047498
|
||||
n93 0.248000 0.044135
|
||||
n33 0.250800 0.041399
|
||||
n38 0.241600 0.044556
|
||||
n43 0.197600 0.011311
|
||||
n67 0.767600 0.013393
|
||||
n47 0.197400 0.040388
|
||||
n51 0.195200 0.019975
|
||||
n55 0.202000 0.042318
|
||||
n59 0.191600 0.007901
|
||||
n63 0.229800 0.048269
|
||||
n68 0.236000 0.046714
|
||||
n73 0.230000 0.046748
|
||||
n78 0.258400 0.040977
|
|
@ -1,91 +0,0 @@
|
|||
# Benchmark "sync_4bits_add" written by ABC on Sat Dec 22 05:55:54 2018
|
||||
.model sync_4bits_add
|
||||
.inputs clk rst a0 a1 a2 a3 b0 b1 b2 b3 cin
|
||||
.outputs sumout0 sumout1 sumout2 sumout3 cout
|
||||
|
||||
.latch n33 reg_b[3] re clk 0
|
||||
.latch n38 reg_cin re clk 0
|
||||
.latch n43 cout re clk 0
|
||||
.latch n47 sumout0 re clk 0
|
||||
.latch n51 sumout1 re clk 0
|
||||
.latch n55 sumout2 re clk 0
|
||||
.latch n59 sumout3 re clk 0
|
||||
.latch n63 reg_a[0] re clk 0
|
||||
.latch n68 reg_a[1] re clk 0
|
||||
.latch n73 reg_a[2] re clk 0
|
||||
.latch n78 reg_a[3] re clk 0
|
||||
.latch n83 reg_b[0] re clk 0
|
||||
.latch n88 reg_b[1] re clk 0
|
||||
.latch n93 reg_b[2] re clk 0
|
||||
|
||||
.names b0 rst n83
|
||||
10 1
|
||||
.names b1 rst n88
|
||||
10 1
|
||||
.names b2 rst n93
|
||||
10 1
|
||||
.names b3 rst n33
|
||||
10 1
|
||||
.names cin rst n38
|
||||
10 1
|
||||
.names rst reg_b[2] reg_a[2] reg_b[3] reg_a[3] n67 n43
|
||||
0111-- 1
|
||||
011-1- 1
|
||||
01-1-0 1
|
||||
01--10 1
|
||||
0-11-0 1
|
||||
0-1-10 1
|
||||
0--11- 1
|
||||
.names reg_b[1] reg_cin reg_b[0] reg_a[0] reg_a[1] n67
|
||||
000-- 1
|
||||
00-0- 1
|
||||
0-00- 1
|
||||
0---0 1
|
||||
-00-0 1
|
||||
-0-00 1
|
||||
--000 1
|
||||
.names reg_cin reg_b[0] reg_a[0] rst n47
|
||||
0010 1
|
||||
0100 1
|
||||
1000 1
|
||||
1110 1
|
||||
.names reg_b[1] reg_a[1] rst reg_cin reg_b[0] reg_a[0] n51
|
||||
00011- 1
|
||||
0001-1 1
|
||||
000-11 1
|
||||
01000- 1
|
||||
0100-0 1
|
||||
010-00 1
|
||||
10000- 1
|
||||
1000-0 1
|
||||
100-00 1
|
||||
11011- 1
|
||||
1101-1 1
|
||||
110-11 1
|
||||
.names reg_b[2] reg_a[2] n67 rst n55
|
||||
0000 1
|
||||
0110 1
|
||||
1010 1
|
||||
1100 1
|
||||
.names reg_b[3] reg_a[3] rst reg_b[2] reg_a[2] n67 n59
|
||||
00011- 1
|
||||
0001-0 1
|
||||
000-10 1
|
||||
01000- 1
|
||||
0100-1 1
|
||||
010-01 1
|
||||
10000- 1
|
||||
1000-1 1
|
||||
100-01 1
|
||||
11011- 1
|
||||
1101-0 1
|
||||
110-10 1
|
||||
.names a0 rst n63
|
||||
10 1
|
||||
.names a1 rst n68
|
||||
10 1
|
||||
.names a2 rst n73
|
||||
10 1
|
||||
.names a3 rst n78
|
||||
10 1
|
||||
.end
|
|
@ -1,90 +0,0 @@
|
|||
////////////////////////////////////////
|
||||
// //
|
||||
// Synchronized adder benchmark //
|
||||
// //
|
||||
////////////////////////////////////////
|
||||
|
||||
module sync_4bits_add(
|
||||
clk,
|
||||
rst,
|
||||
a0,
|
||||
a1,
|
||||
a2,
|
||||
a3,
|
||||
b0,
|
||||
b1,
|
||||
b2,
|
||||
b3,
|
||||
cin,
|
||||
sumout0,
|
||||
sumout1,
|
||||
sumout2,
|
||||
sumout3,
|
||||
cout);
|
||||
|
||||
input clk;
|
||||
input rst;
|
||||
input a0;
|
||||
input a1;
|
||||
input a2;
|
||||
input a3;
|
||||
input b0;
|
||||
input b1;
|
||||
input b2;
|
||||
input b3;
|
||||
input cin;
|
||||
output sumout0;
|
||||
output sumout1;
|
||||
output sumout2;
|
||||
output sumout3;
|
||||
output reg cout;
|
||||
|
||||
wire[3:0] a;
|
||||
wire[3:0] b;
|
||||
reg[3:0] sumout;
|
||||
|
||||
reg[3:0] reg_a;
|
||||
reg[3:0] reg_b;
|
||||
reg reg_cin;
|
||||
wire[4:0] int_sum;
|
||||
|
||||
assign a[3] = a3;
|
||||
assign a[2] = a2;
|
||||
assign a[1] = a1;
|
||||
assign a[0] = a0;
|
||||
assign b[3] = b3;
|
||||
assign b[2] = b2;
|
||||
assign b[1] = b1;
|
||||
assign b[0] = b0;
|
||||
assign sumout3 = sumout[3];
|
||||
assign sumout2 = sumout[2];
|
||||
assign sumout1 = sumout[1];
|
||||
assign sumout0 = sumout[0];
|
||||
|
||||
assign int_sum = reg_a + reg_b + reg_cin;
|
||||
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
reg_a <= 4'h0;
|
||||
reg_b <= 4'h0;
|
||||
reg_cin <= 1'h0;
|
||||
end
|
||||
else begin
|
||||
reg_a <= a;
|
||||
reg_b <= b;
|
||||
reg_cin <= cin;
|
||||
end
|
||||
end
|
||||
|
||||
always@(posedge clk or posedge rst) begin
|
||||
if(rst) begin
|
||||
sumout <= 4'h0;
|
||||
cout <= 1'h0;
|
||||
end
|
||||
else begin
|
||||
sumout <= int_sum[3:0];
|
||||
cout <= int_sum[4];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# Please note that a Mac can run the graphics if the X11 library is installed.
|
||||
|
||||
ENABLE_GRAPHICS = true
|
||||
ENABLE_GRAPHICS = false
|
||||
# can be true or false
|
||||
|
||||
export BUILD_TYPE = debug
|
||||
|
@ -23,11 +23,12 @@ OPTIMIZATION_LEVEL_FOR_RELEASE_BUILD = -O3
|
|||
|
||||
CC = $(COMPILER)
|
||||
LIB_DIR = -L.
|
||||
LIB = -lm -lvpr
|
||||
FPGA_SPICE_SRC_DIR = SRC/fpga_spice
|
||||
LIB = -lm -lvpr -lreadline
|
||||
SHELL_LIB = -lm -lvpr_shell -lreadline
|
||||
FPGA_SPICE_SRC_DIR = SRC/fpga_x2p
|
||||
SRC_DIR = SRC
|
||||
OBJ_DIR = OBJ
|
||||
OTHER_DIR = -ISRC/util -ISRC/timing -ISRC/pack -ISRC/place -ISRC/base -ISRC/route -ISRC/power -ISRC/mrfpga -ISRC/fpga_spice/base -ISRC/fpga_spice/spice -ISRC/fpga_spice/verilog -ISRC/fpga_spice/clb_pin_remap -I../libarchfpga -I../printhandler/SRC/TIO_InputOutputHandlers
|
||||
OTHER_DIR = -ISRC/util -ISRC/timing -ISRC/pack -ISRC/place -ISRC/base -ISRC/route -ISRC/power -ISRC/mrfpga -ISRC/fpga_spice -I$(FPGA_SPICE_SRC_DIR)/base -I$(FPGA_SPICE_SRC_DIR)/bitstream -I$(FPGA_SPICE_SRC_DIR)/bitstream -I$(FPGA_SPICE_SRC_DIR)/clb_pin_remap -I$(FPGA_SPICE_SRC_DIR)/spice -I$(FPGA_SPICE_SRC_DIR)/verilog -I$(FPGA_SPICE_SRC_DIR)/router -I../libarchfpga -I../printhandler/SRC/TIO_InputOutputHandlers -I$(FPGA_SPICE_SRC_DIR)/shell
|
||||
|
||||
WARN_FLAGS = -Wall -Wpointer-arith -Wcast-qual -D__USE_FIXED_PROTOTYPES__ -ansi -pedantic -Wshadow -Wcast-align -D_POSIX_SOURCE -Wno-write-strings
|
||||
|
||||
|
@ -41,8 +42,6 @@ UNAME := $(shell uname)
|
|||
# determine build env
|
||||
ifeq ($(UNAME), Darwin)
|
||||
MAC_OS = true
|
||||
# Disable graphic in MacOS
|
||||
ENABLE_GRAPHICS = false
|
||||
else
|
||||
MAC_OS = false
|
||||
endif
|
||||
|
@ -79,6 +78,12 @@ DEP := $(OBJ:.o=.d)
|
|||
$(EXE): $(OBJ) Makefile libvpr.a | notify
|
||||
$(CC) $(FLAGS) OBJ/main.o -o $(EXE) $(LIB_DIR) $(LIB)
|
||||
|
||||
SHELL_EXE = vpr_shell
|
||||
|
||||
# cmd-shell interface main
|
||||
$(SHELL_EXE): $(OBJ) Makefile libvpr_shell.a | notify
|
||||
$(CC) $(FLAGS) OBJ/shell_main.o -o $(SHELL_EXE) $(LIB_DIR) $(SHELL_LIB)
|
||||
|
||||
# if graphics enabled but libx11-dev is not installed, notify the user
|
||||
notify:
|
||||
@ $(PACKAGENOTIFICATION)
|
||||
|
@ -96,6 +101,11 @@ libvpr.a: $(OBJ) Makefile libarchfpga
|
|||
@ ar rcs $@ $(OBJ)
|
||||
@ ar d $@ main.o
|
||||
|
||||
libvpr_shell.a: $(OBJ) Makefile libarchfpga
|
||||
@ cp ../libarchfpga/libarchfpga.a $@
|
||||
@ ar rcs $@ $(OBJ)
|
||||
@ ar d $@ shell_main.o
|
||||
|
||||
# Enable a second round of expansion so that we may include
|
||||
# the target directory as a prerequisite of the object file.
|
||||
.SECONDEXPANSION:
|
||||
|
@ -104,7 +114,7 @@ libvpr.a: $(OBJ) Makefile libarchfpga
|
|||
# timestamp check. Every write to the directory updates the timestamp thus
|
||||
# without this, all but the last file written to a directory would appear
|
||||
# to be out of date.
|
||||
$(OBJ): OBJ/%.o:$(SRC_DIR)/%.c | $$(dir $$@D)
|
||||
$(OBJ): OBJ/%.o:$(SRC_DIR)/%.c | $$(dir $$@D)
|
||||
$(CC) $(FLAGS) -MD -MP -I$(OTHER_DIR) -ISRC/util -c $< -o $@
|
||||
|
||||
# Silently create target directories as need
|
||||
|
@ -113,8 +123,16 @@ $(OBJ_DIRS):
|
|||
|
||||
-include $(DEP)
|
||||
|
||||
.PHONY: all vpr shell_vpr
|
||||
|
||||
all: $(EXE) $(SHELL_EXE)
|
||||
|
||||
vpr: $(EXE)
|
||||
|
||||
shell_vpr: $(SHELL_EXE)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) $(OBJ) $(DEP) libvpr.a
|
||||
rm -f $(SHELL_EXE) $(EXE) $(OBJ) $(DEP) libvpr.a libvpr_shell.a
|
||||
cd ../libarchfpga && make clean
|
||||
|
||||
clean_coverage: clean
|
||||
|
|
|
@ -57,40 +57,47 @@ struct s_TokenPair OptionBaseTokenList[] = {
|
|||
{ "power_output_file", OT_POWER_OUT_FILE }, /* Output file for power results */
|
||||
{ "power", OT_POWER }, /* Run power estimation? */
|
||||
{ "tech_properties", OT_CMOS_TECH_BEHAVIOR_FILE }, /* Technology properties */
|
||||
/* General FPGA_X2P: FPGA-SPICE/Verilog/Bitstream Options */
|
||||
{ "fpga_x2p_rename_illegal_port", OT_FPGA_X2P_RENAME_ILLEGAL_PORT }, /* Xifan TANG: rename illegal port names */
|
||||
{ "fpga_x2p_signal_density_weight", OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT }, /* The weight of signal density */
|
||||
{ "fpga_x2p_sim_window_size", OT_FPGA_X2P_SIM_WINDOW_SIZE }, /* Window size in determining number of clock cycles in simulation */
|
||||
/* Xifan TANG: FPGA SPICE Support */
|
||||
{ "fpga_spice", OT_FPGA_SPICE },/* Xifan TANG: SPICE Model Support, turn on the functionality*/
|
||||
{ "fpga_spice_rename_illegal_port", OT_FPGA_SPICE_RENAME_ILLEGAL_PORT }, /* Xifan TANG: rename illegal port names */
|
||||
{ "fpga_spice_signal_density_weight", OT_FPGA_SPICE_SIGNAL_DENSITY_WEIGHT }, /* The weight of signal density */
|
||||
{ "fpga_spice_sim_window_size", OT_FPGA_SPICE_SIM_WINDOW_SIZE }, /* Window size in determining number of clock cycles in simulation */
|
||||
{ "fpga_spice_sim_mt_num", OT_FPGA_SPICE_SIM_MT_NUM }, /* number of multi-thread used in simulation */
|
||||
{ "fpga_spice_dir", OT_SPICE_DIR },/* Xifan TANG: SPICE Model Support, directory of spice netlists*/
|
||||
{ "fpga_spice_print_top_testbench", OT_SPICE_PRINT_TOP_TESTBENCH }, /* Print the SPICE TOP Testbench for MUXes */
|
||||
{ "fpga_spice_print_pb_mux_testbench", OT_SPICE_PRINT_PB_MUX_TESTBENCH }, /* Print the SPICE Testbench for MUXes */
|
||||
{ "fpga_spice_print_cb_mux_testbench", OT_SPICE_PRINT_CB_MUX_TESTBENCH }, /* Print the SPICE Testbench for MUXes */
|
||||
{ "fpga_spice_print_sb_mux_testbench", OT_SPICE_PRINT_SB_MUX_TESTBENCH }, /* Print the SPICE Testbench for MUXes */
|
||||
{ "fpga_spice_print_cb_testbench", OT_SPICE_PRINT_CB_TESTBENCH }, /* Print the SPICE Testbench for CBs */
|
||||
{ "fpga_spice_print_sb_testbench", OT_SPICE_PRINT_SB_TESTBENCH }, /* Print the SPICE Testbench for SBs */
|
||||
{ "fpga_spice_print_grid_testbench", OT_SPICE_PRINT_GRID_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_print_lut_testbench", OT_SPICE_PRINT_LUT_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_print_hardlogic_testbench", OT_SPICE_PRINT_HARDLOGIC_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_dir", OT_FPGA_SPICE_DIR },/* Xifan TANG: SPICE Model Support, directory of spice netlists*/
|
||||
{ "fpga_spice_print_top_testbench", OT_FPGA_SPICE_PRINT_TOP_TESTBENCH }, /* Print the SPICE TOP Testbench for MUXes */
|
||||
{ "fpga_spice_print_pb_mux_testbench", OT_FPGA_SPICE_PRINT_PB_MUX_TESTBENCH }, /* Print the SPICE Testbench for MUXes */
|
||||
{ "fpga_spice_print_cb_mux_testbench", OT_FPGA_SPICE_PRINT_CB_MUX_TESTBENCH }, /* Print the SPICE Testbench for MUXes */
|
||||
{ "fpga_spice_print_sb_mux_testbench", OT_FPGA_SPICE_PRINT_SB_MUX_TESTBENCH }, /* Print the SPICE Testbench for MUXes */
|
||||
{ "fpga_spice_print_cb_testbench", OT_FPGA_SPICE_PRINT_CB_TESTBENCH }, /* Print the SPICE Testbench for CBs */
|
||||
{ "fpga_spice_print_sb_testbench", OT_FPGA_SPICE_PRINT_SB_TESTBENCH }, /* Print the SPICE Testbench for SBs */
|
||||
{ "fpga_spice_print_grid_testbench", OT_FPGA_SPICE_PRINT_GRID_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_print_lut_testbench", OT_FPGA_SPICE_PRINT_LUT_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_print_hardlogic_testbench", OT_FPGA_SPICE_PRINT_HARDLOGIC_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_print_io_testbench", OT_FPGA_SPICE_PRINT_IO_TESTBENCH }, /* Print the SPICE Testbench for Grids */
|
||||
{ "fpga_spice_leakage_only", OT_FPGA_SPICE_LEAKAGE_ONLY }, /* Only simulate leakage power in FPGA SPICE */
|
||||
{ "fpga_spice_parasitic_net_estimation_off", OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION_OFF }, /* Xifan TANG: turn off the parasitic net estimation*/
|
||||
{ "fpga_spice_testbench_load_extraction_off", OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION_OFF }, /* Xifan TANG: turn off the parasitic net estimation*/
|
||||
|
||||
|
||||
{ "fpga_spice_parasitic_net_estimation", OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION}, /* Xifan TANG: turn on/off the parasitic net estimation*/
|
||||
{ "fpga_spice_testbench_load_extraction", OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION}, /* Xifan TANG: turn on/off the parasitic net estimation*/
|
||||
{ "fpga_spice_simulator_path", OT_FPGA_SPICE_SIMULATOR_PATH}, /* Specify simulator path for SPICE netlists */
|
||||
{ "fpga_spice_sim_mt_num", OT_FPGA_SPICE_SIM_MT_NUM }, /* number of multi-thread used in simulation */
|
||||
/* Xifan TANG: Synthsizable Verilog */
|
||||
{ "fpga_verilog", OT_FPGA_VERILOG_SYN },
|
||||
{ "fpga_verilog_dir", OT_FPGA_VERILOG_SYN_DIR },
|
||||
{ "fpga_verilog_print_top_testbench", OT_FPGA_VERILOG_SYN_PRINT_TOP_TB },
|
||||
{ "fpga_verilog_print_top_auto_testbench", OT_FPGA_VERILOG_SYN_PRINT_TOP_AUTO_TB },
|
||||
{ "fpga_verilog_print_input_blif_testbench", OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TB },
|
||||
{ "fpga_verilog_print_input_blif_testbench", OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TB },
|
||||
{ "fpga_verilog_tb_serial_config_mode", OT_FPGA_VERILOG_SYN_TB_SERIAL_CONFIG_MODE },
|
||||
{ "fpga_verilog_print_top_testbench", OT_FPGA_VERILOG_SYN_PRINT_TOP_TESTBENCH },
|
||||
{ "fpga_verilog_print_autocheck_top_testbench", OT_FPGA_VERILOG_SYN_PRINT_AUTOCHECK_TOP_TESTBENCH },
|
||||
{ "fpga_verilog_print_input_blif_testbench", OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TESTBENCH },
|
||||
{ "fpga_verilog_print_formal_verification_top_netlist", OT_FPGA_VERILOG_SYN_PRINT_FORMAL_VERIFICATION_TOP_NETLIST },
|
||||
{ "fpga_verilog_include_timing", OT_FPGA_VERILOG_SYN_INCLUDE_TIMING }, /* Include timing constraints in Verilog netlists */
|
||||
{ "fpga_verilog_init_sim", OT_FPGA_VERILOG_INIT_SIM }, /* Allow simulation initialization */
|
||||
{ "fpga_verilog_print_modelsim_autodeck", OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK }, /* Allow simulation script generation */
|
||||
{ "fpga_verilog_modelsim_ini_path", OT_FPGA_VERILOG_SYN_MODELSIM_INI_PATH }, /* Specify the simulator path for Verilog netlists */
|
||||
/* mrFPGA: Xifan TANG */
|
||||
{ "fpga_verilog_include_signal_init", OT_FPGA_VERILOG_SYN_INCLUDE_SIGNAL_INIT }, /* Include signal initialization in Verilog netlists */
|
||||
{ "fpga_verilog_include_icarus_simulator", OT_FPGA_VERILOG_SYN_INCLUDE_ICARUS_SIMULATOR }, /* Include/activate Icarus required functions in Verilog netlists */
|
||||
{ "fpga_verilog_print_modelsim_autodeck", OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK }, /* Generate autodeck scripts for modelsim */
|
||||
{ "fpga_verilog_print_user_defined_template", OT_FPGA_VERILOG_SYN_PRINT_USER_DEFINED_TEMPLATE }, /* Specify the simulator path for Verilog netlists */
|
||||
{ "fpga_verilog_print_report_timing_tcl", OT_FPGA_VERILOG_SYN_PRINT_REPORT_TIMING_TCL }, /* Specify the simulator path for Verilog netlists */
|
||||
{ "fpga_verilog_report_timing_rpt_path", OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH }, /* Specify the simulator path for Verilog netlists */
|
||||
{ "fpga_verilog_print_sdc_pnr", OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR }, /* Specify the simulator path for Verilog netlists */
|
||||
{ "fpga_verilog_print_sdc_analysis", OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS }, /* Specify the simulator path for Verilog netlists */
|
||||
/* Xifan Tang: Bitstream generator */
|
||||
{ "fpga_bitstream_generator", OT_FPGA_BITSTREAM_GENERATOR }, /* turn on bitstream generator, and specify the output file */
|
||||
{ "fpga_bitstream_output_file", OT_FPGA_BITSTREAM_OUTPUT_FILE }, /* turn on bitstream generator, and specify the output file */
|
||||
/* mrFPGA: Xifan TANG */
|
||||
{"show_sram", OT_SHOW_SRAM},
|
||||
{"show_pass_trans", OT_SHOW_PASS_TRANS},
|
||||
|
|
|
@ -74,36 +74,47 @@ enum e_OptionBaseToken {
|
|||
OT_ACTIVITY_FILE,
|
||||
OT_POWER_OUT_FILE,
|
||||
OT_CMOS_TECH_BEHAVIOR_FILE,
|
||||
/* General FPGA_X2P: FPGA-SPICE/Verilog/Bitstream Options */
|
||||
OT_FPGA_X2P_RENAME_ILLEGAL_PORT,
|
||||
OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT, /* The weight of signal density in determining number of clock cycles in simulation */
|
||||
OT_FPGA_X2P_SIM_WINDOW_SIZE, /* Window size in determining number of clock cycles in simulation */
|
||||
/* Xifan TANG: FPGA SPICE Support */
|
||||
OT_FPGA_SPICE, /* Xifan TANG: FPGA SPICE Model Support */
|
||||
OT_FPGA_SPICE_RENAME_ILLEGAL_PORT,
|
||||
OT_FPGA_SPICE_SIGNAL_DENSITY_WEIGHT, /* The weight of signal density in determining number of clock cycles in simulation */
|
||||
OT_FPGA_SPICE_SIM_WINDOW_SIZE, /* Window size in determining number of clock cycles in simulation */
|
||||
OT_FPGA_SPICE_SIM_MT_NUM, /* number of multi-thread used in simulation */
|
||||
OT_SPICE_DIR, /* Xifan TANG: FPGA SPICE Model Support */
|
||||
OT_SPICE_PRINT_TOP_TESTBENCH, /* Xifan TANG: Print Top-level SPICE Testbench */
|
||||
OT_SPICE_PRINT_PB_MUX_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_SPICE_PRINT_CB_MUX_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_SPICE_PRINT_SB_MUX_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_SPICE_PRINT_CB_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for CBs */
|
||||
OT_SPICE_PRINT_SB_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for SBs */
|
||||
OT_SPICE_PRINT_GRID_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for Grids */
|
||||
OT_SPICE_PRINT_LUT_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for LUTs */
|
||||
OT_SPICE_PRINT_HARDLOGIC_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for hard logic s */
|
||||
OT_FPGA_SPICE_DIR, /* Xifan TANG: FPGA SPICE Model Support */
|
||||
OT_FPGA_SPICE_PRINT_TOP_TESTBENCH, /* Xifan TANG: Print Top-level SPICE Testbench */
|
||||
OT_FPGA_SPICE_PRINT_PB_MUX_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_FPGA_SPICE_PRINT_CB_MUX_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_FPGA_SPICE_PRINT_SB_MUX_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_FPGA_SPICE_PRINT_CB_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for CBs */
|
||||
OT_FPGA_SPICE_PRINT_SB_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for SBs */
|
||||
OT_FPGA_SPICE_PRINT_GRID_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for Grids */
|
||||
OT_FPGA_SPICE_PRINT_LUT_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for LUTs */
|
||||
OT_FPGA_SPICE_PRINT_HARDLOGIC_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for hard logic s */
|
||||
OT_FPGA_SPICE_PRINT_IO_TESTBENCH, /* Xifan TANG: Print SPICE Testbench for hard logic s */
|
||||
OT_FPGA_SPICE_LEAKAGE_ONLY, /* Xifan TANG: Print SPICE Testbench for MUXes */
|
||||
OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION_OFF, /* Xifan TANG: turn off the parasitic net estimation*/
|
||||
OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION_OFF, /* Xifan TANG: turn off the testbench load extraction */
|
||||
OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION, /* Xifan TANG: turn on/off the parasitic net estimation*/
|
||||
OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION, /* Xifan TANG: turn on/off the testbench load extraction */
|
||||
OT_FPGA_SPICE_SIMULATOR_PATH,
|
||||
OT_FPGA_SPICE_SIM_MT_NUM, /* number of multi-thread used in simulation */
|
||||
/* Xifan TANG: Verilog Generation */
|
||||
OT_FPGA_VERILOG_SYN, /* Xifan TANG: Synthesizable Verilog Dump */
|
||||
OT_FPGA_VERILOG_SYN_DIR, /* Xifan TANG: Synthesizable Verilog Dump */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_TOP_TB, /* Xifan TANG: Synthesizable Verilog Dump */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_TOP_AUTO_TB, /* Xifan TANG: Synthesizable Verilog Dump */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TB, /* Xifan TANG: Synthesizable Verilog Dump */
|
||||
OT_FPGA_VERILOG_SYN_TB_SERIAL_CONFIG_MODE, /* Xifan TANG: Synthesizable Verilog Dump */
|
||||
OT_FPGA_VERILOG_SYN_INCLUDE_TIMING, /* Include timing constraint in Verilog*/
|
||||
OT_FPGA_VERILOG_INIT_SIM, /* AA: to allow initialization in simulation */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK, // To allow modelsim script generation
|
||||
OT_FPGA_VERILOG_SYN_MODELSIM_INI_PATH, // To set modelsim script path
|
||||
OT_FPGA_VERILOG_SYN_PRINT_TOP_TESTBENCH, /* Xifan Tang: Synthesizable Verilog, turn on option: output testbench for top-level netlist */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_AUTOCHECK_TOP_TESTBENCH, /* Xifan Tang: Synthesizable Verilog, turn on option: output testbench for top-level netlist */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TESTBENCH, /* Xifan Tang: Synthesizable Verilog, turn on option: output testbench for the orignial input blif */
|
||||
OT_FPGA_VERILOG_SYN_PRINT_FORMAL_VERIFICATION_TOP_NETLIST, /* Xifan Tang: Synthesizable Verilog, turn on option: output netlists in a compact way */
|
||||
OT_FPGA_VERILOG_SYN_INCLUDE_TIMING, /* Xifan TANG: Include timing constraints in Verilog */
|
||||
OT_FPGA_VERILOG_SYN_INCLUDE_SIGNAL_INIT, /* Xifan TANG: Include timing constraints in Verilog */
|
||||
OT_FPGA_VERILOG_SYN_INCLUDE_ICARUS_SIMULATOR,
|
||||
OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK,
|
||||
OT_FPGA_VERILOG_SYN_PRINT_USER_DEFINED_TEMPLATE,
|
||||
OT_FPGA_VERILOG_SYN_PRINT_REPORT_TIMING_TCL,
|
||||
OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH,
|
||||
OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR,
|
||||
OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS,
|
||||
/* Xifan Tang: Bitstream generator */
|
||||
OT_FPGA_BITSTREAM_GENERATOR,
|
||||
OT_FPGA_BITSTREAM_OUTPUT_FILE,
|
||||
/* mrFPGA: Xifan TANG */
|
||||
OT_SHOW_SRAM,
|
||||
OT_SHOW_PASS_TRANS,
|
||||
|
|
|
@ -474,64 +474,84 @@ ProcessOption(INP char **Args, INOUTP t_options * Options) {
|
|||
case OT_CMOS_TECH_BEHAVIOR_FILE:
|
||||
return ReadString(Args, &Options->CmosTechFile);
|
||||
|
||||
/* Xifan Tang: FPGA X2P Options*/
|
||||
case OT_FPGA_X2P_RENAME_ILLEGAL_PORT:
|
||||
return Args;
|
||||
case OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT:
|
||||
return ReadFloat(Args, &Options->fpga_spice_signal_density_weight);
|
||||
case OT_FPGA_X2P_SIM_WINDOW_SIZE:
|
||||
return ReadFloat(Args, &Options->fpga_spice_sim_window_size);
|
||||
/* Xifan TANG: FPGA SPICE Model Options*/
|
||||
case OT_FPGA_SPICE:
|
||||
return Args;
|
||||
case OT_SPICE_DIR:
|
||||
case OT_FPGA_SPICE_DIR:
|
||||
return ReadString(Args, &Options->spice_dir);
|
||||
case OT_SPICE_PRINT_TOP_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_TOP_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_PB_MUX_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_PB_MUX_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_CB_MUX_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_CB_MUX_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_SB_MUX_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_SB_MUX_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_CB_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_CB_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_SB_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_SB_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_GRID_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_GRID_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_LUT_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_LUT_TESTBENCH:
|
||||
return Args;
|
||||
case OT_SPICE_PRINT_HARDLOGIC_TESTBENCH:
|
||||
case OT_FPGA_SPICE_PRINT_HARDLOGIC_TESTBENCH:
|
||||
return Args;
|
||||
case OT_FPGA_SPICE_PRINT_IO_TESTBENCH:
|
||||
return Args;
|
||||
case OT_FPGA_SPICE_LEAKAGE_ONLY:
|
||||
return Args;
|
||||
case OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION_OFF:
|
||||
return Args;
|
||||
case OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION_OFF:
|
||||
return Args;
|
||||
case OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION:
|
||||
return ReadOnOff(Args, &Options->fpga_spice_parasitic_net_estimation);
|
||||
case OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION:
|
||||
return ReadOnOff(Args, &Options->fpga_spice_testbench_load_extraction);
|
||||
case OT_FPGA_SPICE_SIM_MT_NUM:
|
||||
return ReadInt(Args, &Options->fpga_spice_sim_mt_num);
|
||||
case OT_FPGA_SPICE_SIMULATOR_PATH:
|
||||
return ReadString(Args, &Options->fpga_spice_simulator_path);
|
||||
/* Xifan TANG: Synthesizable Verilog */
|
||||
case OT_FPGA_VERILOG_SYN:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_DIR:
|
||||
return ReadString(Args, &Options->syn_verilog_dir);
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_TOP_TB:
|
||||
return ReadString(Args, &Options->fpga_syn_verilog_dir);
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_TOP_TESTBENCH:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_TOP_AUTO_TB:
|
||||
return ReadString(Args, &Options->verilog_benchmark_path);
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TB:
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_AUTOCHECK_TOP_TESTBENCH:
|
||||
return ReadString(Args, &Options->fpga_verilog_reference_benchmark_file);
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TESTBENCH:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_TB_SERIAL_CONFIG_MODE:
|
||||
return Args;
|
||||
case OT_FPGA_SPICE_RENAME_ILLEGAL_PORT:
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_FORMAL_VERIFICATION_TOP_NETLIST:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_INCLUDE_TIMING:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_INIT_SIM:
|
||||
case OT_FPGA_VERILOG_SYN_INCLUDE_SIGNAL_INIT:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_INCLUDE_ICARUS_SIMULATOR:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_MODELSIM_INI_PATH:
|
||||
return ReadString(Args, &Options->fpga_verilog_modelsim_ini_path);
|
||||
case OT_FPGA_SPICE_SIGNAL_DENSITY_WEIGHT:
|
||||
return ReadFloat(Args, &Options->signal_density_weight);
|
||||
case OT_FPGA_SPICE_SIM_WINDOW_SIZE:
|
||||
return ReadFloat(Args, &Options->sim_window_size);
|
||||
case OT_FPGA_SPICE_SIM_MT_NUM:
|
||||
return ReadInt(Args, &Options->spice_sim_mt_num);
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_USER_DEFINED_TEMPLATE:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_REPORT_TIMING_TCL:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH:
|
||||
return ReadString(Args, &Options->fpga_verilog_report_timing_path);
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR:
|
||||
return Args;
|
||||
case OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS:
|
||||
return Args;
|
||||
/* Xifan TANG: Bitstream generator */
|
||||
case OT_FPGA_BITSTREAM_GENERATOR:
|
||||
return Args;
|
||||
case OT_FPGA_BITSTREAM_OUTPUT_FILE:
|
||||
return ReadString(Args, &Options->fpga_bitstream_file);
|
||||
/* mrFPGA: Xifan TANG */
|
||||
case OT_SHOW_SRAM:
|
||||
case OT_SHOW_PASS_TRANS:
|
||||
|
|
|
@ -91,16 +91,23 @@ struct s_options {
|
|||
/* Last read settings file */
|
||||
int read_settings;
|
||||
|
||||
/* Xifan TANG: signal weight in FPGA_SPICE simulation */
|
||||
float fpga_spice_signal_density_weight;
|
||||
float fpga_spice_sim_window_size;
|
||||
|
||||
/* Xifan TANG: SPICE Support*/
|
||||
char* spice_dir;
|
||||
boolean fpga_spice_parasitic_net_estimation;
|
||||
boolean fpga_spice_testbench_load_extraction;
|
||||
int fpga_spice_sim_mt_num;
|
||||
char* fpga_spice_simulator_path;
|
||||
/* Xifan TANG: Synthesizable Verilog */
|
||||
char* syn_verilog_dir;
|
||||
char* verilog_benchmark_path;
|
||||
char* fpga_syn_verilog_dir;
|
||||
char* fpga_verilog_reference_benchmark_file;
|
||||
char* fpga_verilog_modelsim_ini_path;
|
||||
/* Xifan TANG: signal weight in FPGA_SPICE simulation */
|
||||
float signal_density_weight;
|
||||
float sim_window_size;
|
||||
int spice_sim_mt_num;
|
||||
char* fpga_verilog_report_timing_path;
|
||||
/* Xifan TANG: Bitstream generator */
|
||||
char* fpga_bitstream_file;
|
||||
};
|
||||
|
||||
enum e_echo_files {
|
||||
|
|
|
@ -48,14 +48,18 @@ static void SetupSpiceOpts(t_options Options,
|
|||
static void SetupSynVerilogOpts(t_options Options,
|
||||
t_syn_verilog_opts* syn_verilog_opts,
|
||||
t_arch* arch);
|
||||
|
||||
/* Xifan TANG: Bitstream Generator */
|
||||
static void SetupBitstreamGenOpts(t_options Options,
|
||||
t_bitstream_gen_opts* bitstream_gen_opts,
|
||||
t_arch* arch);
|
||||
|
||||
/* Xifan TANG: FPGA-SPICE Tool suites Options Setup */
|
||||
static void SetupFpgaSpiceOpts(t_options Options,
|
||||
t_fpga_spice_opts* fpga_spice_opts,
|
||||
t_arch* arch);
|
||||
/* end */
|
||||
/* Xifan Tang: Parse CLB to CLB direct connections */
|
||||
static void alloc_and_init_globals_clb_to_clb_directs(int num_directs,
|
||||
t_direct_inf* directs);
|
||||
|
||||
/* mrFPGA */
|
||||
static void SetupSwitches_mrFPGA(INP t_arch Arch,
|
||||
|
@ -67,6 +71,77 @@ static void set_max_pins_per_side();
|
|||
static void hack_switch_to_rram(struct s_det_routing_arch *det_routing_arch);
|
||||
/* end */
|
||||
|
||||
void VPRSetupArch(t_arch* arch,
|
||||
t_det_routing_arch* RoutingArch,
|
||||
t_segment_inf ** Segments,
|
||||
/*Xifan TANG: Switch Segment Pattern Support*/
|
||||
t_swseg_pattern_inf** swseg_patterns,
|
||||
t_model** user_models,
|
||||
t_model** library_models) {
|
||||
int i, j;
|
||||
|
||||
(*user_models) = arch->models;
|
||||
(*library_models) = arch->model_library;
|
||||
|
||||
/* TODO: this is inelegant, I should be populating this information in XmlReadArch */
|
||||
EMPTY_TYPE = NULL;
|
||||
FILL_TYPE = NULL;
|
||||
IO_TYPE = NULL;
|
||||
for (i = 0; i < num_types; i++) {
|
||||
if (strcmp(type_descriptors[i].name, "<EMPTY>") == 0) {
|
||||
EMPTY_TYPE = &type_descriptors[i];
|
||||
} else if (strcmp(type_descriptors[i].name, "io") == 0) {
|
||||
IO_TYPE = &type_descriptors[i];
|
||||
} else {
|
||||
for (j = 0; j < type_descriptors[i].num_grid_loc_def; j++) {
|
||||
if (type_descriptors[i].grid_loc_def[j].grid_loc_type == FILL) {
|
||||
assert(FILL_TYPE == NULL);
|
||||
FILL_TYPE = &type_descriptors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(EMPTY_TYPE != NULL && FILL_TYPE != NULL && IO_TYPE != NULL);
|
||||
|
||||
*Segments = arch->Segments;
|
||||
RoutingArch->num_segment = arch->num_segments;
|
||||
/*Xifan TANG: Switch Segment Pattern Support*/
|
||||
(*swseg_patterns) = arch->swseg_patterns;
|
||||
RoutingArch->num_swseg_pattern = arch->num_swseg_pattern;
|
||||
/* END */
|
||||
|
||||
/* mrFPGA */
|
||||
sync_arch_mrfpga_globals(arch->arch_mrfpga);
|
||||
if (is_mrFPGA) {
|
||||
SetupSwitches_mrFPGA(*arch, RoutingArch,
|
||||
arch->Switches, arch->num_switches, arch->Segments);
|
||||
/* Xifan TANG: added by bjxiao */
|
||||
set_max_pins_per_side();
|
||||
hack_switch_to_rram(RoutingArch);
|
||||
} else {
|
||||
/* Normal Setup VPR switches */
|
||||
// Xifan TANG: Add Connection Blocks Switches
|
||||
SetupSwitches(*arch, RoutingArch,
|
||||
arch->Switches, arch->num_switches);
|
||||
}
|
||||
/* END */
|
||||
|
||||
/* end */
|
||||
if(!is_mrFPGA && is_stack) {
|
||||
add_wire_to_switch(RoutingArch);
|
||||
}
|
||||
/* end */
|
||||
/* Xifan TANG: mrFPGA */
|
||||
if (is_junction) {
|
||||
setup_junction_switch(RoutingArch);
|
||||
}
|
||||
/* end */
|
||||
|
||||
SetupRoutingArch(*arch, RoutingArch);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sets VPR parameters and defaults. Does not do any error checking
|
||||
* as this should have been done by the various input checkers */
|
||||
void SetupVPR(INP t_options *Options, INP boolean TimingEnabled,
|
||||
|
@ -84,7 +159,7 @@ void SetupVPR(INP t_options *Options, INP boolean TimingEnabled,
|
|||
/*Xifan TANG: Switch Segment Pattern Support*/
|
||||
t_swseg_pattern_inf** swseg_patterns,
|
||||
t_fpga_spice_opts* fpga_spice_opts) {
|
||||
int i, j, len;
|
||||
int len;
|
||||
|
||||
len = strlen(Options->CircuitName) + 6; /* circuit_name.blif/0*/
|
||||
if (Options->out_file_prefix != NULL ) {
|
||||
|
@ -210,62 +285,8 @@ void SetupVPR(INP t_options *Options, INP boolean TimingEnabled,
|
|||
&num_types);
|
||||
}
|
||||
|
||||
*user_models = Arch->models;
|
||||
*library_models = Arch->model_library;
|
||||
VPRSetupArch(Arch, RoutingArch, Segments, swseg_patterns, user_models, library_models);
|
||||
|
||||
/* TODO: this is inelegant, I should be populating this information in XmlReadArch */
|
||||
EMPTY_TYPE = NULL;
|
||||
FILL_TYPE = NULL;
|
||||
IO_TYPE = NULL;
|
||||
for (i = 0; i < num_types; i++) {
|
||||
if (strcmp(type_descriptors[i].name, "<EMPTY>") == 0) {
|
||||
EMPTY_TYPE = &type_descriptors[i];
|
||||
} else if (strcmp(type_descriptors[i].name, "io") == 0) {
|
||||
IO_TYPE = &type_descriptors[i];
|
||||
} else {
|
||||
for (j = 0; j < type_descriptors[i].num_grid_loc_def; j++) {
|
||||
if (type_descriptors[i].grid_loc_def[j].grid_loc_type == FILL) {
|
||||
assert(FILL_TYPE == NULL);
|
||||
FILL_TYPE = &type_descriptors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(EMPTY_TYPE != NULL && FILL_TYPE != NULL && IO_TYPE != NULL);
|
||||
|
||||
*Segments = Arch->Segments;
|
||||
RoutingArch->num_segment = Arch->num_segments;
|
||||
/*Xifan TANG: Switch Segment Pattern Support*/
|
||||
(*swseg_patterns) = Arch->swseg_patterns;
|
||||
RoutingArch->num_swseg_pattern = Arch->num_swseg_pattern;
|
||||
/* END */
|
||||
|
||||
/* mrFPGA */
|
||||
sync_arch_mrfpga_globals(Arch->arch_mrfpga);
|
||||
if (is_mrFPGA) {
|
||||
SetupSwitches_mrFPGA(*Arch, RoutingArch, Arch->Switches, Arch->num_switches, Arch->Segments);
|
||||
/* Xifan TANG: added by bjxiao */
|
||||
set_max_pins_per_side();
|
||||
hack_switch_to_rram(RoutingArch);
|
||||
} else {
|
||||
/* Normal Setup VPR switches */
|
||||
// Xifan TANG: Add Connection Blocks Switches
|
||||
SetupSwitches(*Arch, RoutingArch, Arch->Switches, Arch->num_switches);
|
||||
}
|
||||
/* END */
|
||||
|
||||
/* end */
|
||||
if(!is_mrFPGA && is_stack) {
|
||||
add_wire_to_switch(RoutingArch);
|
||||
}
|
||||
/* end */
|
||||
/* Xifan TANG: mrFPGA */
|
||||
if (is_junction) {
|
||||
setup_junction_switch(RoutingArch);
|
||||
}
|
||||
/* end */
|
||||
|
||||
SetupRoutingArch(*Arch, RoutingArch);
|
||||
SetupTiming(*Options, *Arch, TimingEnabled, *Operation, *PlacerOpts,
|
||||
*RouterOpts, Timing);
|
||||
SetupPackerOpts(*Options, TimingEnabled, *Arch, Options->NetFile,
|
||||
|
@ -960,18 +981,19 @@ static void SetupSpiceOpts(t_options Options,
|
|||
t_arch* arch) {
|
||||
/* Initialize */
|
||||
spice_opts->do_spice = FALSE;
|
||||
spice_opts->spice_print_top_testbench = FALSE;
|
||||
spice_opts->spice_print_pb_mux_testbench = FALSE;
|
||||
spice_opts->spice_print_cb_mux_testbench = FALSE;
|
||||
spice_opts->spice_print_sb_mux_testbench = FALSE;
|
||||
spice_opts->spice_print_cb_testbench = FALSE;
|
||||
spice_opts->spice_print_sb_testbench = FALSE;
|
||||
spice_opts->spice_print_lut_testbench = FALSE;
|
||||
spice_opts->spice_print_hardlogic_testbench = FALSE;
|
||||
spice_opts->spice_print_grid_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_top_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_pb_mux_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_cb_mux_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_sb_mux_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_cb_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_sb_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_lut_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_hardlogic_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_io_testbench = FALSE;
|
||||
spice_opts->fpga_spice_print_grid_testbench = FALSE;
|
||||
spice_opts->fpga_spice_leakage_only = FALSE;
|
||||
spice_opts->fpga_spice_parasitic_net_estimation_off = FALSE;
|
||||
spice_opts->fpga_spice_testbench_load_extraction_off = FALSE;
|
||||
spice_opts->fpga_spice_parasitic_net_estimation = TRUE;
|
||||
spice_opts->fpga_spice_testbench_load_extraction = TRUE;
|
||||
|
||||
/* Turn on the spice option if it is selected*/
|
||||
if (Options.Count[OT_FPGA_SPICE]) {
|
||||
|
@ -980,65 +1002,74 @@ static void SetupSpiceOpts(t_options Options,
|
|||
/* TODO: this could be more flexible*/
|
||||
spice_opts->include_dir = "include/";
|
||||
spice_opts->subckt_dir = "subckt/";
|
||||
if (Options.Count[OT_SPICE_PRINT_TOP_TESTBENCH]) {
|
||||
spice_opts->spice_print_top_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_TOP_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_top_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_PB_MUX_TESTBENCH]) {
|
||||
spice_opts->spice_print_pb_mux_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_PB_MUX_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_pb_mux_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_CB_MUX_TESTBENCH]) {
|
||||
spice_opts->spice_print_cb_mux_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_CB_MUX_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_cb_mux_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_SB_MUX_TESTBENCH]) {
|
||||
spice_opts->spice_print_sb_mux_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_SB_MUX_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_sb_mux_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_CB_TESTBENCH]) {
|
||||
spice_opts->spice_print_cb_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_CB_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_cb_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_SB_TESTBENCH]) {
|
||||
spice_opts->spice_print_sb_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_SB_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_sb_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_GRID_TESTBENCH]) {
|
||||
spice_opts->spice_print_grid_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_GRID_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_grid_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_LUT_TESTBENCH]) {
|
||||
spice_opts->spice_print_lut_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_LUT_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_lut_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_SPICE_PRINT_HARDLOGIC_TESTBENCH]) {
|
||||
spice_opts->spice_print_hardlogic_testbench = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_HARDLOGIC_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_hardlogic_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_FPGA_SPICE_PRINT_IO_TESTBENCH]) {
|
||||
spice_opts->fpga_spice_print_io_testbench = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_FPGA_SPICE_LEAKAGE_ONLY]) {
|
||||
spice_opts->fpga_spice_leakage_only = TRUE;
|
||||
}
|
||||
if (Options.Count[OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION_OFF]) {
|
||||
spice_opts->fpga_spice_parasitic_net_estimation_off = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_PARASITIC_NET_ESTIMATION]) {
|
||||
spice_opts->fpga_spice_parasitic_net_estimation = Options.fpga_spice_parasitic_net_estimation;
|
||||
}
|
||||
if (Options.Count[OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION_OFF]) {
|
||||
spice_opts->fpga_spice_testbench_load_extraction_off = TRUE;
|
||||
if (Options.Count[OT_FPGA_SPICE_TESTBENCH_LOAD_EXTRACTION]) {
|
||||
spice_opts->fpga_spice_testbench_load_extraction = Options.fpga_spice_testbench_load_extraction;
|
||||
}
|
||||
}
|
||||
/* Set default options */
|
||||
if ((TRUE == spice_opts->do_spice)
|
||||
&&(FALSE == spice_opts->spice_print_top_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_grid_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_pb_mux_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_cb_mux_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_sb_mux_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_cb_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_sb_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_lut_testbench)
|
||||
&&(FALSE == spice_opts->spice_print_hardlogic_testbench)) {
|
||||
spice_opts->spice_print_pb_mux_testbench = TRUE;
|
||||
spice_opts->spice_print_cb_mux_testbench = TRUE;
|
||||
spice_opts->spice_print_sb_mux_testbench = TRUE;
|
||||
spice_opts->spice_print_lut_testbench = TRUE;
|
||||
spice_opts->spice_print_hardlogic_testbench = TRUE;
|
||||
&&(FALSE == spice_opts->fpga_spice_print_top_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_grid_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_pb_mux_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_cb_mux_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_sb_mux_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_cb_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_sb_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_lut_testbench)
|
||||
&&(FALSE == spice_opts->fpga_spice_print_hardlogic_testbench)) {
|
||||
spice_opts->fpga_spice_print_pb_mux_testbench = TRUE;
|
||||
spice_opts->fpga_spice_print_cb_mux_testbench = TRUE;
|
||||
spice_opts->fpga_spice_print_sb_mux_testbench = TRUE;
|
||||
spice_opts->fpga_spice_print_lut_testbench = TRUE;
|
||||
spice_opts->fpga_spice_print_hardlogic_testbench = TRUE;
|
||||
}
|
||||
|
||||
/* Assign the number of mt in SPICE simulation */
|
||||
spice_opts->spice_sim_multi_thread_num = 8;
|
||||
spice_opts->fpga_spice_sim_multi_thread_num = 8;
|
||||
if (Options.Count[OT_FPGA_SPICE_SIM_MT_NUM]) {
|
||||
spice_opts->spice_sim_multi_thread_num = Options.spice_sim_mt_num;
|
||||
spice_opts->fpga_spice_sim_multi_thread_num = Options.fpga_spice_sim_mt_num;
|
||||
}
|
||||
|
||||
/* Assign path of SPICE simulator */
|
||||
spice_opts->simulator_path = NULL;
|
||||
if (Options.Count[OT_FPGA_SPICE_SIMULATOR_PATH]) {
|
||||
spice_opts->simulator_path = my_strdup(Options.fpga_spice_simulator_path);
|
||||
}
|
||||
|
||||
/* If spice option is selected*/
|
||||
|
@ -1056,16 +1087,20 @@ static void SetupSynVerilogOpts(t_options Options,
|
|||
/* Initialize */
|
||||
syn_verilog_opts->dump_syn_verilog = FALSE;
|
||||
syn_verilog_opts->syn_verilog_dump_dir = NULL;
|
||||
syn_verilog_opts->tb_serial_config_mode = FALSE;
|
||||
syn_verilog_opts->print_top_tb = FALSE;
|
||||
syn_verilog_opts->print_top_auto_tb = FALSE;
|
||||
syn_verilog_opts->print_input_blif_tb = FALSE;
|
||||
syn_verilog_opts->print_top_testbench = FALSE;
|
||||
syn_verilog_opts->print_autocheck_top_testbench = FALSE;
|
||||
syn_verilog_opts->reference_verilog_benchmark_file = NULL;
|
||||
syn_verilog_opts->print_input_blif_testbench = FALSE;
|
||||
syn_verilog_opts->include_timing = FALSE;
|
||||
syn_verilog_opts->init_sim = FALSE;
|
||||
syn_verilog_opts->include_signal_init = FALSE;
|
||||
syn_verilog_opts->print_modelsim_autodeck = FALSE;
|
||||
syn_verilog_opts->print_formal_verification_top_netlist= FALSE;
|
||||
syn_verilog_opts->modelsim_ini_path = NULL;
|
||||
|
||||
|
||||
syn_verilog_opts->print_user_defined_template = FALSE;
|
||||
syn_verilog_opts->print_report_timing_tcl = FALSE;
|
||||
syn_verilog_opts->print_sdc_pnr = FALSE;
|
||||
syn_verilog_opts->print_sdc_analysis = FALSE;
|
||||
syn_verilog_opts->include_icarus_simulator = FALSE;
|
||||
|
||||
/* Turn on Syn_verilog options */
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN]) {
|
||||
|
@ -1075,40 +1110,61 @@ static void SetupSynVerilogOpts(t_options Options,
|
|||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_DIR]) {
|
||||
syn_verilog_opts->syn_verilog_dump_dir = my_strdup(Options.syn_verilog_dir);
|
||||
syn_verilog_opts->syn_verilog_dump_dir = my_strdup(Options.fpga_syn_verilog_dir);
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_TB_SERIAL_CONFIG_MODE]) {
|
||||
syn_verilog_opts->tb_serial_config_mode = TRUE;
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_TOP_TESTBENCH]) {
|
||||
syn_verilog_opts->print_top_testbench = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_TOP_TB]) {
|
||||
syn_verilog_opts->print_top_tb = TRUE;
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_AUTOCHECK_TOP_TESTBENCH]) {
|
||||
syn_verilog_opts->print_autocheck_top_testbench = TRUE;
|
||||
syn_verilog_opts->reference_verilog_benchmark_file = my_strdup(Options.fpga_verilog_reference_benchmark_file);
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_TOP_AUTO_TB]) {
|
||||
syn_verilog_opts->print_top_auto_tb = TRUE;
|
||||
syn_verilog_opts->verilog_benchmark_file = my_strdup(Options.verilog_benchmark_path);
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TESTBENCH]) {
|
||||
syn_verilog_opts->print_input_blif_testbench = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_INPUT_BLIF_TB]) {
|
||||
syn_verilog_opts->print_input_blif_tb = TRUE;
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_FORMAL_VERIFICATION_TOP_NETLIST]) {
|
||||
syn_verilog_opts->print_formal_verification_top_netlist = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_INCLUDE_TIMING]) {
|
||||
syn_verilog_opts->include_timing = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_INIT_SIM]) {
|
||||
syn_verilog_opts->init_sim = TRUE;
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_INCLUDE_SIGNAL_INIT]) {
|
||||
syn_verilog_opts->include_signal_init = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_INCLUDE_ICARUS_SIMULATOR]) {
|
||||
syn_verilog_opts->include_icarus_simulator = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_MODELSIM_AUTODECK]) {
|
||||
syn_verilog_opts->print_modelsim_autodeck = TRUE;
|
||||
syn_verilog_opts->modelsim_ini_path = my_strdup(Options.fpga_verilog_modelsim_ini_path);
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_MODELSIM_INI_PATH]) {
|
||||
syn_verilog_opts->modelsim_ini_path = my_strdup(Options.fpga_verilog_modelsim_ini_path);
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_USER_DEFINED_TEMPLATE]) {
|
||||
syn_verilog_opts->print_user_defined_template = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_REPORT_TIMING_TCL]) {
|
||||
syn_verilog_opts->print_report_timing_tcl = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_REPORT_TIMING_RPT_PATH]) {
|
||||
syn_verilog_opts->report_timing_path = my_strdup(Options.fpga_verilog_report_timing_path);
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_SDC_PNR]) {
|
||||
syn_verilog_opts->print_sdc_pnr = TRUE;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_VERILOG_SYN_PRINT_SDC_ANALYSIS]) {
|
||||
syn_verilog_opts->print_sdc_analysis = TRUE;
|
||||
}
|
||||
|
||||
/* SynVerilog needs the input from spice modeling */
|
||||
|
@ -1120,6 +1176,35 @@ static void SetupSynVerilogOpts(t_options Options,
|
|||
return;
|
||||
}
|
||||
|
||||
/*Xifan TANG: Bitstream Generator */
|
||||
static void SetupBitstreamGenOpts(t_options Options,
|
||||
t_bitstream_gen_opts* bitstream_gen_opts,
|
||||
t_arch* arch) {
|
||||
|
||||
/* Initialize */
|
||||
bitstream_gen_opts->gen_bitstream = FALSE;
|
||||
bitstream_gen_opts->bitstream_output_file = NULL;
|
||||
|
||||
/* Turn on Bitstream Generator options */
|
||||
if (Options.Count[OT_FPGA_BITSTREAM_GENERATOR]) {
|
||||
bitstream_gen_opts->gen_bitstream = TRUE;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Options.Count[OT_FPGA_BITSTREAM_OUTPUT_FILE]) {
|
||||
bitstream_gen_opts->bitstream_output_file = my_strdup(Options.fpga_bitstream_file);
|
||||
}
|
||||
|
||||
/* SynVerilog needs the input from spice modeling */
|
||||
if (FALSE == arch->read_xml_spice) {
|
||||
arch->read_xml_spice = bitstream_gen_opts->gen_bitstream;
|
||||
arch->spice = (t_spice*)my_malloc(sizeof(t_spice));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void SetupFpgaSpiceOpts(t_options Options,
|
||||
t_fpga_spice_opts* fpga_spice_opts,
|
||||
t_arch* Arch) {
|
||||
|
@ -1129,40 +1214,46 @@ static void SetupFpgaSpiceOpts(t_options Options,
|
|||
/* Xifan TANG: Synthesizable Verilog Dumping*/
|
||||
SetupSynVerilogOpts(Options, &(fpga_spice_opts->SynVerilogOpts), Arch);
|
||||
|
||||
/* Decide if we need to read activity file */
|
||||
fpga_spice_opts->read_act_file = FALSE;
|
||||
/* Xifan TANG: Bitstream generator */
|
||||
SetupBitstreamGenOpts(Options, &(fpga_spice_opts->BitstreamGenOpts), Arch);
|
||||
|
||||
/* Decide if we need to rename illegal port names */
|
||||
fpga_spice_opts->rename_illegal_port = FALSE;
|
||||
if (Options.Count[OT_FPGA_SPICE_RENAME_ILLEGAL_PORT]) {
|
||||
if (Options.Count[OT_FPGA_X2P_RENAME_ILLEGAL_PORT]) {
|
||||
fpga_spice_opts->rename_illegal_port = TRUE;
|
||||
}
|
||||
|
||||
/* Assign the weight of signal density */
|
||||
fpga_spice_opts->signal_density_weight = 1.;
|
||||
if (Options.Count[OT_FPGA_SPICE_SIGNAL_DENSITY_WEIGHT]) {
|
||||
fpga_spice_opts->signal_density_weight = Options.signal_density_weight;
|
||||
if (Options.Count[OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT]) {
|
||||
fpga_spice_opts->signal_density_weight = Options.fpga_spice_signal_density_weight;
|
||||
}
|
||||
|
||||
/* Assign the weight of signal density */
|
||||
fpga_spice_opts->sim_window_size = 0.5;
|
||||
if (Options.Count[OT_FPGA_SPICE_SIM_WINDOW_SIZE]) {
|
||||
fpga_spice_opts->sim_window_size = Options.sim_window_size;
|
||||
if (Options.Count[OT_FPGA_X2P_SIM_WINDOW_SIZE]) {
|
||||
fpga_spice_opts->sim_window_size = Options.fpga_spice_sim_window_size;
|
||||
}
|
||||
|
||||
/* Decide if we need to do FPGA-SPICE */
|
||||
fpga_spice_opts->do_fpga_spice = FALSE;
|
||||
if (( TRUE == fpga_spice_opts->SpiceOpts.do_spice)
|
||||
||(TRUE == fpga_spice_opts->SynVerilogOpts.dump_syn_verilog)
|
||||
||(TRUE == fpga_spice_opts->BitstreamGenOpts.gen_bitstream)) {
|
||||
fpga_spice_opts->do_fpga_spice = TRUE;
|
||||
}
|
||||
|
||||
/* Decide if we need to read activity file */
|
||||
fpga_spice_opts->read_act_file = FALSE;
|
||||
if (( TRUE == fpga_spice_opts->SpiceOpts.do_spice)
|
||||
||(TRUE == fpga_spice_opts->SynVerilogOpts.dump_syn_verilog)) {
|
||||
fpga_spice_opts->read_act_file = TRUE;
|
||||
fpga_spice_opts->do_fpga_spice = TRUE;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the global variables for clb to clb directs */
|
||||
static
|
||||
void alloc_and_init_globals_clb_to_clb_directs(int num_directs,
|
||||
t_direct_inf* directs) {
|
||||
num_clb2clb_directs = num_directs;
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
#define SETUPVPR_H
|
||||
|
||||
|
||||
void VPRSetupArch(t_arch* arch,
|
||||
t_det_routing_arch* RoutingArch,
|
||||
t_segment_inf ** Segments,
|
||||
t_swseg_pattern_inf** swseg_patterns,
|
||||
t_model** user_models,
|
||||
t_model** library_models);
|
||||
|
||||
void alloc_and_init_globals_clb_to_clb_directs(int num_directs,
|
||||
t_direct_inf* directs);
|
||||
|
||||
void SetupVPR(INP t_options *Options,
|
||||
INP boolean TimingEnabled,
|
||||
|
|
|
@ -523,7 +523,7 @@ static void add_latch(int doall, INP t_model *latch_model) {
|
|||
logical_block[num_logical_blocks - 1].trigger_type = my_strdup(saved_names[2]);
|
||||
/* Store the initial value */
|
||||
logical_block[num_logical_blocks - 1].init_val = my_atoi(saved_names[4]);
|
||||
/* Identify clocks */
|
||||
/* Add clock identification */
|
||||
logical_block[logical_block[num_logical_blocks - 1].clock_net].is_clock = TRUE;
|
||||
/*END*/
|
||||
|
||||
|
|
|
@ -962,8 +962,10 @@ static int count_sinks_internal_cb_rr_graph_net_nums(
|
|||
for (i = 0; i < cur_rr_node->num_edges; i++) {
|
||||
if (&rr_graph[rr_graph[cur_rr_node->edges[i]].prev_node]
|
||||
== cur_rr_node) {
|
||||
if (!(rr_graph[cur_rr_node->edges[i]].net_num == OPEN || rr_graph[cur_rr_node->edges[i]].net_num == cur_rr_node->net_num)) {
|
||||
assert(
|
||||
rr_graph[cur_rr_node->edges[i]].net_num == OPEN || rr_graph[cur_rr_node->edges[i]].net_num == cur_rr_node->net_num);
|
||||
}
|
||||
count += count_sinks_internal_cb_rr_graph_net_nums(
|
||||
&rr_graph[cur_rr_node->edges[i]], rr_graph);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ Second - instantiate_top_level() module is called. This function will will trave
|
|||
|
||||
Third - instantiate_SDF_header() is a short function that will just write the top level declarations in the SDF file.
|
||||
|
||||
Fourth - All the wires in the design are instantiated. This is done in the way demonstrated bellow:
|
||||
Fourth - All the wires in the design are instantiated. This is done in the way demonstrated below:
|
||||
|
||||
Traverse through all primitives
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -102,6 +102,13 @@ t_trace* vpr_resync_post_route_netlist_to_TI_CLAY_v1_architecture(
|
|||
INP const t_arch *arch);
|
||||
|
||||
/* FPGA-SPICE */
|
||||
#include "fpga_spice_api.h"
|
||||
#include "fpga_x2p_api.h"
|
||||
|
||||
/* mrFPGA : Xifan TANG */
|
||||
#include "mrfpga_api.h"
|
||||
/* END */
|
||||
|
||||
/* APIs to be call by the interactive shell*/
|
||||
void vpr_init_file_handler() ;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -201,6 +201,7 @@ typedef struct s_pb {
|
|||
|
||||
/* Xifan TANG: SPICE model support*/
|
||||
char* spice_name_tag;
|
||||
void* phy_pb;
|
||||
|
||||
/* Xifan TANG: FPGA-SPICE and SynVerilog */
|
||||
int num_reserved_conf_bits;
|
||||
|
@ -248,8 +249,7 @@ typedef struct s_logical_block {
|
|||
/* for Register/flip-flop */
|
||||
char* trigger_type;
|
||||
int init_val;
|
||||
/* To identify if this is a clock */
|
||||
int is_clock;
|
||||
boolean is_clock;
|
||||
|
||||
} t_logical_block;
|
||||
|
||||
|
@ -557,6 +557,7 @@ typedef struct s_grid_tile {
|
|||
/* Stores the bounding box of a net in terms of the minimum and *
|
||||
* maximum coordinates of the blocks forming the net, clipped to *
|
||||
* the region (1..nx, 1..ny). */
|
||||
typedef struct s_bb t_bb;
|
||||
struct s_bb {
|
||||
int xmin;
|
||||
int xmax;
|
||||
|
@ -598,6 +599,11 @@ struct s_block {
|
|||
int** pin_prefer_side; /* [0..num_pins-1][0..3] */
|
||||
|
||||
t_pb *pb;
|
||||
|
||||
/* Xifan TANG: FPGA-SPICE
|
||||
* pb for physical model
|
||||
*/
|
||||
void* phy_pb;
|
||||
|
||||
boolean isFixed;
|
||||
|
||||
|
@ -616,6 +622,8 @@ struct s_file_name_opts {
|
|||
char *PowerFile;
|
||||
char *CmosTechFile;
|
||||
char *out_file_prefix;
|
||||
/* For shell-like interface */
|
||||
char *SDCFile;
|
||||
};
|
||||
|
||||
/* Options for packing
|
||||
|
@ -881,7 +889,7 @@ typedef struct s_seg_details {
|
|||
* (UDSD by AY) drivers: How do signals driving a routing track connect to *
|
||||
* the track? *
|
||||
* index: index of the segment type used for this track. */
|
||||
|
||||
typedef struct s_linked_f_pointer t_linked_f_pointer;
|
||||
struct s_linked_f_pointer {
|
||||
struct s_linked_f_pointer *next;
|
||||
float *fptr;
|
||||
|
@ -966,6 +974,7 @@ struct s_rr_node {
|
|||
int* drive_switches;
|
||||
/* Xifan TANG: for parasitic net estimation */
|
||||
boolean vpack_net_num_changed;
|
||||
boolean is_parasitic_net;
|
||||
/* Xifan TANG: pb_pin_eq_auto_detect support */
|
||||
boolean is_in_heap;
|
||||
/* SPECIAL: For switch box muxes */
|
||||
|
@ -973,6 +982,9 @@ struct s_rr_node {
|
|||
t_rr_node** sb_drive_rr_nodes;
|
||||
int* sb_drive_switches;
|
||||
t_pb* pb;
|
||||
/* BC: Supports SDC for SBs/CBs. PBs use the one inside of the pb_graph*/
|
||||
char* name_mux;
|
||||
int id_path;
|
||||
// int seg_index; /* Valid only for CHANX or CHANY*/
|
||||
/* END */
|
||||
|
||||
|
@ -1182,25 +1194,27 @@ struct s_cb {
|
|||
typedef struct s_spice_opts t_spice_opts;
|
||||
struct s_spice_opts {
|
||||
boolean do_spice;
|
||||
boolean spice_print_top_testbench;
|
||||
boolean spice_print_grid_testbench;
|
||||
boolean spice_print_cb_testbench;
|
||||
boolean spice_print_sb_testbench;
|
||||
boolean spice_print_pb_mux_testbench;
|
||||
boolean spice_print_cb_mux_testbench;
|
||||
boolean spice_print_sb_mux_testbench;
|
||||
boolean spice_print_lut_testbench;
|
||||
boolean spice_print_hardlogic_testbench;
|
||||
boolean fpga_spice_print_top_testbench;
|
||||
boolean fpga_spice_print_grid_testbench;
|
||||
boolean fpga_spice_print_cb_testbench;
|
||||
boolean fpga_spice_print_sb_testbench;
|
||||
boolean fpga_spice_print_pb_mux_testbench;
|
||||
boolean fpga_spice_print_cb_mux_testbench;
|
||||
boolean fpga_spice_print_sb_mux_testbench;
|
||||
boolean fpga_spice_print_lut_testbench;
|
||||
boolean fpga_spice_print_hardlogic_testbench;
|
||||
boolean fpga_spice_print_io_testbench;
|
||||
boolean fpga_spice_leakage_only;
|
||||
boolean fpga_spice_parasitic_net_estimation_off;
|
||||
boolean fpga_spice_testbench_load_extraction_off;
|
||||
boolean fpga_spice_parasitic_net_estimation;
|
||||
boolean fpga_spice_testbench_load_extraction;
|
||||
|
||||
/*Xifan TANG: FPGA SPICE Model Support*/
|
||||
char* spice_dir;
|
||||
char* include_dir;
|
||||
char* subckt_dir;
|
||||
|
||||
int spice_sim_multi_thread_num;
|
||||
int fpga_spice_sim_multi_thread_num;
|
||||
char* simulator_path;
|
||||
};
|
||||
|
||||
/* Xifan TANG: synthesizable verilog dumping */
|
||||
|
@ -1208,15 +1222,28 @@ typedef struct s_syn_verilog_opts t_syn_verilog_opts;
|
|||
struct s_syn_verilog_opts {
|
||||
boolean dump_syn_verilog;
|
||||
char* syn_verilog_dump_dir;
|
||||
boolean print_top_tb;
|
||||
boolean print_top_auto_tb;
|
||||
char* verilog_benchmark_file;
|
||||
boolean print_input_blif_tb;
|
||||
boolean tb_serial_config_mode;
|
||||
boolean print_top_testbench;
|
||||
boolean print_input_blif_testbench;
|
||||
boolean print_formal_verification_top_netlist;
|
||||
boolean include_timing;
|
||||
boolean init_sim;
|
||||
boolean include_signal_init;
|
||||
boolean include_icarus_simulator;
|
||||
boolean print_modelsim_autodeck;
|
||||
char* modelsim_ini_path;
|
||||
char* report_timing_path;
|
||||
boolean print_user_defined_template;
|
||||
boolean print_autocheck_top_testbench;
|
||||
char* reference_verilog_benchmark_file;
|
||||
boolean print_report_timing_tcl;
|
||||
boolean print_sdc_pnr;
|
||||
boolean print_sdc_analysis;
|
||||
};
|
||||
|
||||
/* Xifan TANG: bitstream generator */
|
||||
typedef struct s_bitstream_gen_opts t_bitstream_gen_opts;
|
||||
struct s_bitstream_gen_opts {
|
||||
boolean gen_bitstream;
|
||||
char* bitstream_output_file;
|
||||
};
|
||||
|
||||
typedef struct s_fpga_spice_opts t_fpga_spice_opts;
|
||||
|
@ -1226,6 +1253,7 @@ struct s_fpga_spice_opts {
|
|||
boolean rename_illegal_port; /* Rename illegal port names that is not compatible with verilog/SPICE syntax */
|
||||
t_spice_opts SpiceOpts; /* Xifan TANG: SPICE Support*/
|
||||
t_syn_verilog_opts SynVerilogOpts; /* Xifan TANG: Synthesizable verilog dumping*/
|
||||
t_bitstream_gen_opts BitstreamGenOpts; /* Xifan Bitsteam Generator */
|
||||
|
||||
/* Signal Density */
|
||||
float signal_density_weight;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
ctags -R . ../../libarchfpga/include/*.[ch] ../../libarchfpga/fpga_spice_include/*.[ch] ../../libarchfpga/*.[ch]
|
||||
rm tags
|
||||
ctags -R shell_main.c main.c ./* ../../libarchfpga/include/*.[ch] ../../libarchfpga/fpga_spice_include/*.[ch] ../../libarchfpga/*.[ch] ../../pcre/SRC/*.[ch]
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
|
||||
void vpr_fpga_spice_tool_suites(t_vpr_setup vpr_setup,
|
||||
t_arch Arch);
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
void encode_decoder_addr(int input,
|
||||
int decoder_size, char* addr);
|
||||
|
||||
void dump_fpga_spice_bitstream(char* bitstream_file_name,
|
||||
char* circuit_name,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +0,0 @@
|
|||
void vpr_print_spice_netlists(t_vpr_setup vpr_setup,
|
||||
t_arch Arch,
|
||||
char* circuit_name);
|
|
@ -1,860 +0,0 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph_util.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph2.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "spice_globals.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "spice_utils.h"
|
||||
#include "spice_mux.h"
|
||||
#include "spice_pbtypes.h"
|
||||
#include "spice_subckt.h"
|
||||
|
||||
/* local global variables */
|
||||
static int tb_num_hardlogic = 0;
|
||||
static int testbench_load_cnt = 0;
|
||||
static int upbound_sim_num_clock_cycles = 2;
|
||||
static int max_sim_num_clock_cycles = 2;
|
||||
static int auto_select_max_sim_num_clock_cycles = TRUE;
|
||||
|
||||
/* Subroutines in this source file*/
|
||||
/* Initialize the global parameters in this source file */
|
||||
static
|
||||
void init_spice_hardlogic_testbench_globals(t_spice spice) {
|
||||
tb_num_hardlogic = 0;
|
||||
auto_select_max_sim_num_clock_cycles = spice.spice_params.meas_params.auto_select_sim_num_clk_cycle;
|
||||
upbound_sim_num_clock_cycles = spice.spice_params.meas_params.sim_num_clock_cycle + 1;
|
||||
if (FALSE == auto_select_max_sim_num_clock_cycles) {
|
||||
max_sim_num_clock_cycles = spice.spice_params.meas_params.sim_num_clock_cycle + 1;
|
||||
} else {
|
||||
max_sim_num_clock_cycles = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print Common global ports in the testbench */
|
||||
static
|
||||
void fprint_spice_hardlogic_testbench_global_ports(FILE* fp, int grid_x, int grid_y,
|
||||
int num_clock,
|
||||
t_spice spice) {
|
||||
/* int i; */
|
||||
/* A valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File Handler!\n",__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* Global nodes: Vdd for SRAMs, Logic Blocks(Include IO), Switch Boxes, Connection Boxes */
|
||||
/* Print generic global ports*/
|
||||
fprint_spice_generic_testbench_global_ports(fp,
|
||||
sram_spice_orgz_info,
|
||||
global_ports_head);
|
||||
/* VDD Load port name */
|
||||
fprintf(fp, ".global %s\n",
|
||||
spice_tb_global_vdd_load_port_name);
|
||||
|
||||
/*Global Vdds for FFs: TODO: TO BE REMOVED */
|
||||
fprint_grid_global_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_FF, spice);
|
||||
|
||||
/*Global Vdds for hardlogic */
|
||||
fprint_grid_global_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_HARDLOGIC, spice);
|
||||
|
||||
/*Global Vdds for IOPADs (TODO: TO BE MOVED TO IO_TB SOURCE FILE */
|
||||
fprint_grid_global_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_IOPAD, spice);
|
||||
|
||||
/* Global VDDs for SRAMs of IOPADs */
|
||||
fprintf(fp, ".global %s\n",
|
||||
spice_tb_global_vdd_io_sram_port_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dump the subckt of a hardlogic and also the input stimuli */
|
||||
void fprint_spice_hardlogic_testbench_one_hardlogic(FILE* fp,
|
||||
char* subckt_name,
|
||||
t_spice_model* hardlogic_spice_model) {
|
||||
int iport, ipin;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
|
||||
int num_inout_port = 0;
|
||||
t_spice_model_port** inout_ports = NULL;
|
||||
|
||||
int num_clk_port = 0;
|
||||
t_spice_model_port** clk_ports = NULL;
|
||||
|
||||
/* A valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File Handler!\n",__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check */
|
||||
assert(NULL != hardlogic_spice_model);
|
||||
|
||||
/* identify the type of spice model */
|
||||
/* Call defined subckt */
|
||||
fprintf(fp, "Xhardlogic_%s[%d] \n",
|
||||
hardlogic_spice_model->prefix,
|
||||
hardlogic_spice_model->tb_cnt);
|
||||
|
||||
/* Sequence in dumping ports:
|
||||
* 1. Global ports
|
||||
* 2. Input ports
|
||||
* 3. Output ports
|
||||
* 4. Inout ports
|
||||
* 5. Configuration ports
|
||||
* 6. VDD and GND ports
|
||||
*/
|
||||
|
||||
/* 1. Global ports */
|
||||
if (0 < rec_fprint_spice_model_global_ports(fp, hardlogic_spice_model, FALSE)) {
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
|
||||
/* 2. Input ports (TODO: check the number of inputs matches the spice model definition) */
|
||||
/* Find pb_type input ports */
|
||||
input_ports = find_spice_model_ports(hardlogic_spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
for (iport = 0; iport < num_input_port; iport++) {
|
||||
for (ipin = 0; ipin < input_ports[iport]->size; ipin++) {
|
||||
fprintf(fp, "hardlogic_%s[%d]->%s[%d] ",
|
||||
hardlogic_spice_model->prefix,
|
||||
hardlogic_spice_model->tb_cnt,
|
||||
input_ports[iport]->prefix, ipin);
|
||||
}
|
||||
}
|
||||
if (NULL != input_ports) {
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
|
||||
/* 3. Output ports */
|
||||
/* Find pb_type output ports */
|
||||
output_ports = find_spice_model_ports(hardlogic_spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
for (iport = 0; iport < num_output_port; iport++) {
|
||||
for (ipin = 0; ipin < output_ports[iport]->size; ipin++) {
|
||||
fprintf(fp, "hardlogic_%s[%d]->%s[%d] ",
|
||||
hardlogic_spice_model->prefix,
|
||||
hardlogic_spice_model->tb_cnt,
|
||||
output_ports[iport]->prefix, ipin);
|
||||
}
|
||||
}
|
||||
if (NULL != output_ports) {
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
|
||||
/* 4. Inout ports */
|
||||
/* INOUT ports */
|
||||
/* Find pb_type inout ports */
|
||||
inout_ports = find_spice_model_ports(hardlogic_spice_model, SPICE_MODEL_PORT_INOUT, &num_inout_port, TRUE);
|
||||
for (iport = 0; iport < num_inout_port; iport++) {
|
||||
for (ipin = 0; ipin < inout_ports[iport]->size; ipin++) {
|
||||
fprintf(fp, "hardlogic_%s[%d]->%s[%d] ",
|
||||
hardlogic_spice_model->prefix,
|
||||
hardlogic_spice_model->tb_cnt,
|
||||
inout_ports[iport]->prefix, ipin);
|
||||
}
|
||||
}
|
||||
if (NULL != inout_ports) {
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
|
||||
/* Clocks */
|
||||
/* Identify if the clock port is a global signal */
|
||||
/* Find pb_type clock ports */
|
||||
clk_ports = find_spice_model_ports(hardlogic_spice_model, SPICE_MODEL_PORT_CLOCK, &num_clk_port, TRUE);
|
||||
for (iport = 0; iport < num_clk_port; iport++) {
|
||||
for (ipin = 0; ipin < clk_ports[iport]->size; ipin++) {
|
||||
fprintf(fp, "hardlogic_%s[%d]->%s[%d] ",
|
||||
hardlogic_spice_model->prefix,
|
||||
hardlogic_spice_model->tb_cnt,
|
||||
clk_ports[iport]->prefix, ipin);
|
||||
}
|
||||
}
|
||||
if (NULL != clk_ports) {
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
|
||||
/* 5. Configuration ports */
|
||||
/* Generate SRAMs? */
|
||||
|
||||
/* 6. VDD and GND ports */
|
||||
fprintf(fp, "%s_%s[%d] %s ",
|
||||
spice_tb_global_vdd_port_name, hardlogic_spice_model->prefix, hardlogic_spice_model->tb_cnt,
|
||||
spice_tb_global_gnd_port_name);
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "+ ");
|
||||
|
||||
/* Call the name of subckt */
|
||||
fprintf(fp, "%s\n", hardlogic_spice_model->name);
|
||||
|
||||
/* Free */
|
||||
my_free(input_ports);
|
||||
my_free(output_ports);
|
||||
my_free(inout_ports);
|
||||
my_free(clk_ports);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_hardlogic_testbench_one_pb_graph_node_hardlogic(FILE* fp,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
char* prefix,
|
||||
int x, int y,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
int logical_block_index = OPEN;
|
||||
t_spice_model* pb_spice_model = NULL;
|
||||
t_pb_type* cur_pb_type = NULL;
|
||||
int iport, ipin;
|
||||
|
||||
/* For pb_spice_model */
|
||||
int num_input_port;
|
||||
t_spice_model_port** input_ports;
|
||||
int num_output_port;
|
||||
t_spice_model_port** output_ports;
|
||||
|
||||
/* Two-dimension arrays, corresponding to the port map [port_id][pin_id] */
|
||||
float** input_density = NULL;
|
||||
float** input_probability = NULL;
|
||||
int** input_init_value = NULL;
|
||||
int** input_net_num = NULL;
|
||||
|
||||
char* outport_name = NULL;
|
||||
t_rr_node* local_rr_graph = NULL;
|
||||
float average_density = 0.;
|
||||
int avg_density_cnt = 0;
|
||||
int num_sim_clock_cycles = 0;
|
||||
|
||||
assert(NULL != cur_pb_graph_node);
|
||||
assert(NULL != prefix);
|
||||
|
||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
||||
assert(NULL != cur_pb_type);
|
||||
pb_spice_model = cur_pb_type->spice_model;
|
||||
|
||||
/* Just a double check*/
|
||||
if ((SPICE_MODEL_HARDLOGIC != pb_spice_model->type)
|
||||
&&(SPICE_MODEL_FF != pb_spice_model->type)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(File:%s, [LINE%d]) Type of SPICE models should be either Flip-Flop or Hard Logic!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Try to find the mapped logic block index */
|
||||
logical_block_index = find_grid_mapped_logical_block(x, y,
|
||||
pb_spice_model, prefix);
|
||||
|
||||
/* UNCOMMENT THIS, IF YOU DO NOT WANT SIMULATE THE IDLE ELEMENTS
|
||||
if (OPEN == logical_block_index) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Call the subckt and give stimulates, measurements */
|
||||
if (OPEN != logical_block_index) {
|
||||
fprintf(fp,"***** Hardlogic[%d]: logical_block_index[%d], gvdd_index[%d]*****\n",
|
||||
pb_spice_model->cnt, logical_block_index, logical_block[logical_block_index].mapped_spice_model_index);
|
||||
} else {
|
||||
fprintf(fp,"***** Hardlogic[%d]: logical_block_index[%d], gvdd_index[%d]*****\n",
|
||||
pb_spice_model->cnt, -1, -1);
|
||||
}
|
||||
|
||||
/* Now, we print the SPICE subckt of a hard logic */
|
||||
fprint_spice_hardlogic_testbench_one_hardlogic(fp, prefix, pb_spice_model);
|
||||
|
||||
/* Malloc */
|
||||
/* First dimension */
|
||||
input_density = (float**)my_malloc(sizeof(float*) * cur_pb_graph_node->num_input_ports);
|
||||
input_probability = (float**)my_malloc(sizeof(float*) * cur_pb_graph_node->num_input_ports);
|
||||
input_init_value = (int**)my_malloc(sizeof(int*) * cur_pb_graph_node->num_input_ports);
|
||||
input_net_num = (int**)my_malloc(sizeof(int*) * cur_pb_graph_node->num_input_ports);
|
||||
/* Second dimension */
|
||||
for (iport = 0; iport < cur_pb_graph_node->num_input_ports; iport++) {
|
||||
input_density[iport] = (float*)my_malloc(sizeof(float) * cur_pb_graph_node->num_input_pins[iport]);
|
||||
input_probability[iport] = (float*)my_malloc(sizeof(float) * cur_pb_graph_node->num_input_pins[iport]);
|
||||
input_init_value[iport] = (int*)my_malloc(sizeof(int) * cur_pb_graph_node->num_input_pins[iport]);
|
||||
input_net_num[iport] = (int*)my_malloc(sizeof(int) * cur_pb_graph_node->num_input_pins[iport]);
|
||||
}
|
||||
|
||||
/* Get activity information */
|
||||
for (iport = 0; iport < cur_pb_graph_node->num_input_ports; iport++) {
|
||||
for (ipin = 0; ipin < cur_pb_graph_node->num_input_pins[iport]; ipin++) {
|
||||
/* if we find a mapped logic block */
|
||||
if (OPEN != logical_block_index) {
|
||||
local_rr_graph = logical_block[logical_block_index].pb->parent_pb->rr_graph;
|
||||
} else {
|
||||
local_rr_graph = NULL;
|
||||
}
|
||||
input_net_num[iport][ipin] = pb_pin_net_num(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
input_density[iport][ipin] = pb_pin_density(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
input_probability[iport][ipin] = pb_pin_probability(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
input_init_value[iport][ipin] = pb_pin_init_value(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Add Input stimulates */
|
||||
/* Get the input port list of spice model */
|
||||
input_ports = find_spice_model_ports(pb_spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
/* Check if the port map of current pb_graph_node matches that of the spice model !!!*/
|
||||
assert(num_input_port == cur_pb_graph_node->num_input_ports);
|
||||
for (iport = 0; iport < num_input_port; iport++) {
|
||||
assert(input_ports[iport]->size == cur_pb_graph_node->num_input_pins[iport]);
|
||||
for (ipin = 0; ipin < input_ports[iport]->size; ipin++) {
|
||||
/* Check the port size should match!*/
|
||||
fprintf(fp, "Vhardlogic_%s[%d]->%s[%d] hardlogic_%s[%d]->%s[%d] 0 \n",
|
||||
pb_spice_model->prefix,
|
||||
pb_spice_model->tb_cnt,
|
||||
cur_pb_graph_node->input_pins[iport]->port->name,
|
||||
ipin,
|
||||
pb_spice_model->prefix,
|
||||
pb_spice_model->tb_cnt,
|
||||
input_ports[iport]->prefix,
|
||||
ipin);
|
||||
fprint_voltage_pulse_params(fp, input_init_value[iport][ipin], input_density[iport][ipin], input_probability[iport][ipin]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add loads: Recursively */
|
||||
/* Get the output port list of spice model */
|
||||
output_ports = find_spice_model_ports(pb_spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
for (iport = 0; iport < num_output_port; iport++) {
|
||||
for (ipin = 0; ipin < output_ports[iport]->size; ipin++) {
|
||||
outport_name = (char*)my_malloc(sizeof(char)*( 10 +
|
||||
+ strlen(pb_spice_model->prefix) + 1
|
||||
+ strlen(my_itoa(pb_spice_model->tb_cnt))
|
||||
+ 3 + strlen(output_ports[iport]->prefix) + 1
|
||||
+ strlen(my_itoa(ipin)) + 2 ));
|
||||
sprintf(outport_name, "hardlogic_%s[%d]->%s[%d]",
|
||||
pb_spice_model->prefix,
|
||||
pb_spice_model->tb_cnt,
|
||||
output_ports[iport]->prefix,
|
||||
ipin);
|
||||
if (TRUE == run_testbench_load_extraction) { /* Additional switch, default on! */
|
||||
if (OPEN != logical_block_index) {
|
||||
fprint_spice_testbench_pb_graph_pin_inv_loads_rec(fp, &testbench_load_cnt,
|
||||
x, y,
|
||||
&(cur_pb_graph_node->output_pins[0][0]),
|
||||
logical_block[logical_block_index].pb,
|
||||
outport_name,
|
||||
FALSE,
|
||||
LL_rr_node_indices);
|
||||
} else {
|
||||
fprint_spice_testbench_pb_graph_pin_inv_loads_rec(fp, &testbench_load_cnt,
|
||||
x, y,
|
||||
&(cur_pb_graph_node->output_pins[0][0]),
|
||||
NULL,
|
||||
outport_name,
|
||||
FALSE,
|
||||
LL_rr_node_indices);
|
||||
}
|
||||
}
|
||||
/* Free outport_name in each iteration */
|
||||
my_free(outport_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate average density of this hardlogic */
|
||||
average_density = 0.;
|
||||
avg_density_cnt = 0;
|
||||
for (iport = 0; iport < cur_pb_graph_node->num_input_ports; iport++) {
|
||||
for (ipin = 0; ipin < cur_pb_graph_node->num_input_pins[iport]; ipin++) {
|
||||
assert(!(0 > input_density[iport][ipin]));
|
||||
if (0. < input_density[iport][ipin]) {
|
||||
average_density += input_density[iport][ipin];
|
||||
avg_density_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Calculate the num_sim_clock_cycle for this MUX, update global max_sim_clock_cycle in this testbench */
|
||||
if (0 < avg_density_cnt) {
|
||||
average_density = average_density/avg_density_cnt;
|
||||
} else {
|
||||
assert(0 == avg_density_cnt);
|
||||
average_density = 0.;
|
||||
}
|
||||
if (0. == average_density) {
|
||||
num_sim_clock_cycles = 2;
|
||||
} else {
|
||||
assert(0. < average_density);
|
||||
num_sim_clock_cycles = (int)(1/average_density) + 1;
|
||||
}
|
||||
if (TRUE == auto_select_max_sim_num_clock_cycles) {
|
||||
/* for idle blocks, 2 clock cycle is well enough... */
|
||||
if (2 < num_sim_clock_cycles) {
|
||||
num_sim_clock_cycles = upbound_sim_num_clock_cycles;
|
||||
} else {
|
||||
num_sim_clock_cycles = 2;
|
||||
}
|
||||
if (max_sim_num_clock_cycles < num_sim_clock_cycles) {
|
||||
max_sim_num_clock_cycles = num_sim_clock_cycles;
|
||||
}
|
||||
} else {
|
||||
num_sim_clock_cycles = max_sim_num_clock_cycles;
|
||||
}
|
||||
|
||||
/* Mark temporary used */
|
||||
if (OPEN != logical_block_index) {
|
||||
logical_block[logical_block_index].temp_used = 1;
|
||||
}
|
||||
|
||||
/* Increment the counter of the hardlogic spice model */
|
||||
pb_spice_model->tb_cnt++;
|
||||
tb_num_hardlogic++;
|
||||
|
||||
/* Free */
|
||||
for (iport = 0; iport < cur_pb_graph_node->num_input_ports; iport++) {
|
||||
my_free(input_net_num[iport]);
|
||||
my_free(input_init_value[iport]);
|
||||
my_free(input_density[iport]);
|
||||
my_free(input_probability[iport]);
|
||||
}
|
||||
my_free(input_net_num);
|
||||
my_free(input_init_value);
|
||||
my_free(input_density);
|
||||
my_free(input_probability);
|
||||
my_free(input_ports);
|
||||
my_free(output_ports);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_hardlogic_testbench_rec_pb_graph_node_hardlogics(FILE* fp,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
char* prefix,
|
||||
int x, int y,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
char* formatted_prefix = format_spice_node_prefix(prefix);
|
||||
int ipb, jpb, mode_index;
|
||||
t_pb_type* cur_pb_type = NULL;
|
||||
char* rec_prefix = NULL;
|
||||
|
||||
assert(NULL != cur_pb_graph_node);
|
||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
||||
assert(NULL != cur_pb_type);
|
||||
/* Until we reach a FF */
|
||||
if (NULL != cur_pb_type->spice_model) {
|
||||
if ((SPICE_MODEL_FF != cur_pb_type->spice_model->type)
|
||||
&&(SPICE_MODEL_HARDLOGIC != cur_pb_type->spice_model->type)) {
|
||||
return;
|
||||
}
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb_graph_node->placement_index))
|
||||
+ 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]",
|
||||
formatted_prefix, cur_pb_type->name, cur_pb_graph_node->placement_index);
|
||||
/* Print a hardlogic tb: call spice_model, stimulates */
|
||||
fprint_spice_hardlogic_testbench_one_pb_graph_node_hardlogic(fp, cur_pb_graph_node, rec_prefix, x, y, LL_rr_node_indices);
|
||||
my_free(rec_prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go recursively ... */
|
||||
mode_index = find_pb_type_idle_mode_index(*(cur_pb_type));
|
||||
for (ipb = 0; ipb < cur_pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
||||
for (jpb = 0; jpb < cur_pb_type->modes[mode_index].pb_type_children[ipb].num_pb; jpb++) {
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb_graph_node->placement_index)) + 7
|
||||
+ strlen(cur_pb_type->modes[mode_index].name) + 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]_mode[%s]",
|
||||
formatted_prefix, cur_pb_type->name, cur_pb_graph_node->placement_index,
|
||||
cur_pb_type->modes[mode_index].name);
|
||||
/* Go recursively */
|
||||
fprint_spice_hardlogic_testbench_rec_pb_graph_node_hardlogics(fp, &(cur_pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]),
|
||||
rec_prefix, x, y, LL_rr_node_indices);
|
||||
my_free(rec_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_hardlogic_testbench_rec_pb_hardlogics(FILE* fp,
|
||||
t_pb* cur_pb, char* prefix,
|
||||
int x, int y,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
char* formatted_prefix = format_spice_node_prefix(prefix);
|
||||
int ipb, jpb;
|
||||
int mode_index;
|
||||
char* rec_prefix = NULL;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Check */
|
||||
assert(NULL != cur_pb);
|
||||
|
||||
/* If we touch the leaf, there is no need print interc*/
|
||||
if (NULL != cur_pb->pb_graph_node->pb_type->spice_model) {
|
||||
if ((SPICE_MODEL_HARDLOGIC != cur_pb->pb_graph_node->pb_type->spice_model->type)
|
||||
&&(SPICE_MODEL_FF != cur_pb->pb_graph_node->pb_type->spice_model->type)) {
|
||||
return;
|
||||
}
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb->pb_graph_node->pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb->pb_graph_node->placement_index))
|
||||
+ 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]",
|
||||
formatted_prefix, cur_pb->pb_graph_node->pb_type->name, cur_pb->pb_graph_node->placement_index);
|
||||
/* Print a lut tb: call spice_model, stimulates */
|
||||
fprint_spice_hardlogic_testbench_one_pb_graph_node_hardlogic(fp, cur_pb->pb_graph_node, rec_prefix, x, y, LL_rr_node_indices);
|
||||
my_free(rec_prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go recursively ... */
|
||||
mode_index = cur_pb->mode;
|
||||
if (!(0 < cur_pb->pb_graph_node->pb_type->num_modes)) {
|
||||
return;
|
||||
}
|
||||
for (ipb = 0; ipb < cur_pb->pb_graph_node->pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
||||
for (jpb = 0; jpb < cur_pb->pb_graph_node->pb_type->modes[mode_index].pb_type_children[ipb].num_pb; jpb++) {
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb->pb_graph_node->pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb->pb_graph_node->placement_index)) + 7
|
||||
+ strlen(cur_pb->pb_graph_node->pb_type->modes[mode_index].name) + 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]_mode[%s]",
|
||||
formatted_prefix, cur_pb->pb_graph_node->pb_type->name,
|
||||
cur_pb->pb_graph_node->placement_index,
|
||||
cur_pb->pb_graph_node->pb_type->modes[mode_index].name);
|
||||
/* Refer to pack/output_clustering.c [LINE 392] */
|
||||
if ((NULL != cur_pb->child_pbs[ipb])&&(NULL != cur_pb->child_pbs[ipb][jpb].name)) {
|
||||
fprint_spice_hardlogic_testbench_rec_pb_hardlogics(fp, &(cur_pb->child_pbs[ipb][jpb]), rec_prefix, x, y, LL_rr_node_indices);
|
||||
} else {
|
||||
/* Then we go on */
|
||||
fprint_spice_hardlogic_testbench_rec_pb_graph_node_hardlogics(fp, cur_pb->child_pbs[ipb][jpb].pb_graph_node,
|
||||
rec_prefix, x, y, LL_rr_node_indices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_hardlogic_testbench_call_one_grid_defined_hardlogics(FILE* fp,
|
||||
int ix, int iy,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
int iblk;
|
||||
char* prefix = NULL;
|
||||
|
||||
if ((NULL == grid[ix][iy].type)
|
||||
||(EMPTY_TYPE == grid[ix][iy].type)
|
||||
||(0 != grid[ix][iy].offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (iblk = 0; iblk < grid[ix][iy].usage; iblk++) {
|
||||
prefix = (char*)my_malloc(sizeof(char)* (5
|
||||
+ strlen(my_itoa(block[grid[ix][iy].blocks[iblk]].x))
|
||||
+ 2 + strlen(my_itoa(block[grid[ix][iy].blocks[iblk]].y))
|
||||
+ 3 ));
|
||||
sprintf(prefix, "grid[%d][%d]_",
|
||||
block[grid[ix][iy].blocks[iblk]].x,
|
||||
block[grid[ix][iy].blocks[iblk]].y);
|
||||
/* Only for mapped block */
|
||||
assert(NULL != block[grid[ix][iy].blocks[iblk]].pb);
|
||||
/* Mark the temporary net_num for the type pins*/
|
||||
mark_one_pb_parasitic_nets(block[grid[ix][iy].blocks[iblk]].pb);
|
||||
/* Go into the hierachy and dump hardlogics */
|
||||
fprint_spice_hardlogic_testbench_rec_pb_hardlogics(fp, block[grid[ix][iy].blocks[iblk]].pb, prefix, ix, iy, LL_rr_node_indices);
|
||||
/* Free */
|
||||
my_free(prefix);
|
||||
}
|
||||
/* Bypass unused blocks */
|
||||
for (iblk = grid[ix][iy].usage; iblk < grid[ix][iy].type->capacity; iblk++) {
|
||||
prefix = (char*)my_malloc(sizeof(char)* (5 + strlen(my_itoa(ix))
|
||||
+ 2 + strlen(my_itoa(iy)) + 3 ));
|
||||
sprintf(prefix, "grid[%d][%d]_", ix, iy);
|
||||
assert(NULL != grid[ix][iy].type->pb_graph_head);
|
||||
/* Mark the temporary net_num for the type pins*/
|
||||
mark_grid_type_pb_graph_node_pins_temp_net_num(ix, iy);
|
||||
/* Go into the hierachy and dump hardlogics */
|
||||
fprint_spice_hardlogic_testbench_rec_pb_graph_node_hardlogics(fp, grid[ix][iy].type->pb_graph_head, prefix, ix, iy, LL_rr_node_indices);
|
||||
/* Free */
|
||||
my_free(prefix);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_hardlogic_testbench_call_defined_hardlogics(FILE* fp,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
int ix, iy;
|
||||
|
||||
for (ix = 1; ix < (nx + 1); ix++) {
|
||||
for (iy = 1; iy < (ny + 1); iy++) {
|
||||
fprint_spice_hardlogic_testbench_call_one_grid_defined_hardlogics(fp, ix, iy, LL_rr_node_indices);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void fprint_spice_hardlogic_testbench_stimulations(FILE* fp, int grid_x, int grid_y,
|
||||
int num_clocks,
|
||||
t_spice spice,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
/* Print generic stimuli */
|
||||
fprint_spice_testbench_generic_global_ports_stimuli(fp, num_clocks);
|
||||
|
||||
/* Generate global ports stimuli */
|
||||
fprint_spice_testbench_global_ports_stimuli(fp, global_ports_head);
|
||||
|
||||
/* SRAM ports */
|
||||
fprintf(fp, "***** Global Inputs for SRAMs *****\n");
|
||||
fprint_spice_testbench_global_sram_inport_stimuli(fp, sram_spice_orgz_info);
|
||||
|
||||
fprintf(fp, "***** Global VDD for SRAMs *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_sram_port_name,
|
||||
"vsp");
|
||||
|
||||
fprintf(fp, "***** Global VDD for load inverters *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_load_port_name,
|
||||
"vsp");
|
||||
/*
|
||||
fprintf(fp, "***** Global VDD for IOPADs *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_io_port_name,
|
||||
"vsp");
|
||||
|
||||
fprintf(fp, "***** Global VDD for IOPAD SRAMs *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_io_sram_port_name,
|
||||
"vsp");
|
||||
*/
|
||||
|
||||
/* Every LUT use an independent Voltage source */
|
||||
fprintf(fp, "***** Global VDD for FFs *****\n");
|
||||
fprint_grid_splited_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_FF, spice);
|
||||
fprintf(fp, "***** Global VDD for Hardlogics *****\n");
|
||||
fprint_grid_splited_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_HARDLOGIC, spice);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_hardlogic_testbench_measurements(FILE* fp, int grid_x, int grid_y,
|
||||
t_spice spice,
|
||||
boolean leakage_only) {
|
||||
|
||||
/* int i; */
|
||||
/* First cycle reserved for measuring leakage */
|
||||
int num_clock_cycle = max_sim_num_clock_cycles;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprint_spice_netlist_transient_setting(fp, spice, num_clock_cycle, leakage_only);
|
||||
fprint_spice_netlist_generic_measurements(fp, spice.spice_params.mc_params, spice.num_spice_model, spice.spice_models);
|
||||
|
||||
/* TODO: Measure the delay of each mapped net and logical block */
|
||||
|
||||
/* Measure the power */
|
||||
/* Leakage ( the first cycle is reserved for leakage measurement) */
|
||||
/* Leakage power of FFs*/
|
||||
fprint_measure_grid_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_FF, SPICE_MEASURE_LEAKAGE_POWER, num_clock_cycle, spice, leakage_only);
|
||||
/* Leakage power of Hardlogic */
|
||||
fprint_measure_grid_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_HARDLOGIC, SPICE_MEASURE_LEAKAGE_POWER, num_clock_cycle, spice, leakage_only);
|
||||
|
||||
if (TRUE == leakage_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dynamic power */
|
||||
/* Dynamic power of FFs */
|
||||
fprint_measure_grid_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_FF, SPICE_MEASURE_DYNAMIC_POWER, num_clock_cycle, spice, leakage_only);
|
||||
|
||||
/* Dynamic power of Hardlogics */
|
||||
fprint_measure_grid_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_HARDLOGIC, SPICE_MEASURE_DYNAMIC_POWER, num_clock_cycle, spice, leakage_only);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Top-level function in this source file */
|
||||
int fprint_spice_one_hardlogic_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* hardlogic_testbench_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_arch arch,
|
||||
int grid_x, int grid_y,
|
||||
boolean leakage_only) {
|
||||
FILE* fp = NULL;
|
||||
char* title = my_strcat("FPGA Hard Logic Testbench for Design: ", circuit_name);
|
||||
char* hardlogic_testbench_file_path = my_strcat(formatted_spice_dir, hardlogic_testbench_name);
|
||||
int used;
|
||||
|
||||
/* Check if the path exists*/
|
||||
fp = fopen(hardlogic_testbench_file_path,"w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create DFF Testbench SPICE netlist %s!",__FILE__, __LINE__,
|
||||
hardlogic_testbench_file_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Reset tb_cnt for all the spice models */
|
||||
init_spice_models_grid_tb_cnt(arch.spice->num_spice_model, arch.spice->spice_models, grid_x, grid_y);
|
||||
|
||||
/* vpr_printf(TIO_MESSAGE_INFO, "Writing DFF Testbench for %s...\n", circuit_name); */
|
||||
testbench_load_cnt = 0;
|
||||
|
||||
/* Print the title */
|
||||
fprint_spice_head(fp, title);
|
||||
my_free(title);
|
||||
|
||||
/* print technology library and design parameters*/
|
||||
/* fprint_tech_lib(fp, arch.spice->tech_lib);*/
|
||||
|
||||
/* Include parameter header files */
|
||||
fprint_spice_include_param_headers(fp, include_dir_path);
|
||||
|
||||
/* Include Key subckts */
|
||||
fprint_spice_include_key_subckts(fp, subckt_dir_path);
|
||||
|
||||
/* Include user-defined sub-circuit netlist */
|
||||
init_include_user_defined_netlists(*(arch.spice));
|
||||
fprint_include_user_defined_netlists(fp, *(arch.spice));
|
||||
|
||||
/* Print simulation temperature and other options for SPICE */
|
||||
fprint_spice_options(fp, arch.spice->spice_params);
|
||||
|
||||
/* Global nodes: Vdd for SRAMs, Logic Blocks(Include IO), Switch Boxes, Connection Boxes */
|
||||
fprint_spice_hardlogic_testbench_global_ports(fp, grid_x, grid_y, num_clock, (*arch.spice));
|
||||
|
||||
/* Quote defined Logic blocks subckts (Grids) */
|
||||
init_spice_hardlogic_testbench_globals(*(arch.spice));
|
||||
init_logical_block_spice_model_type_temp_used(arch.spice->num_spice_model, arch.spice->spice_models, SPICE_MODEL_FF);
|
||||
init_logical_block_spice_model_type_temp_used(arch.spice->num_spice_model, arch.spice->spice_models, SPICE_MODEL_HARDLOGIC);
|
||||
|
||||
/* Now start our job formally: dump hard logic circuit one by one */
|
||||
fprint_spice_hardlogic_testbench_call_one_grid_defined_hardlogics(fp, grid_x, grid_y, LL_rr_node_indices);
|
||||
|
||||
/* Back-anotate activity information to each routing resource node
|
||||
* (We should have activity of each Grid port)
|
||||
*/
|
||||
|
||||
/* Check if the all hardlogic located in this grid have been printed */
|
||||
check_spice_models_grid_tb_cnt(arch.spice->num_spice_model, arch.spice->spice_models, grid_x, grid_y, SPICE_MODEL_FF);
|
||||
check_spice_models_grid_tb_cnt(arch.spice->num_spice_model, arch.spice->spice_models, grid_x, grid_y, SPICE_MODEL_HARDLOGIC);
|
||||
|
||||
/* Add stimulations */
|
||||
fprint_spice_hardlogic_testbench_stimulations(fp, grid_x, grid_y, num_clock, (*arch.spice), LL_rr_node_indices);
|
||||
|
||||
/* Add measurements */
|
||||
fprint_spice_hardlogic_testbench_measurements(fp, grid_x, grid_y, (*arch.spice), leakage_only);
|
||||
|
||||
/* SPICE ends*/
|
||||
fprintf(fp, ".end\n");
|
||||
|
||||
/* Close the file*/
|
||||
fclose(fp);
|
||||
|
||||
if (0 < tb_num_hardlogic) {
|
||||
/*
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Grid[%d][%d] SPICE Hard Logic Testbench for %s...\n",
|
||||
grid_x, grid_y, circuit_name);
|
||||
*/
|
||||
/* Push the testbench to the linked list */
|
||||
tb_head = add_one_spice_tb_info_to_llist(tb_head, hardlogic_testbench_file_path,
|
||||
max_sim_num_clock_cycles);
|
||||
used = 1;
|
||||
} else {
|
||||
/* Remove the file generated */
|
||||
my_remove_file(hardlogic_testbench_file_path);
|
||||
used = 0;
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
/* Top-level function in this source file */
|
||||
void spice_print_hardlogic_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_arch arch,
|
||||
boolean leakage_only) {
|
||||
char* hardlogic_testbench_name = NULL;
|
||||
int ix, iy;
|
||||
int cnt = 0;
|
||||
int used = 0;
|
||||
|
||||
for (ix = 1; ix < (nx+1); ix++) {
|
||||
for (iy = 1; iy < (ny+1); iy++) {
|
||||
/* Name the testbench */
|
||||
hardlogic_testbench_name = (char*)my_malloc(sizeof(char)*( strlen(circuit_name)
|
||||
+ 6 + strlen(my_itoa(ix)) + 1
|
||||
+ strlen(my_itoa(iy)) + 1
|
||||
+ strlen(spice_hardlogic_testbench_postfix) + 1 ));
|
||||
sprintf(hardlogic_testbench_name, "%s_grid%d_%d%s",
|
||||
circuit_name, ix, iy, spice_hardlogic_testbench_postfix);
|
||||
/* Start building one testbench */
|
||||
used = fprint_spice_one_hardlogic_testbench(formatted_spice_dir, circuit_name, hardlogic_testbench_name,
|
||||
include_dir_path, subckt_dir_path, LL_rr_node_indices,
|
||||
num_clock, arch, ix, iy,
|
||||
leakage_only);
|
||||
if (1 == used) {
|
||||
cnt += used;
|
||||
}
|
||||
/* free */
|
||||
my_free(hardlogic_testbench_name);
|
||||
}
|
||||
}
|
||||
/* Update the global counter */
|
||||
num_used_hardlogic_tb = cnt;
|
||||
vpr_printf(TIO_MESSAGE_INFO,"No. of generated hard logic testbench = %d\n", num_used_hardlogic_tb);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
void spice_print_hardlogic_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_arch arch,
|
||||
boolean leakage_only);
|
|
@ -1,387 +0,0 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph_swseg.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "spice_globals.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "spice_utils.h"
|
||||
#include "spice_mux.h"
|
||||
#include "spice_pbtypes.h"
|
||||
#include "spice_lut.h"
|
||||
|
||||
|
||||
/***** Subroutines *****/
|
||||
|
||||
void fprint_spice_lut_subckt(FILE* fp,
|
||||
t_spice_model spice_model) {
|
||||
int i;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_sram_port = 0;
|
||||
t_spice_model_port** sram_ports = NULL;
|
||||
float total_width;
|
||||
int width_cnt;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
/* Find input ports, output ports and sram ports*/
|
||||
input_ports = find_spice_model_ports(&spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
output_ports = find_spice_model_ports(&spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
sram_ports = find_spice_model_ports(&spice_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
||||
|
||||
/* Check */
|
||||
assert(1 == num_input_port);
|
||||
assert(1 == num_output_port);
|
||||
assert(1 == num_sram_port);
|
||||
|
||||
fprintf(fp, "***** Auto-generated LUT info: spice_model_name = %s, size = %d *****\n",
|
||||
spice_model.name, input_ports[0]->size);
|
||||
/* Define the subckt*/
|
||||
fprintf(fp, ".subckt %s ", spice_model.name); /* Subckt name*/
|
||||
/* Input ports*/
|
||||
for (i = 0; i < input_ports[0]->size; i++) {
|
||||
fprintf(fp, "%s%d ", input_ports[0]->prefix, i);
|
||||
}
|
||||
/* output ports*/
|
||||
assert(1 == output_ports[0]->size);
|
||||
fprintf(fp, "%s ", output_ports[0]->prefix);
|
||||
/* sram ports */
|
||||
for (i = 0; i < sram_ports[0]->size; i++) {
|
||||
fprintf(fp, "%s%d ", sram_ports[0]->prefix, i);
|
||||
}
|
||||
/* local vdd and gnd*/
|
||||
fprintf(fp, "svdd sgnd\n");
|
||||
|
||||
/* Input buffers */
|
||||
for (i = 0; i < input_ports[0]->size; i++) {
|
||||
/* For negative input of LUT MUX*/
|
||||
/* Output inverter with maximum size allowed
|
||||
* until the rest of width is smaller than threshold */
|
||||
total_width = spice_model.lut_input_buffer->size * spice_model.lut_input_buffer->f_per_stage;
|
||||
width_cnt = 0;
|
||||
while (total_width > max_width_per_trans) {
|
||||
fprintf(fp, "Xinv0_in%d_no%d %s%d lut_mux_in%d_inv svdd sgnd inv size=\'%g\'",
|
||||
i, width_cnt,
|
||||
input_ports[0]->prefix, i,
|
||||
i, max_width_per_trans);
|
||||
fprintf(fp, "\n");
|
||||
/* Update */
|
||||
total_width = total_width - max_width_per_trans;
|
||||
width_cnt++;
|
||||
}
|
||||
/* Print if we still have to */
|
||||
if (total_width > 0) {
|
||||
fprintf(fp, "Xinv0_in%d_no%d %s%d lut_mux_in%d_inv svdd sgnd inv size=\'%g\'",
|
||||
i, width_cnt,
|
||||
input_ports[0]->prefix, i,
|
||||
i, total_width);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
/* For postive input of LUT MUX, we use the tapered_buffer subckt directly */
|
||||
assert(1 == spice_model.lut_input_buffer->tapered_buf);
|
||||
fprintf(fp, "X%s_in%d %s%d lut_mux_in%d svdd sgnd tapbuf_level%d_f%d\n",
|
||||
spice_model.lut_input_buffer->spice_model->prefix, i,
|
||||
input_ports[0]->prefix, i, i,
|
||||
spice_model.lut_input_buffer->tap_buf_level,
|
||||
spice_model.lut_input_buffer->f_per_stage);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
/* Output buffers already included in LUT MUX */
|
||||
/* LUT MUX*/
|
||||
assert(sram_ports[0]->size == (int)pow(2.,(double)(input_ports[0]->size)));
|
||||
fprintf(fp, "Xlut_mux ");
|
||||
/* SRAM ports of LUT, they are inputs of lut_muxes*/
|
||||
for (i = 0; i < sram_ports[0]->size; i++) {
|
||||
fprintf(fp, "%s%d ", sram_ports[0]->prefix, i);
|
||||
}
|
||||
/* Output port, LUT output is LUT MUX output*/
|
||||
fprintf(fp, "%s ", output_ports[0]->prefix);
|
||||
/* input port, LUT input is LUT MUX sram*/
|
||||
for (i = 0; i < input_ports[0]->size; i++) {
|
||||
fprintf(fp, "lut_mux_in%d lut_mux_in%d_inv ", i, i);
|
||||
}
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, "svdd sgnd %s_mux_size%d\n", spice_model.name, sram_ports[0]->size);
|
||||
|
||||
/* End of LUT subckt*/
|
||||
fprintf(fp, ".eom\n");
|
||||
|
||||
/* Free */
|
||||
free(input_ports);
|
||||
free(output_ports);
|
||||
free(sram_ports);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print LUT subckts into a SPICE file*/
|
||||
void generate_spice_luts(char* subckt_dir,
|
||||
int num_spice_model,
|
||||
t_spice_model* spice_models) {
|
||||
FILE* fp = NULL;
|
||||
char* sp_name = my_strcat(subckt_dir, luts_spice_file_name);
|
||||
int imodel = 0;
|
||||
|
||||
/* Create FILE*/
|
||||
fp = fopen(sp_name, "w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create SPICE netlist %s",__FILE__, __LINE__, wires_spice_file_name);
|
||||
exit(1);
|
||||
}
|
||||
fprint_spice_head(fp,"LUTs");
|
||||
|
||||
for (imodel = 0; imodel < num_spice_model; imodel++) {
|
||||
if ((SPICE_MODEL_LUT == spice_models[imodel].type)
|
||||
&&(NULL == spice_models[imodel].model_netlist)) {
|
||||
fprint_spice_lut_subckt(fp, spice_models[imodel]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close*/
|
||||
fclose(fp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_pb_primitive_lut(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_pb* prim_pb,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model,
|
||||
int lut_status,
|
||||
t_rr_node* pb_rr_graph) {
|
||||
int i;
|
||||
int num_sram = 0;
|
||||
int* sram_bits = NULL; /* decoded SRAM bits */
|
||||
int truth_table_length = 0;
|
||||
char** truth_table = NULL;
|
||||
int lut_size = 0;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_sram_port = 0;
|
||||
t_spice_model_port** sram_ports = NULL;
|
||||
|
||||
char* formatted_subckt_prefix = format_spice_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* cur_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
int cur_num_sram = 0;
|
||||
char* sram_vdd_port_name = NULL;
|
||||
|
||||
int num_lut_pin_nets;
|
||||
int* lut_pin_net = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == cur_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid cur_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Asserts */
|
||||
assert(SPICE_MODEL_LUT == spice_model->type);
|
||||
|
||||
/* Check if this is an idle logical block mapped*/
|
||||
switch (lut_status) {
|
||||
case PRIMITIVE_WIRED_LUT:
|
||||
assert(NULL != pb_rr_graph);
|
||||
if (NULL == mapped_logical_block) {
|
||||
/* Get the mapped vpack_net_num of this physical LUT pb */
|
||||
get_mapped_lut_pb_input_pin_vpack_net_num(cur_pb_graph_node, pb_rr_graph, &num_lut_pin_nets, &lut_pin_net);
|
||||
/* consider LUT pin remapping when assign lut truth tables */
|
||||
mapped_logical_block = &logical_block[get_pb_graph_node_wired_lut_logical_block_index(cur_pb_graph_node, pb_rr_graph)];
|
||||
/* Match truth table and post-routing results */
|
||||
truth_table = assign_post_routing_wired_lut_truth_table(mapped_logical_block,
|
||||
num_lut_pin_nets, lut_pin_net, &truth_table_length);
|
||||
} else {
|
||||
/* Give a special truth table */
|
||||
assert (VPACK_COMB == mapped_logical_block->type);
|
||||
/* Get the mapped vpack_net_num of this physical LUT pb */
|
||||
get_mapped_lut_pb_input_pin_vpack_net_num(cur_pb_graph_node, pb_rr_graph, &num_lut_pin_nets, &lut_pin_net);
|
||||
/* consider LUT pin remapping when assign lut truth tables */
|
||||
/* Match truth table and post-routing results */
|
||||
truth_table = assign_post_routing_wired_lut_truth_table(mapped_logical_block,
|
||||
num_lut_pin_nets, lut_pin_net, &truth_table_length);
|
||||
}
|
||||
break;
|
||||
case PRIMITIVE_IDLE:
|
||||
break;
|
||||
case PRIMITIVE_NORMAL:
|
||||
assert (NULL != mapped_logical_block);
|
||||
/* Back-annotate to logical block */
|
||||
/* Back-annotate to logical block */
|
||||
mapped_logical_block->mapped_spice_model = spice_model;
|
||||
mapped_logical_block->mapped_spice_model_index = spice_model->cnt;
|
||||
|
||||
assert (VPACK_COMB == mapped_logical_block->type);
|
||||
/* Get the mapped vpack_net_num of this physical LUT pb */
|
||||
get_mapped_lut_pb_input_pin_vpack_net_num(cur_pb_graph_node, pb_rr_graph, &num_lut_pin_nets, &lut_pin_net);
|
||||
/* consider LUT pin remapping when assign lut truth tables */
|
||||
/* Match truth table and post-routing results */
|
||||
truth_table = assign_post_routing_lut_truth_table(mapped_logical_block,
|
||||
num_lut_pin_nets, lut_pin_net, &truth_table_length);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(FILE:%s, [LINE%d]) Invalid status(=%d) for LUT!\n",
|
||||
__FILE__, __LINE__, lut_status);
|
||||
exit(1);
|
||||
}
|
||||
/* Determine size of LUT*/
|
||||
input_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
output_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
sram_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
||||
assert(1 == num_input_port);
|
||||
assert(1 == num_output_port);
|
||||
assert(1 == num_sram_port);
|
||||
lut_size = input_ports[0]->size;
|
||||
num_sram = (int)pow(2.,(double)(lut_size));
|
||||
assert(num_sram == sram_ports[0]->size);
|
||||
assert(1 == output_ports[0]->size);
|
||||
|
||||
/* Get current counter of mem_bits, bl and wl */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_spice_orgz_info);
|
||||
|
||||
/* Generate sram bits, use the default value of SRAM port */
|
||||
sram_bits = generate_lut_sram_bits(truth_table_length, truth_table,
|
||||
lut_size, sram_ports[0]->default_val);
|
||||
|
||||
/* Print the subckts*/
|
||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
||||
|
||||
if (NULL != mapped_logical_block) {
|
||||
fprintf(fp, "***** Logical block mapped to this LUT: %s *****\n",
|
||||
mapped_logical_block->name);
|
||||
}
|
||||
|
||||
/* Subckt definition*/
|
||||
fprintf(fp, ".subckt %s%s[%d] ", formatted_subckt_prefix, cur_pb_type->name, index);
|
||||
/* Print inputs, outputs, inouts, clocks, NO SRAMs*/
|
||||
/*
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(formatted_subckt_prefix) + strlen(cur_pb_type->name) + 1 +
|
||||
strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s%s[%d]", formatted_subckt_prefix, cur_pb_type->name, index);
|
||||
*/
|
||||
/* Simplify the prefix, make the SPICE netlist readable*/
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(cur_pb_type->name) + 1 +
|
||||
strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s[%d]", cur_pb_type->name, index);
|
||||
|
||||
/* Only dump the global ports belonging to a spice_model
|
||||
* Do not go recursive, we can freely define global ports anywhere in SPICE netlist
|
||||
*/
|
||||
rec_fprint_spice_model_global_ports(fp, spice_model, FALSE);
|
||||
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, cur_pb_type);
|
||||
/* SRAM bits are fixed in this subckt, no need to define them here*/
|
||||
/* Local Vdd and gnd*/
|
||||
fprintf(fp, "svdd sgnd\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Print the encoding in SPICE netlist for debugging */
|
||||
fprintf(fp, "***** Truth Table for LUT[%d], size=%d. *****\n",
|
||||
spice_model->cnt, lut_size);
|
||||
for (i = 0; i < truth_table_length; i++) {
|
||||
fprintf(fp,"* %s *\n", truth_table[i]);
|
||||
}
|
||||
|
||||
fprintf(fp, "***** SRAM bits for LUT[%d], size=%d, num_sram=%d. *****\n",
|
||||
spice_model->cnt, lut_size, num_sram);
|
||||
fprintf(fp, "*****");
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
fprintf(fp, "%d", sram_bits[i]);
|
||||
}
|
||||
fprintf(fp, "*****\n");
|
||||
|
||||
/* Call SRAM subckts*/
|
||||
/* Give the VDD port name for SRAMs */
|
||||
sram_vdd_port_name = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(spice_tb_global_vdd_lut_sram_port_name)
|
||||
+ 1 ));
|
||||
sprintf(sram_vdd_port_name, "%s",
|
||||
spice_tb_global_vdd_lut_sram_port_name);
|
||||
/* Now Print SRAMs one by one */
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
fprint_spice_one_sram_subckt(fp, sram_spice_orgz_info, spice_model, sram_vdd_port_name);
|
||||
}
|
||||
|
||||
/* Call LUT subckt*/
|
||||
fprintf(fp, "X%s[%d] ", spice_model->prefix, spice_model->cnt);
|
||||
/* Connect inputs*/
|
||||
/* Connect outputs*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, cur_pb_type);
|
||||
/* Connect srams*/
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
assert( (0 == sram_bits[i]) || (1 == sram_bits[i]) );
|
||||
fprint_spice_sram_one_outport(fp, sram_spice_orgz_info, cur_num_sram + i, sram_bits[i]);
|
||||
}
|
||||
|
||||
/* vdd should be connected to special global wire gvdd_lut and gnd,
|
||||
* Every LUT has a special VDD for statistics
|
||||
*/
|
||||
fprintf(fp, "gvdd_%s[%d] sgnd %s\n", spice_model->prefix, spice_model->cnt, spice_model->name);
|
||||
/* TODO: Add a nodeset for convergence */
|
||||
|
||||
/* End of subckt*/
|
||||
fprintf(fp, ".eom\n");
|
||||
|
||||
/* Store the configuraion bit to linked-list */
|
||||
add_sram_conf_bits_to_llist(sram_spice_orgz_info, cur_num_sram,
|
||||
num_sram, sram_bits);
|
||||
|
||||
spice_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
for (i = 0; i < truth_table_length; i++) {
|
||||
free(truth_table[i]);
|
||||
}
|
||||
free(truth_table);
|
||||
my_free(formatted_subckt_prefix);
|
||||
my_free(input_ports);
|
||||
my_free(output_ports);
|
||||
my_free(sram_ports);
|
||||
my_free(sram_bits);
|
||||
my_free(port_prefix);
|
||||
my_free(sram_vdd_port_name);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
|
||||
|
||||
void fprint_spice_lut_subckt(FILE* fp,
|
||||
t_spice_model spice_model);
|
||||
|
||||
void generate_spice_luts(char* subckt_dir,
|
||||
int num_spice_model,
|
||||
t_spice_model* spice_models);
|
||||
|
||||
|
||||
void fprint_pb_primitive_lut(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_pb* prim_pb,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model,
|
||||
int lut_status,
|
||||
t_rr_node* pb_rr_graph);
|
|
@ -1,773 +0,0 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph_util.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph2.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "spice_globals.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "spice_utils.h"
|
||||
#include "spice_subckt.h"
|
||||
#include "spice_mux_testbench.h"
|
||||
|
||||
/* local global variables */
|
||||
static int tb_num_luts = 0;
|
||||
static int testbench_load_cnt = 0;
|
||||
static int upbound_sim_num_clock_cycles = 2;
|
||||
static int max_sim_num_clock_cycles = 2;
|
||||
static int auto_select_max_sim_num_clock_cycles = TRUE;
|
||||
|
||||
/* Subroutines in this source file*/
|
||||
static
|
||||
void init_spice_lut_testbench_globals(t_spice spice) {
|
||||
tb_num_luts = 0;
|
||||
auto_select_max_sim_num_clock_cycles = spice.spice_params.meas_params.auto_select_sim_num_clk_cycle;
|
||||
upbound_sim_num_clock_cycles = spice.spice_params.meas_params.sim_num_clock_cycle + 1;
|
||||
if (FALSE == auto_select_max_sim_num_clock_cycles) {
|
||||
max_sim_num_clock_cycles = spice.spice_params.meas_params.sim_num_clock_cycle + 1;
|
||||
} else {
|
||||
max_sim_num_clock_cycles = 2;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void fprint_spice_lut_testbench_global_ports(FILE* fp, int grid_x, int grid_y,
|
||||
int num_clock,
|
||||
t_spice spice) {
|
||||
/* int i; */
|
||||
/* A valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File Handler!\n",__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Print generic global ports*/
|
||||
fprint_spice_generic_testbench_global_ports(fp,
|
||||
sram_spice_orgz_info,
|
||||
global_ports_head);
|
||||
|
||||
fprintf(fp, ".global gvdd_sram_luts\n");
|
||||
fprintf(fp, ".global gvdd_load\n");
|
||||
|
||||
/*Global Vdds for LUTs*/
|
||||
fprint_grid_global_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_LUT, spice);
|
||||
/*
|
||||
for (i = 0; i < spice.num_spice_model; i++) {
|
||||
if (SPICE_MODEL_LUT == spice.spice_models[i].type) {
|
||||
fprint_global_vdds_logical_block_spice_model(fp, &(spice.spice_models[i]));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_one_lut(FILE* fp,
|
||||
char* subckt_name,
|
||||
int num_inputs, int num_outputs,
|
||||
int* input_init_value,
|
||||
float* input_density,
|
||||
float* input_probability) {
|
||||
int ipin;
|
||||
/* A valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Invalid File Handler!\n",__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Call defined subckt */
|
||||
fprintf(fp, "Xlut[%d] ", tb_num_luts);
|
||||
for (ipin = 0; ipin < num_inputs; ipin++) {
|
||||
fprintf(fp, "lut[%d]->in[%d] ", tb_num_luts, ipin);
|
||||
}
|
||||
fprintf(fp, "lut[%d]->out gvdd 0 %s\n", tb_num_luts, subckt_name);
|
||||
/* Stimulates */
|
||||
for (ipin = 0; ipin < num_inputs; ipin++) {
|
||||
fprintf(fp, "Vlut[%d]->in[%d] lut[%d]->in[%d] 0 \n",
|
||||
tb_num_luts, ipin, tb_num_luts, ipin);
|
||||
fprint_voltage_pulse_params(fp, input_init_value[ipin], input_density[ipin], input_probability[ipin]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_one_pb_graph_node_lut(FILE* fp,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
char* prefix,
|
||||
int x, int y,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
int logical_block_index = OPEN;
|
||||
t_spice_model* pb_spice_model = NULL;
|
||||
t_pb_type* cur_pb_type = NULL;
|
||||
float* input_density = NULL;
|
||||
float* input_probability = NULL;
|
||||
int* input_init_value = NULL;
|
||||
int* input_net_num = NULL;
|
||||
int iport, ipin, cur_pin;
|
||||
int num_inputs, num_outputs, num_clock_pins;
|
||||
char* outport_name = NULL;
|
||||
t_rr_node* local_rr_graph = NULL;
|
||||
float average_density = 0.;
|
||||
int avg_density_cnt = 0;
|
||||
int num_sim_clock_cycles = 0;
|
||||
|
||||
assert(NULL != cur_pb_graph_node);
|
||||
assert(NULL != prefix);
|
||||
|
||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
||||
assert(NULL != cur_pb_type);
|
||||
pb_spice_model = cur_pb_type->spice_model;
|
||||
|
||||
/* Try to find the mapped logic block index */
|
||||
logical_block_index = find_grid_mapped_logical_block(x, y,
|
||||
pb_spice_model, prefix);
|
||||
|
||||
/* Bypass unmapped luts */
|
||||
/*
|
||||
if (OPEN == logical_block_index) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Allocate input_density and probability */
|
||||
stats_pb_graph_node_port_pin_numbers(cur_pb_graph_node,&num_inputs,&num_outputs, &num_clock_pins);
|
||||
assert(0 == num_clock_pins);
|
||||
assert(1 == num_outputs);
|
||||
assert(0 < num_inputs);
|
||||
|
||||
input_density = (float*)my_malloc(sizeof(float)*num_inputs);
|
||||
input_probability = (float*)my_malloc(sizeof(float)*num_inputs);
|
||||
input_init_value = (int*)my_malloc(sizeof(int)*num_inputs);
|
||||
input_net_num = (int*)my_malloc(sizeof(int)*num_inputs);
|
||||
|
||||
/* Get activity information */
|
||||
assert(1 == cur_pb_graph_node->num_input_ports);
|
||||
cur_pin = 0;
|
||||
for (iport = 0; iport < cur_pb_graph_node->num_input_ports; iport++) {
|
||||
for (ipin = 0; ipin < cur_pb_graph_node->num_input_pins[iport]; ipin++) {
|
||||
/* if we find a mapped logic block */
|
||||
if (OPEN != logical_block_index) {
|
||||
local_rr_graph = logical_block[logical_block_index].pb->parent_pb->rr_graph;
|
||||
} else {
|
||||
local_rr_graph = NULL;
|
||||
}
|
||||
input_net_num[cur_pin] = pb_pin_net_num(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
input_density[cur_pin] = pb_pin_density(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
input_probability[cur_pin] = pb_pin_probability(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
input_init_value[cur_pin] = pb_pin_init_value(local_rr_graph, &(cur_pb_graph_node->input_pins[iport][ipin]));
|
||||
cur_pin++;
|
||||
}
|
||||
assert(cur_pin == num_inputs);
|
||||
}
|
||||
/* Check lut pin net num consistency */
|
||||
if (OPEN != logical_block_index) {
|
||||
if (0 == check_consistency_logical_block_net_num(&(logical_block[logical_block_index]), num_inputs, input_net_num)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])LUT(name:%s) consistency check fail!\n",
|
||||
__FILE__, __LINE__, logical_block[logical_block_index].name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the subckt and give stimulates, measurements */
|
||||
if (OPEN != logical_block_index) {
|
||||
fprintf(fp,"***** LUT[%d]: logical_block_index[%d], gvdd_index[%d]*****\n",
|
||||
tb_num_luts, logical_block_index, logical_block[logical_block_index].mapped_spice_model_index);
|
||||
} else {
|
||||
fprintf(fp,"***** LUT[%d]: logical_block_index[%d], gvdd_index[%d]*****\n",
|
||||
tb_num_luts, -1, -1);
|
||||
}
|
||||
fprint_spice_lut_testbench_one_lut(fp, prefix, num_inputs, num_outputs,
|
||||
input_init_value, input_density, input_probability);
|
||||
/* Add loads: two inverters */
|
||||
/* Recursive add all the loads */
|
||||
outport_name = (char*)my_malloc(sizeof(char)*( 4 + strlen(my_itoa(tb_num_luts))
|
||||
+ 6 + 1 ));
|
||||
sprintf(outport_name, "lut[%d]->out",
|
||||
tb_num_luts);
|
||||
if (TRUE == run_testbench_load_extraction) { /* Additional switch, default on! */
|
||||
if (OPEN != logical_block_index) {
|
||||
fprint_spice_testbench_pb_graph_pin_inv_loads_rec(fp, &testbench_load_cnt,
|
||||
x, y,
|
||||
&(cur_pb_graph_node->output_pins[0][0]),
|
||||
logical_block[logical_block_index].pb,
|
||||
outport_name,
|
||||
FALSE,
|
||||
LL_rr_node_indices);
|
||||
} else {
|
||||
fprint_spice_testbench_pb_graph_pin_inv_loads_rec(fp, &testbench_load_cnt,
|
||||
x, y,
|
||||
&(cur_pb_graph_node->output_pins[0][0]),
|
||||
NULL,
|
||||
outport_name,
|
||||
FALSE,
|
||||
LL_rr_node_indices);
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate average density of this MUX */
|
||||
average_density = 0.;
|
||||
avg_density_cnt = 0;
|
||||
for (ipin = 0; ipin < num_inputs; ipin++) {
|
||||
assert(!(0 > input_density[ipin]));
|
||||
if (0. < input_density[ipin]) {
|
||||
average_density += input_density[ipin];
|
||||
avg_density_cnt++;
|
||||
}
|
||||
}
|
||||
/* Calculate the num_sim_clock_cycle for this MUX, update global max_sim_clock_cycle in this testbench */
|
||||
if (0 < avg_density_cnt) {
|
||||
average_density = average_density/avg_density_cnt;
|
||||
} else {
|
||||
assert(0 == avg_density_cnt);
|
||||
average_density = 0.;
|
||||
}
|
||||
if (0. == average_density) {
|
||||
num_sim_clock_cycles = 2;
|
||||
} else {
|
||||
assert(0. < average_density);
|
||||
num_sim_clock_cycles = (int)(1/average_density) + 1;
|
||||
}
|
||||
if (TRUE == auto_select_max_sim_num_clock_cycles) {
|
||||
/* for idle blocks, 2 clock cycle is well enough... */
|
||||
if (2 < num_sim_clock_cycles) {
|
||||
num_sim_clock_cycles = upbound_sim_num_clock_cycles;
|
||||
} else {
|
||||
num_sim_clock_cycles = 2;
|
||||
}
|
||||
if (max_sim_num_clock_cycles < num_sim_clock_cycles) {
|
||||
max_sim_num_clock_cycles = num_sim_clock_cycles;
|
||||
}
|
||||
} else {
|
||||
num_sim_clock_cycles = max_sim_num_clock_cycles;
|
||||
}
|
||||
|
||||
/* Mark temporary used */
|
||||
if (OPEN != logical_block_index) {
|
||||
logical_block[logical_block_index].temp_used = 1;
|
||||
}
|
||||
|
||||
/* Increment the counter of the LUT spice model */
|
||||
tb_num_luts++;
|
||||
pb_spice_model->tb_cnt++;
|
||||
|
||||
/* Free */
|
||||
my_free(input_net_num);
|
||||
my_free(input_init_value);
|
||||
my_free(input_density);
|
||||
my_free(input_probability);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_rec_pb_graph_node_luts(FILE* fp,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
char* prefix,
|
||||
int x, int y,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
char* formatted_prefix = format_spice_node_prefix(prefix);
|
||||
int ipb, jpb, mode_index;
|
||||
t_pb_type* cur_pb_type = NULL;
|
||||
char* rec_prefix = NULL;
|
||||
|
||||
assert(NULL != cur_pb_graph_node);
|
||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
||||
assert(NULL != cur_pb_type);
|
||||
/* Until we reach a LUT */
|
||||
if (NULL != cur_pb_type->spice_model) {
|
||||
if (SPICE_MODEL_LUT != cur_pb_type->spice_model->type) {
|
||||
return;
|
||||
}
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb_graph_node->placement_index))
|
||||
+ 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]",
|
||||
formatted_prefix, cur_pb_type->name, cur_pb_graph_node->placement_index);
|
||||
/* Print a lut tb: call spice_model, stimulates */
|
||||
fprint_spice_lut_testbench_one_pb_graph_node_lut(fp, cur_pb_graph_node, rec_prefix, x, y, LL_rr_node_indices);
|
||||
my_free(rec_prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go recursively ... */
|
||||
mode_index = find_pb_type_idle_mode_index(*(cur_pb_type));
|
||||
for (ipb = 0; ipb < cur_pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
||||
for (jpb = 0; jpb < cur_pb_type->modes[mode_index].pb_type_children[ipb].num_pb; jpb++) {
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb_graph_node->placement_index)) + 7
|
||||
+ strlen(cur_pb_type->modes[mode_index].name) + 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]_mode[%s]",
|
||||
formatted_prefix, cur_pb_type->name, cur_pb_graph_node->placement_index,
|
||||
cur_pb_type->modes[mode_index].name);
|
||||
/* Go recursively */
|
||||
fprint_spice_lut_testbench_rec_pb_graph_node_luts(fp, &(cur_pb_graph_node->child_pb_graph_nodes[mode_index][ipb][jpb]),
|
||||
rec_prefix, x, y, LL_rr_node_indices);
|
||||
my_free(rec_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_rec_pb_luts(FILE* fp,
|
||||
t_pb* cur_pb, char* prefix,
|
||||
int x, int y,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
char* formatted_prefix = format_spice_node_prefix(prefix);
|
||||
int ipb, jpb;
|
||||
int mode_index;
|
||||
char* rec_prefix = NULL;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Check */
|
||||
assert(NULL != cur_pb);
|
||||
|
||||
/* If we touch the leaf, there is no need print interc*/
|
||||
if (NULL != cur_pb->pb_graph_node->pb_type->spice_model) {
|
||||
if (SPICE_MODEL_LUT != cur_pb->pb_graph_node->pb_type->spice_model->type) {
|
||||
return;
|
||||
}
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb->pb_graph_node->pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb->pb_graph_node->placement_index))
|
||||
+ 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]",
|
||||
formatted_prefix, cur_pb->pb_graph_node->pb_type->name, cur_pb->pb_graph_node->placement_index);
|
||||
/* Print a lut tb: call spice_model, stimulates */
|
||||
fprint_spice_lut_testbench_one_pb_graph_node_lut(fp, cur_pb->pb_graph_node, rec_prefix, x, y, LL_rr_node_indices);
|
||||
my_free(rec_prefix);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Go recursively ... */
|
||||
mode_index = cur_pb->mode;
|
||||
for (ipb = 0; ipb < cur_pb->pb_graph_node->pb_type->modes[mode_index].num_pb_type_children; ipb++) {
|
||||
for (jpb = 0; jpb < cur_pb->pb_graph_node->pb_type->modes[mode_index].pb_type_children[ipb].num_pb; jpb++) {
|
||||
/* Generate rec_prefix */
|
||||
rec_prefix = (char*)my_malloc(sizeof(char) * (strlen(formatted_prefix)
|
||||
+ strlen(cur_pb->pb_graph_node->pb_type->name) + 1
|
||||
+ strlen(my_itoa(cur_pb->pb_graph_node->placement_index)) + 7
|
||||
+ strlen(cur_pb->pb_graph_node->pb_type->modes[mode_index].name) + 1 + 1));
|
||||
sprintf(rec_prefix, "%s%s[%d]_mode[%s]",
|
||||
formatted_prefix, cur_pb->pb_graph_node->pb_type->name,
|
||||
cur_pb->pb_graph_node->placement_index,
|
||||
cur_pb->pb_graph_node->pb_type->modes[mode_index].name);
|
||||
/* Refer to pack/output_clustering.c [LINE 392] */
|
||||
if ((NULL != cur_pb->child_pbs[ipb])&&(NULL != cur_pb->child_pbs[ipb][jpb].name)) {
|
||||
fprint_spice_lut_testbench_rec_pb_luts(fp, &(cur_pb->child_pbs[ipb][jpb]), rec_prefix, x, y, LL_rr_node_indices);
|
||||
} else {
|
||||
/* Print idle graph_node muxes */
|
||||
/* Then we go on */
|
||||
fprint_spice_lut_testbench_rec_pb_graph_node_luts(fp, cur_pb->child_pbs[ipb][jpb].pb_graph_node,
|
||||
rec_prefix, x, y, LL_rr_node_indices);
|
||||
}
|
||||
my_free(rec_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_call_one_grid_defined_luts(FILE* fp, int ix, int iy,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
int iblk;
|
||||
char* prefix = NULL;
|
||||
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((NULL == grid[ix][iy].type)
|
||||
||(EMPTY_TYPE == grid[ix][iy].type)
|
||||
||(0 != grid[ix][iy].offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (iblk = 0; iblk < grid[ix][iy].usage; iblk++) {
|
||||
prefix = (char*)my_malloc(sizeof(char)* (5
|
||||
+ strlen(my_itoa(block[grid[ix][iy].blocks[iblk]].x))
|
||||
+ 2 + strlen(my_itoa(block[grid[ix][iy].blocks[iblk]].y))
|
||||
+ 3 ));
|
||||
sprintf(prefix, "grid[%d][%d]_",
|
||||
block[grid[ix][iy].blocks[iblk]].x,
|
||||
block[grid[ix][iy].blocks[iblk]].y);
|
||||
/* Only for mapped block */
|
||||
assert(NULL != block[grid[ix][iy].blocks[iblk]].pb);
|
||||
/* Mark the temporary net_num for the type pins*/
|
||||
mark_one_pb_parasitic_nets(block[grid[ix][iy].blocks[iblk]].pb);
|
||||
fprint_spice_lut_testbench_rec_pb_luts(fp, block[grid[ix][iy].blocks[iblk]].pb, prefix, ix, iy, LL_rr_node_indices);
|
||||
my_free(prefix);
|
||||
}
|
||||
/* By pass unused blocks */
|
||||
for (iblk = grid[ix][iy].usage; iblk < grid[ix][iy].type->capacity; iblk++) {
|
||||
prefix = (char*)my_malloc(sizeof(char)* (5 + strlen(my_itoa(ix))
|
||||
+ 2 + strlen(my_itoa(iy)) + 3 ));
|
||||
sprintf(prefix, "grid[%d][%d]_", ix, iy);
|
||||
assert(NULL != grid[ix][iy].type->pb_graph_head);
|
||||
/* Mark the temporary net_num for the type pins*/
|
||||
mark_grid_type_pb_graph_node_pins_temp_net_num(ix, iy);
|
||||
fprint_spice_lut_testbench_rec_pb_graph_node_luts(fp, grid[ix][iy].type->pb_graph_head, prefix, ix, iy, LL_rr_node_indices);
|
||||
my_free(prefix);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_call_defined_luts(FILE* fp, t_ivec*** LL_rr_node_indices) {
|
||||
int ix, iy;
|
||||
|
||||
for (ix = 1; ix < (nx + 1); ix++) {
|
||||
for (iy = 1; iy < (ny + 1); iy++) {
|
||||
fprint_spice_lut_testbench_call_one_grid_defined_luts(fp, ix, iy, LL_rr_node_indices);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_conkt_lut_scan_chains(FILE* fp, int grid_x, int grid_y,
|
||||
t_spice spice) {
|
||||
int imodel, isc;
|
||||
t_spice_model* lut_spice_model = NULL;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (imodel = 0; imodel < spice.num_spice_model; imodel++) {
|
||||
if (SPICE_MODEL_LUT == spice.spice_models[imodel].type) {
|
||||
lut_spice_model = &(spice.spice_models[imodel]);
|
||||
/* Bypass LUT SPICE models that are contained by this grid */
|
||||
assert(-1 < (lut_spice_model->grid_index_high[grid_x][grid_y] - lut_spice_model->grid_index_low[grid_x][grid_y]));
|
||||
if (0 == (lut_spice_model->grid_index_high[grid_x][grid_y] - lut_spice_model->grid_index_low[grid_x][grid_y])) {
|
||||
continue;
|
||||
}
|
||||
fprintf(fp, "***** Connecting Scan-chains of %s in this grid[%d][%d] *****\n",
|
||||
lut_spice_model->name, grid_x, grid_y);
|
||||
for (isc = lut_spice_model->grid_index_low[grid_x][grid_y];
|
||||
isc < lut_spice_model->grid_index_high[grid_x][grid_y];
|
||||
isc++) {
|
||||
fprintf(fp, "R%s[%d]_sc_short %s[%d]_sc_tail %s[%d]_sc_head\n",
|
||||
lut_spice_model->prefix, isc,
|
||||
lut_spice_model->prefix, isc,
|
||||
lut_spice_model->prefix, isc + 1);
|
||||
}
|
||||
fprintf(fp, "***** END *****\n");
|
||||
fprintf(fp, "***** Scan-Chain Head of %s in grid[%d][%d]\n",
|
||||
lut_spice_model->name, grid_x, grid_y);
|
||||
fprintf(fp, "V%s[%d]_sc_head %s[%d]_sc_head 0 0\n",
|
||||
lut_spice_model->prefix, lut_spice_model->grid_index_low[grid_x][grid_y],
|
||||
lut_spice_model->prefix, lut_spice_model->grid_index_low[grid_x][grid_y]);
|
||||
fprintf(fp, ".nodeset V(%s[%d]_sc_head) 0\n",
|
||||
lut_spice_model->prefix, lut_spice_model->grid_index_low[grid_x][grid_y]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_stimulations(FILE* fp, int grid_x, int grid_y,
|
||||
int num_clock,
|
||||
t_spice spice,
|
||||
t_ivec*** LL_rr_node_indices) {
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Print generic stimuli */
|
||||
fprint_spice_testbench_generic_global_ports_stimuli(fp, num_clock);
|
||||
|
||||
/* Generate global ports stimuli */
|
||||
fprint_spice_testbench_global_ports_stimuli(fp, global_ports_head);
|
||||
|
||||
/* SRAM ports */
|
||||
/* Every SRAM inputs should have a voltage source */
|
||||
fprintf(fp, "***** Global Inputs for SRAMs *****\n");
|
||||
fprint_spice_testbench_global_sram_inport_stimuli(fp, sram_spice_orgz_info);
|
||||
|
||||
fprintf(fp, "***** Global VDD for LUTs SRAMs *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_lut_sram_port_name,
|
||||
"vsp");
|
||||
|
||||
fprintf(fp, "***** Global VDD for SRAMs *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_sram_port_name,
|
||||
"vsp");
|
||||
|
||||
fprintf(fp, "***** Global VDD for load inverters *****\n");
|
||||
fprint_spice_testbench_global_vdd_port_stimuli(fp,
|
||||
spice_tb_global_vdd_load_port_name,
|
||||
"vsp");
|
||||
|
||||
/* Global Vdd ports */
|
||||
/* Every LUT use an independent Voltage source */
|
||||
fprintf(fp, "***** Global VDD for Look-Up Tables (LUTs) *****\n");
|
||||
fprint_grid_splited_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_LUT, spice);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_spice_lut_testbench_measurements(FILE* fp, int grid_x, int grid_y,
|
||||
t_spice spice,
|
||||
boolean leakage_only) {
|
||||
/* int i; */
|
||||
/* First cycle reserved for measuring leakage */
|
||||
int num_clock_cycle = max_sim_num_clock_cycles;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprint_spice_netlist_transient_setting(fp, spice, num_clock_cycle, leakage_only);
|
||||
fprint_spice_netlist_generic_measurements(fp, spice.spice_params.mc_params, spice.num_spice_model, spice.spice_models);
|
||||
|
||||
/* TODO: Measure the delay of each mapped net and logical block */
|
||||
|
||||
/* Measure the power */
|
||||
/* Leakage ( the first cycle is reserved for leakage measurement) */
|
||||
if (TRUE == leakage_only) {
|
||||
/* Leakage power of SRAMs */
|
||||
fprintf(fp, ".measure tran leakage_power_sram_luts find p(Vgvdd_sram_luts) at=0\n");
|
||||
} else {
|
||||
/* Leakage power of SRAMs */
|
||||
fprintf(fp, ".measure tran leakage_power_sram_luts avg p(Vgvdd_sram_luts) from=0 to='clock_period'\n");
|
||||
}
|
||||
/* Leakage power of LUTs*/
|
||||
fprint_measure_grid_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_LUT, SPICE_MEASURE_LEAKAGE_POWER, num_clock_cycle, spice, leakage_only);
|
||||
/*
|
||||
for (i = 0; i < spice.num_spice_model; i++) {
|
||||
if (SPICE_MODEL_LUT == spice.spice_models[i].type) {
|
||||
fprint_measure_vdds_logical_block_spice_model(fp, &(spice.spice_models[i]), SPICE_MEASURE_LEAKAGE_POWER, num_clock_cycle, leakage_only);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (TRUE == leakage_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dynamic power */
|
||||
/* Dynamic power of SRAMs */
|
||||
fprintf(fp, ".measure tran dynamic_power_sram_luts avg p(Vgvdd_sram_luts) from='clock_period' to='%d*clock_period'\n", num_clock_cycle);
|
||||
fprintf(fp, ".measure tran energy_per_cycle_sram_luts param='dynamic_power_sram_luts*clock_period'\n");
|
||||
/* Dynamic power of LUTs */
|
||||
fprint_measure_grid_vdds_spice_model(fp, grid_x, grid_y, SPICE_MODEL_LUT, SPICE_MEASURE_DYNAMIC_POWER, num_clock_cycle, spice, leakage_only);
|
||||
/*
|
||||
for (i = 0; i < spice.num_spice_model; i++) {
|
||||
if (SPICE_MODEL_LUT == spice.spice_models[i].type) {
|
||||
fprint_measure_vdds_logical_block_spice_model(fp, &(spice.spice_models[i]), SPICE_MEASURE_DYNAMIC_POWER, num_clock_cycle, leakage_only);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Top-level function in this source file */
|
||||
int fprint_spice_one_lut_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* lut_testbench_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_arch arch,
|
||||
int grid_x, int grid_y,
|
||||
boolean leakage_only) {
|
||||
FILE* fp = NULL;
|
||||
char* formatted_subckt_dir_path = format_dir_path(subckt_dir_path);
|
||||
char* temp_include_file_path = NULL;
|
||||
char* title = my_strcat("FPGA LUT Testbench for Design: ", circuit_name);
|
||||
char* lut_testbench_file_path = my_strcat(formatted_spice_dir, lut_testbench_name);
|
||||
int used;
|
||||
|
||||
/* Check if the path exists*/
|
||||
fp = fopen(lut_testbench_file_path,"w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create LUT Testbench SPICE netlist %s!",__FILE__, __LINE__, lut_testbench_file_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Reset tb_cnt for all the spice models */
|
||||
init_spice_models_grid_tb_cnt(arch.spice->num_spice_model, arch.spice->spice_models, grid_x, grid_y);
|
||||
|
||||
/*vpr_printf(TIO_MESSAGE_INFO, "Writing LUT Testbench for %s...\n", circuit_name);*/
|
||||
testbench_load_cnt = 0;
|
||||
|
||||
/* Print the title */
|
||||
fprint_spice_head(fp, title);
|
||||
my_free(title);
|
||||
|
||||
/* print technology library and design parameters*/
|
||||
|
||||
/* Include parameter header files */
|
||||
fprint_spice_include_param_headers(fp, include_dir_path);
|
||||
|
||||
/* Include Key subckts */
|
||||
fprint_spice_include_key_subckts(fp, subckt_dir_path);
|
||||
|
||||
/* Include user-defined sub-circuit netlist */
|
||||
init_include_user_defined_netlists(*(arch.spice));
|
||||
fprint_include_user_defined_netlists(fp, *(arch.spice));
|
||||
|
||||
/* Special subckts for Top-level SPICE netlist */
|
||||
fprintf(fp, "****** Include subckt netlists: Look-Up Tables (LUTs) *****\n");
|
||||
spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, luts_spice_file_name);
|
||||
|
||||
/* Generate filename */
|
||||
fprintf(fp, "****** Include subckt netlists: Grid[%d][%d] *****\n",
|
||||
grid_x, grid_y);
|
||||
temp_include_file_path = fpga_spice_create_one_subckt_filename(grid_spice_file_name_prefix, grid_x, grid_y, spice_netlist_file_postfix);
|
||||
/* Check if we include an existing file! */
|
||||
if (FALSE == check_subckt_file_exist_in_llist(grid_spice_subckt_file_path_head,
|
||||
my_strcat(formatted_subckt_dir_path, temp_include_file_path))) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Intend to include a non-existed SPICE netlist %s!\n",
|
||||
__FILE__, __LINE__, temp_include_file_path);
|
||||
exit(1);
|
||||
}
|
||||
spice_print_one_include_subckt_line(fp, formatted_subckt_dir_path, temp_include_file_path);
|
||||
|
||||
/* Print simulation temperature and other options for SPICE */
|
||||
fprint_spice_options(fp, arch.spice->spice_params);
|
||||
|
||||
/* Global nodes: Vdd for SRAMs, Logic Blocks(Include IO), Switch Boxes, Connection Boxes */
|
||||
fprint_spice_lut_testbench_global_ports(fp, grid_x, grid_y, num_clock, (*arch.spice));
|
||||
|
||||
/* Quote defined Logic blocks subckts (Grids) */
|
||||
init_spice_lut_testbench_globals(*(arch.spice));
|
||||
init_logical_block_spice_model_type_temp_used(arch.spice->num_spice_model, arch.spice->spice_models, SPICE_MODEL_LUT);
|
||||
fprint_spice_lut_testbench_call_one_grid_defined_luts(fp, grid_x, grid_y, LL_rr_node_indices);
|
||||
|
||||
/* Back-anotate activity information to each routing resource node
|
||||
* (We should have activity of each Grid port)
|
||||
*/
|
||||
|
||||
/* Check if the all hardlogic located in this grid have been printed */
|
||||
check_spice_models_grid_tb_cnt(arch.spice->num_spice_model, arch.spice->spice_models, grid_x, grid_y, SPICE_MODEL_LUT);
|
||||
|
||||
/* Add stimulations */
|
||||
fprint_spice_lut_testbench_stimulations(fp, grid_x, grid_y, num_clock, (*arch.spice), LL_rr_node_indices);
|
||||
|
||||
/* Add measurements */
|
||||
fprint_spice_lut_testbench_measurements(fp, grid_x, grid_y, (*arch.spice), leakage_only);
|
||||
|
||||
/* SPICE ends*/
|
||||
fprintf(fp, ".end\n");
|
||||
|
||||
/* Close the file*/
|
||||
fclose(fp);
|
||||
|
||||
if (0 < tb_num_luts) {
|
||||
/*
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Grid[%d][%d] SPICE LUT Testbench for %s...\n",
|
||||
grid_x, grid_y, circuit_name);
|
||||
*/
|
||||
/* Push the testbench to the linked list */
|
||||
tb_head = add_one_spice_tb_info_to_llist(tb_head, lut_testbench_file_path,
|
||||
max_sim_num_clock_cycles);
|
||||
used = 1;
|
||||
} else {
|
||||
/* Remove the file generated */
|
||||
my_remove_file(lut_testbench_file_path);
|
||||
used = 0;
|
||||
}
|
||||
|
||||
/* Free */
|
||||
my_free(temp_include_file_path);
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
/* Top-level function in this source file */
|
||||
void spice_print_lut_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_arch arch,
|
||||
boolean leakage_only) {
|
||||
char* lut_testbench_name = NULL;
|
||||
char* temp_include_file_path = NULL;
|
||||
int ix, iy;
|
||||
int cnt = 0;
|
||||
int used;
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Generating LUT testbench...\n");
|
||||
|
||||
for (ix = 1; ix < (nx+1); ix++) {
|
||||
for (iy = 1; iy < (ny+1); iy++) {
|
||||
/* Check if we include an existing subckt file! */
|
||||
temp_include_file_path = fpga_spice_create_one_subckt_filename(grid_spice_file_name_prefix, ix, iy, spice_netlist_file_postfix);
|
||||
if (FALSE == check_subckt_file_exist_in_llist(grid_spice_subckt_file_path_head,
|
||||
my_strcat(subckt_dir_path, temp_include_file_path))) {
|
||||
/* free */
|
||||
my_free(temp_include_file_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create a testbench for the existing subckt */
|
||||
lut_testbench_name = (char*)my_malloc(sizeof(char)*( strlen(circuit_name)
|
||||
+ 6 + strlen(my_itoa(ix)) + 1
|
||||
+ strlen(my_itoa(iy)) + 1
|
||||
+ strlen(spice_lut_testbench_postfix) + 1 ));
|
||||
sprintf(lut_testbench_name, "%s_grid%d_%d%s",
|
||||
circuit_name, ix, iy, spice_lut_testbench_postfix);
|
||||
used = fprint_spice_one_lut_testbench(formatted_spice_dir, circuit_name, lut_testbench_name,
|
||||
include_dir_path, subckt_dir_path, LL_rr_node_indices,
|
||||
num_clock, arch, ix, iy,
|
||||
leakage_only);
|
||||
if (1 == used) {
|
||||
cnt += used;
|
||||
}
|
||||
/* free */
|
||||
my_free(lut_testbench_name);
|
||||
my_free(temp_include_file_path);
|
||||
}
|
||||
}
|
||||
/* Update the global counter */
|
||||
num_used_lut_tb = cnt;
|
||||
vpr_printf(TIO_MESSAGE_INFO,"No. of generated LUT testbench = %d\n", num_used_lut_tb);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
|
||||
void spice_print_lut_testbench(char* formatted_spice_dir,
|
||||
char* circuit_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_arch arch,
|
||||
boolean leakage_only);
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
|
||||
|
||||
void generate_spice_muxes(char* subckt_dir,
|
||||
int num_switch,
|
||||
t_switch_inf* switches,
|
||||
t_spice* spice,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
t_llist* search_mux_linked_list(t_llist* mux_head,
|
||||
int mux_size,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void check_and_add_mux_to_linked_list(t_llist** muxes_head,
|
||||
int mux_size,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void free_muxes_llist(t_llist* muxes_head);
|
||||
|
|
@ -1,468 +0,0 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph_swseg.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "spice_globals.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "spice_utils.h"
|
||||
#include "spice_pbtypes.h"
|
||||
#include "spice_primitives.h"
|
||||
|
||||
enum e_ff_trigger_type {
|
||||
FF_RE, FF_FE
|
||||
};
|
||||
|
||||
/* Subroutines */
|
||||
void fprint_pb_primitive_ff(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model) {
|
||||
int i;
|
||||
/* Default FF settings, applied when this FF is idle*/
|
||||
enum e_ff_trigger_type trigger_type = FF_RE;
|
||||
int init_val = 0;
|
||||
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_clock_port = 0;
|
||||
t_spice_model_port** clock_ports = NULL;
|
||||
|
||||
int iport, ipin;
|
||||
int num_pb_type_output_port = 0;
|
||||
t_port** pb_type_output_ports = NULL;
|
||||
|
||||
char* formatted_subckt_prefix = format_spice_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* prim_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == prim_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Find ports*/
|
||||
input_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, FALSE);
|
||||
output_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
clock_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, FALSE);
|
||||
|
||||
/* Asserts */
|
||||
assert(3 == num_input_port); /* D, Set and Reset*/
|
||||
for (i = 0; i < num_input_port; i++) {
|
||||
assert(1 == input_ports[i]->size);
|
||||
}
|
||||
assert(1 == num_output_port);
|
||||
assert(1 == output_ports[0]->size);
|
||||
assert(1 == num_clock_port);
|
||||
assert(1 == clock_ports[0]->size);
|
||||
|
||||
assert(SPICE_MODEL_FF == spice_model->type);
|
||||
|
||||
/* Initialize */
|
||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
||||
|
||||
if (NULL != mapped_logical_block) {
|
||||
fprintf(fp, "***** Logical block mapped to this FF: %s *****\n",
|
||||
mapped_logical_block->name);
|
||||
}
|
||||
|
||||
/* Generate Subckt for pb_type*/
|
||||
/*
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(formatted_subckt_prefix) + strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s%s[%d]", formatted_subckt_prefix, prim_pb_type->name, index);
|
||||
*/
|
||||
/* Simplify the port prefix, make SPICE netlist readable */
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s[%d]", prim_pb_type->name, index);
|
||||
/* Definition line */
|
||||
fprintf(fp, ".subckt %s%s ", formatted_subckt_prefix, port_prefix);
|
||||
/* print ports*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, prim_pb_type);
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, "svdd sgnd\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Call the dff subckt*/
|
||||
fprintf(fp, "X%s[%d] ", spice_model->prefix, spice_model->cnt);
|
||||
/* Global ports */
|
||||
if (0 < rec_fprint_spice_model_global_ports(fp, spice_model, FALSE)) {
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
/* print ports*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, prim_pb_type); /* Use global clock for each DFF...*/
|
||||
/* Local vdd and gnd, spice_model name
|
||||
* global vdd for ff
|
||||
*/
|
||||
fprintf(fp, "%s_%s[%d] sgnd %s\n",
|
||||
spice_tb_global_vdd_port_name,
|
||||
spice_model->prefix,
|
||||
spice_model->cnt,
|
||||
spice_model->name);
|
||||
|
||||
/* Apply rising edge, and init value to the ff*/
|
||||
if (NULL != mapped_logical_block) {
|
||||
/* Consider the rising edge|falling edge */
|
||||
if (0 == strcmp("re", mapped_logical_block->trigger_type)) {
|
||||
trigger_type = FF_RE;
|
||||
} else if (0 == strcmp("fe", mapped_logical_block->trigger_type)) {
|
||||
trigger_type = FF_FE;
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid ff trigger type! Should be [re|fe].\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Assign initial value */
|
||||
if (1 == mapped_logical_block->init_val) {
|
||||
init_val = 1;
|
||||
} else {
|
||||
init_val = 0;
|
||||
}
|
||||
|
||||
/* Back-annotate to logical block */
|
||||
mapped_logical_block->mapped_spice_model = spice_model;
|
||||
mapped_logical_block->mapped_spice_model_index = spice_model->cnt;
|
||||
} else {
|
||||
trigger_type = FF_RE;
|
||||
init_val = 0;
|
||||
}
|
||||
/* TODO: apply falling edge, initial value to FF!!!*/
|
||||
/*fprintf(fp, "\n");*/
|
||||
|
||||
/* Add nodeset */
|
||||
pb_type_output_ports = find_pb_type_ports_match_spice_model_port_type(prim_pb_type, SPICE_MODEL_PORT_OUTPUT, &num_pb_type_output_port);
|
||||
for (iport = 0; iport < num_pb_type_output_port; iport++) {
|
||||
for (ipin = 0; ipin < pb_type_output_ports[iport]->num_pins; ipin++) {
|
||||
fprintf(fp, ".nodeset V(%s->%s[%d]) ", port_prefix, pb_type_output_ports[iport]->name, ipin);
|
||||
if (0 == init_val) {
|
||||
fprintf(fp, "0\n");
|
||||
} else {
|
||||
assert(1 == init_val);
|
||||
fprintf(fp, "vsp\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End */
|
||||
fprintf(fp, ".eom\n");
|
||||
|
||||
spice_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
my_free(formatted_subckt_prefix);
|
||||
my_free(port_prefix);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print hardlogic SPICE subckt*/
|
||||
void fprint_pb_primitive_hardlogic(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model) {
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_clock_port = 0;
|
||||
t_spice_model_port** clock_ports = NULL;
|
||||
|
||||
char* formatted_subckt_prefix = format_spice_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* prim_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == prim_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Find ports*/
|
||||
input_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
output_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
clock_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, TRUE);
|
||||
|
||||
/* Asserts */
|
||||
assert(SPICE_MODEL_HARDLOGIC == spice_model->type);
|
||||
|
||||
/* Initialize */
|
||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
||||
|
||||
if (NULL != mapped_logical_block) {
|
||||
fprintf(fp, "***** Logical block mapped to this hardlogic: %s *****\n",
|
||||
mapped_logical_block->name);
|
||||
}
|
||||
|
||||
|
||||
/* Generate Subckt for pb_type*/
|
||||
/*
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(formatted_subckt_prefix) + strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s%s[%d]", formatted_subckt_prefix, prim_pb_type->name, index);
|
||||
*/
|
||||
/* Simplify the port prefix, make SPICE netlist readable */
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s[%d]", prim_pb_type->name, index);
|
||||
/* Definition line */
|
||||
fprintf(fp, ".subckt %s%s ", formatted_subckt_prefix, port_prefix);
|
||||
/* print ports*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, prim_pb_type);
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, "svdd sgnd\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Back-annotate to logical block */
|
||||
if (NULL != mapped_logical_block) {
|
||||
mapped_logical_block->mapped_spice_model = spice_model;
|
||||
mapped_logical_block->mapped_spice_model_index = spice_model->cnt;
|
||||
}
|
||||
|
||||
/* Call the dff subckt*/
|
||||
fprintf(fp, "X%s[%d] ", spice_model->prefix, spice_model->cnt);
|
||||
/* print ports*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, prim_pb_type);
|
||||
/* Local vdd and gnd, spice_model name,
|
||||
* Global vdd for hardlogic to split
|
||||
*/
|
||||
fprintf(fp, "gvdd_%s[%d] sgnd %s\n", spice_model->prefix, spice_model->cnt, spice_model->name);
|
||||
|
||||
/* End */
|
||||
fprintf(fp, ".eom\n");
|
||||
|
||||
spice_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
free(formatted_subckt_prefix);
|
||||
free(port_prefix);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_pb_primitive_io(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model) {
|
||||
int num_pad_port = 0; /* INOUT port */
|
||||
t_spice_model_port** pad_ports = NULL;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_clock_port = 0;
|
||||
t_spice_model_port** clock_ports = NULL;
|
||||
int num_sram_port = 0;
|
||||
t_spice_model_port** sram_ports = NULL;
|
||||
|
||||
int i;
|
||||
int num_sram = 0;
|
||||
int expected_num_sram = 0;
|
||||
int* sram_bits = NULL;
|
||||
int cur_num_sram = 0;
|
||||
|
||||
char* formatted_subckt_prefix = format_spice_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* prim_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
char* sram_vdd_port_name = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == prim_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Find ports*/
|
||||
pad_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_INOUT, &num_pad_port, TRUE);
|
||||
input_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
output_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
clock_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, TRUE);
|
||||
sram_ports = find_spice_model_ports(spice_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
||||
|
||||
/* Asserts */
|
||||
assert(SPICE_MODEL_IOPAD == spice_model->type);
|
||||
|
||||
/* Initialize */
|
||||
|
||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
||||
|
||||
if (NULL != mapped_logical_block) {
|
||||
fprintf(fp, "***** Logical block mapped to this IO: %s *****\n",
|
||||
mapped_logical_block->name);
|
||||
}
|
||||
|
||||
/* Generate Subckt for pb_type*/
|
||||
/*
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(formatted_subckt_prefix) + strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s%s[%d]", formatted_subckt_prefix, prim_pb_type->name, index);
|
||||
*/
|
||||
/* Simplify the port prefix, make SPICE netlist readable */
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s[%d]", prim_pb_type->name, index);
|
||||
|
||||
/* Decode SRAM bits */
|
||||
assert((1 == num_sram_port)&&(NULL != sram_ports)&&(1 == sram_ports[0]->size));
|
||||
num_sram = count_num_sram_bits_one_spice_model(spice_model, -1);
|
||||
/* what is the SRAM bit of a mode? */
|
||||
/* If logical block is not NULL, we need to decode the sram bit */
|
||||
if (NULL != mapped_logical_block) {
|
||||
assert(NULL != mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits);
|
||||
sram_bits = decode_mode_bits(mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits, &expected_num_sram);
|
||||
assert(expected_num_sram == num_sram);
|
||||
} else {
|
||||
/* Initialize */
|
||||
sram_bits = (int*)my_calloc(num_sram, sizeof(int));
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
sram_bits[i] = sram_ports[0]->default_val;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get current counter of mem_bits, bl and wl */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_spice_orgz_info);
|
||||
|
||||
/* Definition line */
|
||||
fprintf(fp, ".subckt %s%s ", formatted_subckt_prefix, port_prefix);
|
||||
/* print ports*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, prim_pb_type);
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, "svdd sgnd\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Call the iopad subckt*/
|
||||
fprintf(fp, "X%s[%d] ", spice_model->prefix, spice_model->cnt);
|
||||
/* Only dump the global ports belonging to a spice_model
|
||||
* Do not go recursive, we can freely define global ports anywhere in SPICE netlist
|
||||
*/
|
||||
if (0 < rec_fprint_spice_model_global_ports(fp, spice_model, FALSE)) {
|
||||
fprintf(fp, "+ ");
|
||||
}
|
||||
/* print regular ports*/
|
||||
fprint_pb_type_ports(fp, port_prefix, 0, prim_pb_type);
|
||||
/* Print inout port */
|
||||
fprintf(fp, " %s%s[%d] ",
|
||||
gio_inout_prefix,
|
||||
spice_model->prefix,
|
||||
spice_model->cnt);
|
||||
/* Print SRAM ports */
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
fprint_spice_sram_one_outport(fp, sram_spice_orgz_info, cur_num_sram + i, sram_bits[i]);
|
||||
/* We need the invertered signal for better convergency */
|
||||
fprint_spice_sram_one_outport(fp, sram_spice_orgz_info, cur_num_sram + i, 1 - sram_bits[i]);
|
||||
}
|
||||
|
||||
/* Local vdd and gnd, spice_model name,
|
||||
* TODO: Global vdd for i/o pad to split?
|
||||
*/
|
||||
fprintf(fp, "%s_%s[%d] sgnd %s\n",
|
||||
spice_tb_global_vdd_port_name,
|
||||
spice_model->prefix,
|
||||
spice_model->cnt,
|
||||
spice_model->name);
|
||||
|
||||
/* Print the encoding in SPICE netlist for debugging */
|
||||
fprintf(fp, "***** SRAM bits for IOPAD[%d] *****\n",
|
||||
spice_model->cnt);
|
||||
fprintf(fp, "*****");
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
fprintf(fp, "%d", sram_bits[i]);
|
||||
}
|
||||
fprintf(fp, "*****\n");
|
||||
|
||||
/* Call SRAM subckts*/
|
||||
/* Give the VDD port name for SRAMs */
|
||||
sram_vdd_port_name = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(spice_tb_global_vdd_io_sram_port_name)
|
||||
+ 1 ));
|
||||
sprintf(sram_vdd_port_name, "%s",
|
||||
spice_tb_global_vdd_io_sram_port_name);
|
||||
/* Now Print SRAMs one by one */
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
fprint_spice_one_sram_subckt(fp, sram_spice_orgz_info, spice_model, sram_vdd_port_name);
|
||||
}
|
||||
|
||||
/* Store the configuraion bit to linked-list */
|
||||
add_sram_conf_bits_to_llist(sram_spice_orgz_info, cur_num_sram,
|
||||
num_sram, sram_bits);
|
||||
|
||||
/* End */
|
||||
fprintf(fp, ".eom\n");
|
||||
|
||||
/* Back-annotate to logical block */
|
||||
if (NULL != mapped_logical_block) {
|
||||
mapped_logical_block->mapped_spice_model = spice_model;
|
||||
mapped_logical_block->mapped_spice_model_index = spice_model->cnt;
|
||||
}
|
||||
|
||||
/* Update the spice_model counter */
|
||||
spice_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
my_free(formatted_subckt_prefix);
|
||||
my_free(port_prefix);
|
||||
my_free(sram_vdd_port_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
void fprint_pb_primitive_ff(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
|
||||
void fprint_pb_primitive_hardlogic(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void fprint_pb_primitive_io(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model);
|
|
@ -1,326 +0,0 @@
|
|||
/***********************************/
|
||||
/* Synthesizable Verilog Dumping */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "vpr_utils.h"
|
||||
#include "path_delay.h"
|
||||
#include "stats.h"
|
||||
|
||||
/* Include FPGA-SPICE utils */
|
||||
#include "read_xml_spice_util.h"
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_spice_backannotate_utils.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "fpga_spice_bitstream.h"
|
||||
#include "verilog_modelsim_autodeck.h"
|
||||
|
||||
/* Include SynVerilog headers */
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_utils.h"
|
||||
#include "verilog_submodules.h"
|
||||
#include "verilog_decoder.h"
|
||||
#include "verilog_pbtypes.h"
|
||||
#include "verilog_routing.h"
|
||||
#include "verilog_top_netlist.h"
|
||||
#include "verilog_autocheck_tb.h"
|
||||
|
||||
|
||||
/***** Subroutines *****/
|
||||
/* Alloc array that records Configuration bits for :
|
||||
* (1) Switch blocks
|
||||
* (2) Connection boxes
|
||||
* TODO: Can be improved in alloc strategy to be more memory efficient!
|
||||
*/
|
||||
static
|
||||
void alloc_global_routing_conf_bits() {
|
||||
int i;
|
||||
|
||||
/* Alloc array for Switch blocks */
|
||||
num_conf_bits_sb = (int**)my_malloc((nx+1)*sizeof(int*));
|
||||
for (i = 0; i < (nx + 1); i++) {
|
||||
num_conf_bits_sb[i] = (int*)my_calloc((ny+1), sizeof(int));
|
||||
}
|
||||
|
||||
/* Alloc array for Connection blocks */
|
||||
num_conf_bits_cbx = (int**)my_malloc((nx+1)*sizeof(int*));
|
||||
for (i = 0; i < (nx + 1); i++) {
|
||||
num_conf_bits_cbx[i] = (int*)my_calloc((ny+1), sizeof(int));
|
||||
}
|
||||
|
||||
num_conf_bits_cby = (int**)my_malloc((nx+1)*sizeof(int*));
|
||||
for (i = 0; i < (nx + 1); i++) {
|
||||
num_conf_bits_cby[i] = (int*)my_calloc((ny+1), sizeof(int));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void free_global_routing_conf_bits() {
|
||||
int i;
|
||||
|
||||
/* Free array for Switch blocks */
|
||||
for (i = 0; i < (nx + 1); i++) {
|
||||
my_free(num_conf_bits_sb[i]);
|
||||
}
|
||||
my_free(num_conf_bits_sb);
|
||||
|
||||
/* Free array for Connection box */
|
||||
for (i = 0; i < (nx + 1); i++) {
|
||||
my_free(num_conf_bits_cbx[i]);
|
||||
}
|
||||
my_free(num_conf_bits_cbx);
|
||||
|
||||
for (i = 0; i < (nx + 1); i++) {
|
||||
my_free(num_conf_bits_cby[i]);
|
||||
}
|
||||
my_free(num_conf_bits_cby);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Top-level function*/
|
||||
void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
|
||||
t_arch Arch,
|
||||
char* circuit_name) {
|
||||
/* Timer */
|
||||
clock_t t_start;
|
||||
clock_t t_end;
|
||||
float run_time_sec;
|
||||
|
||||
int num_clocks = Arch.spice->spice_params.stimulate_params.num_clocks;
|
||||
/* int vpr_crit_path_delay = Arch.spice->spice_params.stimulate_params.vpr_crit_path_delay; */
|
||||
|
||||
/* Directory paths */
|
||||
char* verilog_dir_formatted = NULL;
|
||||
char* submodule_dir_path= NULL;
|
||||
char* lb_dir_path = NULL;
|
||||
char* rr_dir_path = NULL;
|
||||
char* top_netlist_file = NULL;
|
||||
char* top_netlist_path = NULL;
|
||||
char* bitstream_file_name = NULL;
|
||||
char* bitstream_file_path = NULL;
|
||||
char* hex_file_name = NULL;
|
||||
char* hex_file_path = NULL;
|
||||
char* top_testbench_file_name = NULL;
|
||||
char* top_auto_testbench_file_name = NULL;
|
||||
char* top_auto_preconf_testbench_file_name = NULL;
|
||||
char* top_testbench_file_path = NULL;
|
||||
char* top_auto_testbench_file_path = NULL;
|
||||
char* top_auto_preconf_testbench_file_path = NULL;
|
||||
char* blif_testbench_file_name = NULL;
|
||||
char* blif_testbench_file_path = NULL;
|
||||
|
||||
char* chomped_parent_dir = NULL;
|
||||
char* chomped_circuit_name = NULL;
|
||||
|
||||
boolean tb_preconf = TRUE;
|
||||
|
||||
/* Check if the routing architecture we support*/
|
||||
if (UNI_DIRECTIONAL != vpr_setup.RoutingArch.directionality) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable Verilog dumping only support uni-directional routing architecture!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* We don't support mrFPGA */
|
||||
#ifdef MRFPGA_H
|
||||
if (is_mrFPGA) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "FPGA synthesizable verilog dumping do not support mrFPGA!\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
assert ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog);
|
||||
|
||||
/* VerilogGenerator formally starts*/
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\nFPGA synthesizable verilog generator starts...\n");
|
||||
|
||||
/* Start time count */
|
||||
t_start = clock();
|
||||
|
||||
/* Format the directory paths */
|
||||
split_path_prog_name(circuit_name, '/', &chomped_parent_dir, &chomped_circuit_name);
|
||||
|
||||
if (NULL != vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir) {
|
||||
verilog_dir_formatted = format_dir_path(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.syn_verilog_dump_dir);
|
||||
} else {
|
||||
verilog_dir_formatted = format_dir_path(my_strcat(format_dir_path(chomped_parent_dir),default_verilog_dir_name));
|
||||
}
|
||||
/* lb directory */
|
||||
(lb_dir_path) = my_strcat(verilog_dir_formatted, default_lb_dir_name);
|
||||
/* routing resources directory */
|
||||
(rr_dir_path) = my_strcat(verilog_dir_formatted, default_rr_dir_name);
|
||||
/* submodule_dir_path */
|
||||
(submodule_dir_path) = my_strcat(verilog_dir_formatted, default_submodule_dir_name);
|
||||
/* Top netlists dir_path */
|
||||
top_netlist_file = my_strcat(chomped_circuit_name, verilog_top_postfix);
|
||||
top_netlist_path = my_strcat(verilog_dir_formatted, top_netlist_file);
|
||||
bitstream_file_name = my_strcat(chomped_circuit_name, bitstream_verilog_file_postfix);
|
||||
bitstream_file_path = my_strcat(verilog_dir_formatted, bitstream_file_name);
|
||||
hex_file_name = my_strcat(chomped_circuit_name, hex_verilog_file_postfix);
|
||||
hex_file_path = my_strcat(verilog_dir_formatted, hex_file_name);
|
||||
top_testbench_file_name = my_strcat(chomped_circuit_name, top_testbench_verilog_file_postfix);
|
||||
top_testbench_file_path = my_strcat(verilog_dir_formatted, top_testbench_file_name);
|
||||
top_auto_testbench_file_name = my_strcat(chomped_circuit_name, top_auto_testbench_verilog_file_postfix);
|
||||
top_auto_testbench_file_path = my_strcat(verilog_dir_formatted, top_auto_testbench_file_name);
|
||||
top_auto_preconf_testbench_file_name = my_strcat(chomped_circuit_name, top_auto_preconf_testbench_verilog_file_postfix);
|
||||
top_auto_preconf_testbench_file_path = my_strcat(verilog_dir_formatted, top_auto_preconf_testbench_file_name);
|
||||
blif_testbench_file_name = my_strcat(chomped_circuit_name, blif_testbench_verilog_file_postfix);
|
||||
blif_testbench_file_path = my_strcat(verilog_dir_formatted, blif_testbench_file_name);
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(verilog_dir_formatted);
|
||||
create_dir_path(lb_dir_path);
|
||||
create_dir_path(rr_dir_path);
|
||||
create_dir_path(submodule_dir_path);
|
||||
|
||||
/* assign the global variable of SRAM model */
|
||||
assert(NULL != Arch.sram_inf.verilog_sram_inf_orgz); /* Check !*/
|
||||
sram_verilog_model = Arch.sram_inf.verilog_sram_inf_orgz->spice_model;
|
||||
sram_verilog_orgz_type = Arch.sram_inf.verilog_sram_inf_orgz->type;
|
||||
/* initialize the SRAM organization information struct */
|
||||
sram_verilog_orgz_info = alloc_one_sram_orgz_info();
|
||||
init_sram_orgz_info(sram_verilog_orgz_info, sram_verilog_orgz_type, sram_verilog_model, nx + 2, ny + 2);
|
||||
/* Check all the SRAM port is using the correct SRAM SPICE MODEL */
|
||||
config_spice_models_sram_port_spice_model(Arch.spice->num_spice_model,
|
||||
Arch.spice->spice_models,
|
||||
Arch.sram_inf.verilog_sram_inf_orgz->spice_model);
|
||||
|
||||
/* Assign global variables of input and output pads */
|
||||
iopad_verilog_model = find_iopad_spice_model(Arch.spice->num_spice_model, Arch.spice->spice_models);
|
||||
assert(NULL != iopad_verilog_model);
|
||||
|
||||
/* zero the counter of each spice_model */
|
||||
zero_spice_models_cnt(Arch.spice->num_spice_model, Arch.spice->spice_models);
|
||||
|
||||
/* Initialize the user-defined verilog netlists to be included */
|
||||
init_list_include_verilog_netlists(Arch.spice);
|
||||
|
||||
/* Initial global variables about configuration bits */
|
||||
alloc_global_routing_conf_bits();
|
||||
|
||||
/* Initialize the number of configuration bits of all the grids */
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Count the number of configuration bits, IO pads in each logic block...\n");
|
||||
/* init_grids_num_conf_bits(sram_verilog_orgz_type); */
|
||||
init_grids_num_conf_bits(sram_verilog_orgz_info);
|
||||
init_grids_num_iopads();
|
||||
/* init_grids_num_mode_bits(); */
|
||||
|
||||
/* Dump routing resources: switch blocks, connection blocks and channel tracks */
|
||||
dump_verilog_routing_resources(rr_dir_path, Arch, &vpr_setup.RoutingArch,
|
||||
num_rr_nodes, rr_node, rr_node_indices);
|
||||
|
||||
/* Dump logic blocks */
|
||||
dump_verilog_logic_blocks(lb_dir_path, &Arch);
|
||||
|
||||
/* Dump decoder modules only when memory bank is required */
|
||||
switch(sram_verilog_orgz_type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
/* Dump verilog decoder */
|
||||
dump_verilog_decoder(submodule_dir_path);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Dump internal structures of submodules */
|
||||
dump_verilog_submodules(submodule_dir_path, Arch, &vpr_setup.RoutingArch, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.include_timing, vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.init_sim);
|
||||
|
||||
/* Dump top-level verilog */
|
||||
dump_verilog_top_netlist(chomped_circuit_name, top_netlist_path, lb_dir_path, rr_dir_path,
|
||||
num_rr_nodes, rr_node, rr_node_indices, num_clocks, *(Arch.spice));
|
||||
|
||||
/* Dump SDC constraints */
|
||||
// dump_verilog_sdc_file();
|
||||
|
||||
/* dump verilog testbench only for top-level */
|
||||
if (( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_tb) || ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb)){
|
||||
if ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_tb){
|
||||
dump_verilog_top_testbench(chomped_circuit_name, top_testbench_file_path, num_clocks,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice));
|
||||
}
|
||||
// AA: to generate autocheck testbench but only one bitstream
|
||||
if ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb) {
|
||||
dump_verilog_top_auto_testbench(chomped_circuit_name, top_auto_testbench_file_path, num_clocks,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice),
|
||||
modelsim_auto_testbench_module_postfix);
|
||||
}
|
||||
// AA: to generate autocheck preconfigured testbench
|
||||
if (( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb) && (tb_preconf)) {
|
||||
dump_verilog_top_auto_preconf_testbench(chomped_circuit_name,
|
||||
top_auto_preconf_testbench_file_path,
|
||||
num_clocks,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
|
||||
*(Arch.spice),
|
||||
modelsim_auto_preconf_testbench_module_postfix,
|
||||
hex_file_path);
|
||||
dump_fpga_spice_hex(hex_file_path, chomped_circuit_name, sram_verilog_orgz_info);
|
||||
}
|
||||
/* Dump bitstream file */
|
||||
dump_fpga_spice_bitstream(bitstream_file_path, chomped_circuit_name, sram_verilog_orgz_info);
|
||||
}
|
||||
|
||||
|
||||
/* Output Modelsim Autodeck scripts */
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_modelsim_autodeck) {
|
||||
dump_verilog_modelsim_autodeck(sram_verilog_orgz_info, *(Arch.spice),
|
||||
Arch.spice->spice_params.meas_params.sim_num_clock_cycle,
|
||||
verilog_dir_formatted, chomped_circuit_name,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.modelsim_ini_path,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.include_timing,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.init_sim,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_tb,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_top_auto_tb,
|
||||
tb_preconf);
|
||||
}
|
||||
|
||||
/* dump verilog testbench only for input blif */
|
||||
if ( TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_input_blif_tb) {
|
||||
dump_verilog_input_blif_testbench(chomped_circuit_name, blif_testbench_file_path, num_clocks,
|
||||
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, *(Arch.spice));
|
||||
}
|
||||
|
||||
/* End time count */
|
||||
t_end = clock();
|
||||
|
||||
run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Synthesizable verilog dumping took %g seconds\n", run_time_sec);
|
||||
|
||||
/* Free global array */
|
||||
free_global_routing_conf_bits();
|
||||
|
||||
/* Free sram_orgz_info */
|
||||
free_sram_orgz_info(sram_verilog_orgz_info,
|
||||
sram_verilog_orgz_info->type,
|
||||
nx + 2, ny + 2);
|
||||
/* Free */
|
||||
my_free(verilog_dir_formatted);
|
||||
my_free(lb_dir_path);
|
||||
my_free(rr_dir_path);
|
||||
my_free(top_netlist_file);
|
||||
my_free(top_netlist_path);
|
||||
my_free(submodule_dir_path);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
|
||||
t_arch Arch,
|
||||
char* circuit_name);
|
|
@ -1,967 +0,0 @@
|
|||
/***********************************/
|
||||
/* Dump Synthesizable Veriolog */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "read_xml_spice_util.h"
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_spice_backannotate_utils.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "fpga_spice_bitstream.h"
|
||||
|
||||
/* Include verilog support headers*/
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_utils.h"
|
||||
#include "verilog_routing.h"
|
||||
#include "verilog_pbtypes.h"
|
||||
#include "verilog_decoder.h"
|
||||
#include "verilog_top_netlist.h"
|
||||
#include "verilog_autocheck_tb.h"
|
||||
|
||||
|
||||
/* Global varaiable only accessible in this source file*/
|
||||
static char* top_netlist_bl_enable_port_name = "en_bl";
|
||||
static char* top_netlist_wl_enable_port_name = "en_wl";
|
||||
static char* top_netlist_bl_data_in_port_name = "data_in";
|
||||
static char* top_netlist_addr_bl_port_name = "addr_bl";
|
||||
static char* top_netlist_addr_wl_port_name = "addr_wl";
|
||||
static char* top_netlist_array_bl_port_name = "bl_bus";
|
||||
static char* top_netlist_array_wl_port_name = "wl_bus";
|
||||
static char* top_netlist_array_blb_port_name = "blb_bus";
|
||||
static char* top_netlist_array_wlb_port_name = "wlb_bus";
|
||||
static char* top_netlist_reserved_bl_port_postfix = "_reserved_bl";
|
||||
static char* top_netlist_reserved_wl_port_postfix = "_reserved_wl";
|
||||
static char* top_netlist_normal_bl_port_postfix = "_bl";
|
||||
static char* top_netlist_normal_wl_port_postfix = "_wl";
|
||||
static char* top_netlist_normal_blb_port_postfix = "_blb";
|
||||
static char* top_netlist_normal_wlb_port_postfix = "_wlb";
|
||||
static char* top_netlist_scan_chain_head_prefix = "sc_in";
|
||||
|
||||
|
||||
static char* top_tb_reset_port_name = "greset";
|
||||
static char* top_tb_set_port_name = "gset";
|
||||
static char* top_tb_prog_reset_port_name = "prog_reset";
|
||||
static char* top_tb_prog_set_port_name = "prog_set";
|
||||
static char* top_tb_config_done_port_name = "config_done";
|
||||
static char* top_tb_op_clock_port_name = "op_clock";
|
||||
static char* top_tb_prog_clock_port_name = "prog_clock";
|
||||
static char* top_tb_inout_reg_postfix = "_reg";
|
||||
static char* top_tb_clock_reg_postfix = "_reg";
|
||||
|
||||
/* Local Subroutines declaration */
|
||||
|
||||
/******** Subroutines ***********/
|
||||
/** Top level function 2: Testbench for the top-level netlist
|
||||
* This testbench includes a top-level module of a mapped FPGA and voltage pulses
|
||||
*/
|
||||
static
|
||||
void dump_verilog_top_netlist_memory_bank_ports(FILE* fp,
|
||||
enum e_dump_verilog_port_type dump_port_type) {
|
||||
t_spice_model* mem_model = NULL;
|
||||
int num_array_bl, num_array_wl;
|
||||
int bl_decoder_size, wl_decoder_size;
|
||||
char split_sign;
|
||||
|
||||
split_sign = determine_verilog_generic_port_split_sign(dump_port_type);
|
||||
|
||||
/* Only accept two types of dump_port_type here! */
|
||||
assert((VERILOG_PORT_INPUT == dump_port_type)||(VERILOG_PORT_CONKT == dump_port_type));
|
||||
|
||||
/* Check */
|
||||
assert (sram_verilog_orgz_info->type == SPICE_SRAM_MEMORY_BANK);
|
||||
|
||||
/* A valid file handler */
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Depending on the memory technology*/
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
|
||||
assert(NULL != mem_model);
|
||||
|
||||
determine_verilog_blwl_decoder_size(sram_verilog_orgz_info,
|
||||
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
|
||||
|
||||
/* Depend on the memory technology */
|
||||
switch (mem_model->design_tech) {
|
||||
case SPICE_MODEL_DESIGN_CMOS:
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_bl_enable_port_name, 0, 0);
|
||||
fprintf(fp, "%c //--- BL enable port \n", split_sign);
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_wl_enable_port_name, 0, 0);
|
||||
fprintf(fp, "%c //--- WL enable port \n", split_sign);
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_bl_data_in_port_name, 0, 0);
|
||||
fprintf(fp, "%c //--- BL data input port \n", split_sign);
|
||||
break;
|
||||
case SPICE_MODEL_DESIGN_RRAM:
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_bl_enable_port_name, 0, 0);
|
||||
fprintf(fp, "%c //--- BL enable port \n", split_sign);
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_wl_enable_port_name, 0, 0);
|
||||
fprintf(fp, "%c //--- WL enable port \n", split_sign);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_addr_bl_port_name, bl_decoder_size - 1, 0);
|
||||
fprintf(fp, "%c //--- Address of bit lines \n", split_sign);
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_addr_wl_port_name, wl_decoder_size - 1, 0);
|
||||
fprintf(fp, " //--- Address of word lines \n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_testbench_global_ports(FILE* fp, t_llist* head,
|
||||
enum e_dump_verilog_port_type dump_port_type) {
|
||||
t_llist* temp = head;
|
||||
t_spice_model_port* cur_global_port = NULL;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
fprintf(fp, "//----- BEGIN Global ports -----\n");
|
||||
while(NULL != temp) {
|
||||
cur_global_port = (t_spice_model_port*)(temp->dptr);
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
cur_global_port->prefix, 0, cur_global_port->size - 1);
|
||||
fprintf(fp, ";\n");
|
||||
/* Go to the next */
|
||||
temp = temp->next;
|
||||
}
|
||||
fprintf(fp, "//----- END Global ports -----\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Connect a global port to a voltage stimuli */
|
||||
static
|
||||
void dump_verilog_top_testbench_wire_one_global_port_stimuli(FILE* fp, t_spice_model_port* cur_global_port,
|
||||
char* voltage_stimuli_port_name) {
|
||||
int ipin;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(NULL != cur_global_port);
|
||||
|
||||
for (ipin = 0; ipin < cur_global_port->size; ipin++) {
|
||||
fprintf(fp, "assign %s[%d] = ",
|
||||
cur_global_port->prefix, ipin);
|
||||
assert((0 == cur_global_port->default_val)||(1 == cur_global_port->default_val));
|
||||
if (1 == cur_global_port->default_val) {
|
||||
fprintf(fp, "~");
|
||||
}
|
||||
fprintf(fp, "%s;\n",
|
||||
voltage_stimuli_port_name);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_testbench_global_ports_stimuli(FILE* fp, t_llist* head) {
|
||||
t_llist* temp = head;
|
||||
t_spice_model_port* cur_global_port = NULL;
|
||||
int ipin;
|
||||
|
||||
/* Check the file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler.\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(fp, "//----- Connecting Global ports -----\n");
|
||||
while(NULL != temp) {
|
||||
cur_global_port = (t_spice_model_port*)(temp->dptr);
|
||||
/* Make sure this is a global port */
|
||||
assert(TRUE == cur_global_port->is_global);
|
||||
/* If this is a clock signal, connect to op_clock signal */
|
||||
if (SPICE_MODEL_PORT_CLOCK == cur_global_port->type) {
|
||||
/* Special for programming clock */
|
||||
if (TRUE == cur_global_port->is_prog) {
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_prog_clock_port_name);
|
||||
} else {
|
||||
assert(FALSE == cur_global_port->is_prog);
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_op_clock_port_name);
|
||||
}
|
||||
/* If this is a config_enable signal, connect to config_done signal */
|
||||
} else if (TRUE == cur_global_port->is_config_enable) {
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_prog_clock_port_name);
|
||||
/* If this is a set/reset signal, connect to global reset and set signals */
|
||||
} else if (TRUE == cur_global_port->is_reset) {
|
||||
/* Special for programming reset */
|
||||
if (TRUE == cur_global_port->is_prog) {
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_prog_reset_port_name);
|
||||
} else {
|
||||
assert(FALSE == cur_global_port->is_prog);
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_reset_port_name);
|
||||
}
|
||||
/* If this is a set/reset signal, connect to global reset and set signals */
|
||||
} else if (TRUE == cur_global_port->is_set) {
|
||||
/* Special for programming reset */
|
||||
if (TRUE == cur_global_port->is_prog) {
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_prog_set_port_name);
|
||||
} else {
|
||||
assert(FALSE == cur_global_port->is_prog);
|
||||
dump_verilog_top_testbench_wire_one_global_port_stimuli(fp, cur_global_port, top_tb_set_port_name);
|
||||
}
|
||||
} else {
|
||||
/* Other global signals stuck at the default values */
|
||||
for (ipin = 0; ipin < cur_global_port->size; ipin++) {
|
||||
fprintf(fp, "assign %s[%d] = 1'b%d;\n",
|
||||
cur_global_port->prefix, ipin, cur_global_port->default_val);
|
||||
}
|
||||
}
|
||||
/* Go to the next */
|
||||
temp = temp->next;
|
||||
}
|
||||
fprintf(fp, "//----- End Connecting Global ports -----\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_netlist_scan_chain_ports(FILE* fp,
|
||||
enum e_dump_verilog_port_type dump_port_type) {
|
||||
/* Only accept two types of dump_port_type here! */
|
||||
assert((VERILOG_PORT_INPUT == dump_port_type)||(VERILOG_PORT_CONKT == dump_port_type));
|
||||
|
||||
/* Check */
|
||||
assert (sram_verilog_orgz_info->type == SPICE_SRAM_SCAN_CHAIN);
|
||||
|
||||
/* A valid file handler */
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid File Handler!\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Only the head of scan-chain will be the primary input in the top-level netlist
|
||||
* TODO: we may have multiple scan-chains, their heads will be the primary outputs
|
||||
*/
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
top_netlist_scan_chain_head_prefix, 0, 0);
|
||||
fprintf(fp, " //---- Scan-chain head \n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_module_ports(FILE* fp,
|
||||
enum e_dump_verilog_port_type dump_port_type) {
|
||||
char* port_name = NULL;
|
||||
char split_sign;
|
||||
enum e_dump_verilog_port_type actual_dump_port_type;
|
||||
boolean dump_global_port_type = FALSE;
|
||||
|
||||
split_sign = determine_verilog_generic_port_split_sign(dump_port_type);
|
||||
|
||||
/* Only accept two types of dump_port_type here! */
|
||||
assert((VERILOG_PORT_INPUT == dump_port_type)||(VERILOG_PORT_CONKT == dump_port_type));
|
||||
|
||||
if (VERILOG_PORT_INPUT == dump_port_type) {
|
||||
dump_global_port_type = TRUE;
|
||||
}
|
||||
|
||||
/* dump global ports */
|
||||
if (0 < dump_verilog_global_ports(fp, global_ports_head, dump_global_port_type)) {
|
||||
fprintf(fp, "%c\n", split_sign);
|
||||
}
|
||||
/* Inputs and outputs of I/O pads */
|
||||
/* Inout Pads */
|
||||
assert(NULL != iopad_verilog_model);
|
||||
if ((NULL == iopad_verilog_model)
|
||||
||(iopad_verilog_model->cnt > 0)) {
|
||||
actual_dump_port_type = VERILOG_PORT_CONKT;
|
||||
if (VERILOG_PORT_INPUT == dump_port_type) {
|
||||
actual_dump_port_type = VERILOG_PORT_INOUT;
|
||||
}
|
||||
/* Malloc and assign port_name */
|
||||
port_name = (char*)my_malloc(sizeof(char)*(strlen(gio_inout_prefix) + strlen(iopad_verilog_model->prefix) + 1));
|
||||
sprintf(port_name, "%s%s", gio_inout_prefix, iopad_verilog_model->prefix);
|
||||
/* Dump a register port */
|
||||
dump_verilog_generic_port(fp, actual_dump_port_type,
|
||||
port_name, iopad_verilog_model->cnt - 1, 0);
|
||||
fprintf(fp, "%c //---FPGA inouts \n", split_sign);
|
||||
/* Free port_name */
|
||||
my_free(port_name);
|
||||
}
|
||||
|
||||
/* Configuration ports depend on the organization of SRAMs */
|
||||
switch(sram_verilog_orgz_info->type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
dump_verilog_generic_port(fp, dump_port_type,
|
||||
sram_verilog_model->prefix, sram_verilog_model->cnt - 1, 0);
|
||||
fprintf(fp, " //--- SRAM outputs \n");
|
||||
/* Definition ends */
|
||||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
dump_verilog_top_netlist_scan_chain_ports(fp, dump_port_type);
|
||||
/* Definition ends */
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
dump_verilog_top_netlist_memory_bank_ports(fp, dump_port_type);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_testbench_call_top_module(FILE* fp,
|
||||
char* circuit_name) {
|
||||
|
||||
/* Include defined top-level module */
|
||||
fprintf(fp, "//----- Device Under Test (DUT) ----\n");
|
||||
fprintf(fp, "//------Call defined Top-level Verilog Module -----\n");
|
||||
fprintf(fp, "%s_top U0 (\n", circuit_name);
|
||||
|
||||
dump_verilog_top_module_ports(fp, VERILOG_PORT_CONKT);
|
||||
|
||||
fprintf(fp, ");\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the number of configuration clock cycles for a top-level testbench
|
||||
* A valid configuration clock cycle is allocated for an element with
|
||||
* (1) SRAM_val=1;
|
||||
* (2) BL = 1 && WL = 1;
|
||||
* (3) BL = 1 && WL = 0 with a paired conf_bit;
|
||||
*/
|
||||
static
|
||||
int dump_verilog_top_testbench_find_num_config_clock_cycles(t_llist* head) {
|
||||
int cnt = 0;
|
||||
t_llist* temp = head;
|
||||
t_conf_bit_info* temp_conf_bit_info = NULL;
|
||||
|
||||
while (NULL != temp) {
|
||||
/* Fetch the conf_bit_info */
|
||||
temp_conf_bit_info = (t_conf_bit_info*)(temp->dptr);
|
||||
/* Check if conf_bit_info needs a clock cycle*/
|
||||
switch (sram_verilog_orgz_type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
cnt++;
|
||||
temp_conf_bit_info->index_in_top_tb = cnt;
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
cnt++;
|
||||
temp_conf_bit_info->index_in_top_tb = cnt;
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Go to the next */
|
||||
temp = temp->next;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_auto_testbench_ports(FILE* fp,
|
||||
char* circuit_name,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
char* postfix){
|
||||
int num_array_bl, num_array_wl;
|
||||
int bl_decoder_size, wl_decoder_size;
|
||||
int iblock, iopad_idx;
|
||||
t_spice_model* mem_model = NULL;
|
||||
char* port_name = NULL;
|
||||
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
|
||||
fprintf(fp, "`include \"%s\"\n", syn_verilog_opts.verilog_benchmark_file);
|
||||
fprintf(fp, "module %s;\n", my_strcat(circuit_name, postfix));
|
||||
/* Local wires */
|
||||
/* 1. reset, set, clock signals */
|
||||
/* 2. iopad signals */
|
||||
|
||||
/* Connect to defined signals */
|
||||
/* set and reset signals */
|
||||
fprintf(fp, "\n");
|
||||
dump_verilog_top_testbench_global_ports(fp, global_ports_head, VERILOG_PORT_WIRE);
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* TODO: dump each global signal as reg here */
|
||||
|
||||
/* Inputs and outputs of I/O pads */
|
||||
/* Inout Pads */
|
||||
assert(NULL != iopad_verilog_model);
|
||||
if ((NULL == iopad_verilog_model)
|
||||
||(iopad_verilog_model->cnt > 0)) {
|
||||
/* Malloc and assign port_name */
|
||||
port_name = (char*)my_malloc(sizeof(char)*(strlen(gio_inout_prefix) + strlen(iopad_verilog_model->prefix) + 1));
|
||||
sprintf(port_name, "%s%s", gio_inout_prefix, iopad_verilog_model->prefix);
|
||||
/* Dump a wired port */
|
||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
||||
port_name, iopad_verilog_model->cnt - 1, 0);
|
||||
fprintf(fp, "; //--- FPGA inouts \n");
|
||||
/* Free port_name */
|
||||
my_free(port_name);
|
||||
/* Malloc and assign port_name */
|
||||
port_name = (char*)my_malloc(sizeof(char)*(strlen(gio_inout_prefix) + strlen(iopad_verilog_model->prefix) + strlen(top_tb_inout_reg_postfix) + 1));
|
||||
sprintf(port_name, "%s%s%s", gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix);
|
||||
/* Dump a wired port */
|
||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
||||
port_name, iopad_verilog_model->cnt - 1, 0);
|
||||
fprintf(fp, "; //--- reg for FPGA inouts \n");
|
||||
/* Free port_name */
|
||||
my_free(port_name);
|
||||
}
|
||||
|
||||
/* Add a signal to identify the configuration phase is finished */
|
||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_config_done_port_name);
|
||||
/* Programming clock */
|
||||
fprintf(fp, "wire [0:0] %s;\n", top_tb_prog_clock_port_name);
|
||||
fprintf(fp, "reg [0:0] %s%s;\n", top_tb_prog_clock_port_name, top_tb_clock_reg_postfix);
|
||||
/* Operation clock */
|
||||
fprintf(fp, "wire [0:0] %s;\n", top_tb_op_clock_port_name);
|
||||
fprintf(fp, "reg [0:0] %s%s;\n", top_tb_op_clock_port_name, top_tb_clock_reg_postfix);
|
||||
/* Programming set and reset */
|
||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_prog_reset_port_name);
|
||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_prog_set_port_name);
|
||||
/* Global set and reset */
|
||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_reset_port_name);
|
||||
fprintf(fp, "reg [0:0] %s;\n", top_tb_set_port_name);
|
||||
/* Generate stimuli for global ports or connect them to existed signals */
|
||||
dump_verilog_top_testbench_global_ports_stimuli(fp, global_ports_head);
|
||||
|
||||
/* Configuration ports depend on the organization of SRAMs */
|
||||
switch(sram_verilog_orgz_info->type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
dump_verilog_generic_port(fp, VERILOG_PORT_WIRE,
|
||||
sram_verilog_model->prefix, sram_verilog_model->cnt - 1, 0);
|
||||
fprintf(fp, "; //---- SRAM outputs \n");
|
||||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
/* We put the head of scan-chains here
|
||||
*/
|
||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
||||
top_netlist_scan_chain_head_prefix, 0, 0);
|
||||
fprintf(fp, "; //---- Scan-chain head \n");
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
/* Get the number of array BLs/WLs, decoder sizes */
|
||||
determine_verilog_blwl_decoder_size(sram_verilog_orgz_info,
|
||||
&num_array_bl, &num_array_wl, &bl_decoder_size, &wl_decoder_size);
|
||||
|
||||
fprintf(fp, " wire [0:0] %s;\n",
|
||||
top_netlist_bl_enable_port_name
|
||||
);
|
||||
fprintf(fp, " wire [0:0] %s;\n",
|
||||
top_netlist_wl_enable_port_name
|
||||
);
|
||||
/* Wire en_bl, en_wl to prog_clock */
|
||||
fprintf(fp, "assign %s[0:0] = %s[0:0];\n",
|
||||
top_netlist_bl_enable_port_name,
|
||||
top_tb_prog_clock_port_name);
|
||||
fprintf(fp, "assign %s [0:0]= %s[0:0];\n",
|
||||
top_netlist_wl_enable_port_name,
|
||||
top_tb_prog_clock_port_name);
|
||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
||||
top_netlist_addr_bl_port_name, bl_decoder_size - 1, 0);
|
||||
fprintf(fp, "; //--- Address of bit lines \n");
|
||||
dump_verilog_generic_port(fp, VERILOG_PORT_REG,
|
||||
top_netlist_addr_wl_port_name, wl_decoder_size - 1, 0);
|
||||
fprintf(fp, "; //--- Address of word lines \n");
|
||||
/* data_in is only require by BL decoder of SRAM array
|
||||
* As for RRAM array, the data_in signal will not be used
|
||||
*/
|
||||
if (SPICE_MODEL_DESIGN_CMOS == mem_model->design_tech) {
|
||||
fprintf(fp, " reg [0:0] %s; // --- Data_in signal for BL decoder, only required by SRAM array \n",
|
||||
top_netlist_bl_data_in_port_name);
|
||||
}
|
||||
/* I add all the Bit lines and Word lines here just for testbench usage
|
||||
fprintf(fp, " input wire [%d:0] %s_out; //--- Bit lines \n",
|
||||
sram_verilog_model->cnt - 1, sram_verilog_model->prefix);
|
||||
fprintf(fp, " input wire [%d:0] %s_outb; //--- Word lines \n",
|
||||
sram_verilog_model->cnt - 1, sram_verilog_model->prefix);
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid type of SRAM organization in Verilog Generator!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Add signals from blif benchmark and short-wire them to FPGA I/O PADs
|
||||
* This brings convenience to checking functionality
|
||||
*/
|
||||
fprintf(fp, "//-----Link Blif Benchmark inputs to FPGA IOPADs -----\n");
|
||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
||||
/* General INOUT*/
|
||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
||||
/* Make sure We find the correct logical block !*/
|
||||
assert((VPACK_INPAD == logical_block[iblock].type)||(VPACK_OUTPAD == logical_block[iblock].type));
|
||||
fprintf(fp, "//----- Blif Benchmark inout %s is mapped to FPGA IOPAD %s[%d] -----\n",
|
||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
||||
if(VPACK_INPAD == logical_block[iblock].type){
|
||||
fprintf(fp, "wire in_%s_%s_%d_;\n",
|
||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
||||
fprintf(fp, "assign in_%s_%s_%d_ = %s%s[%d];\n",
|
||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx,
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx);
|
||||
} else{
|
||||
fprintf(fp, "wire %s_%s_%d_;\n",
|
||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
||||
fprintf(fp, "assign %s_%s_%d_ = %s%s[%d];\n",
|
||||
logical_block[iblock].name, gio_inout_prefix, iopad_idx,
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx);
|
||||
fprintf(fp, "wire %s_benchmark;\n", logical_block[iblock].name);
|
||||
fprintf(fp, "reg %s_verification;\n", logical_block[iblock].name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_auto_testbench_call_benchmark(FILE* fp, char* blif_circuit_name){
|
||||
int iblock, iopad_idx;
|
||||
fprintf(fp, "// Benchmark instanciation\n");
|
||||
fprintf(fp, " %s Benchmark(\n", blif_circuit_name);
|
||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
||||
/* General INOUT*/
|
||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
||||
/* Make sure We find the correct logical block !*/
|
||||
assert((VPACK_INPAD == logical_block[iblock].type)||(VPACK_OUTPAD == logical_block[iblock].type));
|
||||
if(iblock>0){
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
if(TRUE == logical_block[iblock].is_clock){
|
||||
fprintf(fp, " %s", top_tb_op_clock_port_name);
|
||||
} else if(VPACK_INPAD == logical_block[iblock].type){
|
||||
fprintf(fp, " in_%s_%s_%d_", logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
||||
} else if(VPACK_OUTPAD == logical_block[iblock].type){
|
||||
fprintf(fp, " %s_benchmark", logical_block[iblock].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fp, " );\n");
|
||||
fprintf(fp, "// End Benchmark instanciation\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_auto_testbench_check(FILE* fp){
|
||||
int iblock, iopad_idx;
|
||||
fprintf(fp, " // Begin checking\n");
|
||||
fprintf(fp, " always@(negedge %s) begin\n", top_tb_op_clock_port_name);
|
||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
||||
/* Make sure We find the correct logical block !*/
|
||||
assert((VPACK_INPAD == logical_block[iblock].type)||(VPACK_OUTPAD == logical_block[iblock].type));
|
||||
if(VPACK_OUTPAD == logical_block[iblock].type){
|
||||
fprintf(fp, " %s_verification <= %s_benchmark ^ %s_%s_%d_ ;\n", logical_block[iblock].name, logical_block[iblock].name, logical_block[iblock].name, gio_inout_prefix, iopad_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(fp, " end\n\n");
|
||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
||||
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
|
||||
iopad_idx = logical_block[iblock].mapped_spice_model_index;
|
||||
/* Make sure We find the correct logical block !*/
|
||||
assert((VPACK_INPAD == logical_block[iblock].type)||(VPACK_OUTPAD == logical_block[iblock].type));
|
||||
if(VPACK_OUTPAD == logical_block[iblock].type){
|
||||
fprintf(fp, " always@(posedge %s_verification) begin\n", logical_block[iblock].name);
|
||||
fprintf(fp, " if(%s_verification) begin\n", logical_block[iblock].name);
|
||||
fprintf(fp, " $display(\"Mismatch on %s_verification\");\n", logical_block[iblock].name);
|
||||
fprintf(fp, " $finish;\n");
|
||||
fprintf(fp, " end\n");
|
||||
fprintf(fp, " end\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_verilog_top_auto_testbench(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog,
|
||||
char* postfix) {
|
||||
FILE* fp = NULL;
|
||||
char* title = my_strcat("FPGA Verilog Testbench for Top-level netlist of Design: ", circuit_name);
|
||||
|
||||
/* Check if the path exists*/
|
||||
fp = fopen(top_netlist_name,"w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create top Verilog testbench %s!",__FILE__, __LINE__, top_netlist_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Autochecked Testbench for FPGA Top-level Verilog netlist for %s...\n", circuit_name);
|
||||
|
||||
/* Print the title */
|
||||
dump_verilog_file_header(fp, title);
|
||||
my_free(title);
|
||||
/* Start of testbench */
|
||||
dump_verilog_top_auto_testbench_ports(fp, circuit_name, syn_verilog_opts, postfix);
|
||||
|
||||
/* Call defined top-level module */
|
||||
dump_verilog_top_testbench_call_top_module(fp, circuit_name);
|
||||
|
||||
/* Call defined benchmark */
|
||||
dump_verilog_top_auto_testbench_call_benchmark(fp, blif_circuit_name);
|
||||
|
||||
/* Add stimuli for reset, set, clock and iopad signals */
|
||||
dump_verilog_top_testbench_stimuli(fp, num_clock, syn_verilog_opts, verilog);
|
||||
|
||||
/* Add output autocheck */
|
||||
dump_verilog_top_auto_testbench_check(fp);
|
||||
|
||||
/* Testbench ends*/
|
||||
fprintf(fp, "endmodule\n");
|
||||
|
||||
/* Close the file*/
|
||||
fclose(fp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void dump_verilog_top_preconf_testbench_stimuli(FILE* fp,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog,
|
||||
char* hex_file_path,
|
||||
t_spice spice) {
|
||||
int inet, iblock, iopad_idx;
|
||||
int found_mapped_inpad = 0;
|
||||
t_spice_model* scff_mem_model = NULL;
|
||||
/* Find Input Pad Spice model */
|
||||
t_spice_net_info* cur_spice_net_info = NULL;
|
||||
int iscff, num_scffs;
|
||||
float prog_clock_period = (1./spice.spice_params.stimulate_params.prog_clock_freq);
|
||||
float op_clock_period = (1./spice.spice_params.stimulate_params.op_clock_freq);
|
||||
|
||||
num_scffs = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &scff_mem_model);
|
||||
|
||||
fprintf(fp, " // Loading configuration as initial state\n");
|
||||
fprintf(fp, "integer count;\n");
|
||||
fprintf(fp, "integer file;\n");
|
||||
fprintf(fp, "reg[0:%d] tmp;\n\n", (num_scffs - 1));
|
||||
fprintf(fp, "initial begin\n");
|
||||
fprintf(fp, " file = $fopen(\"%s\", \"r\");\n", hex_file_path);
|
||||
fprintf(fp, " for(count = %d; count > -1 ; count = count - 1) begin\n", (num_scffs - 1));
|
||||
fprintf(fp, " tmp[count] = $fgetc(file);\n");
|
||||
fprintf(fp, " end\n");
|
||||
fprintf(fp, " $signal_force(\"U0/%s_scff_out\", tmp, 0, 1, , 1);\n", scff_mem_model->prefix );
|
||||
fprintf(fp, " $fclose(file);\n");
|
||||
fprintf(fp, "end\n");
|
||||
fprintf(fp, " // End loading configuration as initial state\n\n");
|
||||
|
||||
/* config_done signal: indicate when configuration is finished */
|
||||
fprintf(fp, "//----- %s ----\n", top_tb_config_done_port_name);
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- CONFIG_DONE GENERATOR\n");
|
||||
fprintf(fp, " %s = 1'b0;\n", top_tb_config_done_port_name);
|
||||
fprintf(fp, " //----- %s signal is enabled after 50ns delay ----\n",
|
||||
top_tb_config_done_port_name);
|
||||
fprintf(fp, " #50 %s = 1'b1;\n", top_tb_config_done_port_name);
|
||||
fprintf(fp, " end\n");
|
||||
fprintf(fp, "//----- END of %s ----\n",
|
||||
top_tb_config_done_port_name);
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Generate stimilus of programming clock */
|
||||
fprintf(fp, "//----- Raw Programming clock ----\n");
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- PROG_CLOCK INITIALIZATION\n");
|
||||
fprintf(fp, " %s%s = 1'b0;\n", top_tb_prog_clock_port_name, top_tb_clock_reg_postfix);
|
||||
fprintf(fp, " end\n");
|
||||
fprintf(fp, "//----- END of Programming clock ----\n");
|
||||
fprintf(fp, "\n");
|
||||
/* Programming is already done
|
||||
*/
|
||||
fprintf(fp, "//---- Actual programming clock is triggered only when %s and %s are disabled\n",
|
||||
top_tb_config_done_port_name,
|
||||
top_tb_prog_reset_port_name);
|
||||
fprintf(fp, " assign %s = %s%s & (~%s) & (~%s);\n",
|
||||
top_tb_prog_clock_port_name,
|
||||
top_tb_prog_clock_port_name, top_tb_clock_reg_postfix,
|
||||
top_tb_config_done_port_name,
|
||||
top_tb_prog_reset_port_name);
|
||||
/*
|
||||
fprintf(fp, " assign %s = %s%s & (~%s);\n",
|
||||
top_tb_prog_clock_port_name,
|
||||
top_tb_prog_clock_port_name, top_tb_clock_reg_postfix,
|
||||
top_tb_config_done_port_name);
|
||||
*/
|
||||
fprintf(fp, "//----- END of Actual Programming clock ----\n");
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Generate stimilus of programming clock */
|
||||
fprintf(fp, "//----- Raw Operation clock ----\n");
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- OP_CLOCK INITIALIZATION\n");
|
||||
fprintf(fp, " %s%s = 1'b0;\n", top_tb_op_clock_port_name, top_tb_clock_reg_postfix);
|
||||
fprintf(fp, " end\n");
|
||||
fprintf(fp, "always wait(~%s)\n", top_tb_reset_port_name);
|
||||
fprintf(fp, " begin //--- OP_CLOCK GENERATOR\n");
|
||||
fprintf(fp, " #%.2f %s%s = ~%s%s;\n",
|
||||
0.5*op_clock_period / verilog_sim_timescale,
|
||||
top_tb_op_clock_port_name, top_tb_clock_reg_postfix,
|
||||
top_tb_op_clock_port_name, top_tb_clock_reg_postfix);
|
||||
fprintf(fp, " end\n");
|
||||
fprintf(fp, "//----- END of Operation clock ----\n");
|
||||
/* Operation clock should be enabled after programming phase finishes.
|
||||
* Before configuration is done (config_done is enabled), operation clock should be always zero.
|
||||
*/
|
||||
fprintf(fp, "//---- Actual operation clock is triggered only when %s is enabled \n",
|
||||
top_tb_config_done_port_name);
|
||||
fprintf(fp, " assign %s = %s%s & (%s);\n",
|
||||
top_tb_op_clock_port_name,
|
||||
top_tb_op_clock_port_name, top_tb_clock_reg_postfix,
|
||||
top_tb_config_done_port_name);
|
||||
fprintf(fp, "//----- END of Actual Operation clock ----\n");
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Reset signal for configuration circuit : only enable during the first clock cycle in programming phase */
|
||||
fprintf(fp, "//----- Programming Reset Stimuli ----\n");
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- PROGRAMMING RESET GENERATOR\n");
|
||||
fprintf(fp, " %s = 1'b0;\n", top_tb_prog_reset_port_name);
|
||||
/* Reset is disenabled to avoid configuration reset */
|
||||
fprintf(fp, "end\n");
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Set signal for configuration circuit : only enable during the first clock cycle in programming phase */
|
||||
fprintf(fp, "//----- Programming set Stimuli ----\n");
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- PROGRAMMING SET GENERATOR\n");
|
||||
fprintf(fp, "%s = 1'b0;\n", top_tb_prog_set_port_name);
|
||||
fprintf(fp, "//----- Programming set signal is always disabled -----\n");
|
||||
fprintf(fp, "end\n");
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* reset signals: only enabled during the first clock cycle in operation phase */
|
||||
fprintf(fp, "//----- Reset Stimuli ----\n");
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- RESET GENERATOR\n");
|
||||
fprintf(fp, " %s = 1'b1;\n", top_tb_reset_port_name);
|
||||
/* Reset is enabled until the first clock cycle in operation phase */
|
||||
fprintf(fp, "//----- Reset signal is enabled until the first clock cycle in operation phase ----\n");
|
||||
fprintf(fp, "wait(%s);\n",
|
||||
top_tb_config_done_port_name);
|
||||
fprintf(fp, "#%.2f %s = 1'b1;\n",
|
||||
(1 * op_clock_period)/ verilog_sim_timescale,
|
||||
top_tb_reset_port_name);
|
||||
fprintf(fp, "#%.2f %s = 1'b0;\n",
|
||||
(2 * op_clock_period) / verilog_sim_timescale,
|
||||
top_tb_reset_port_name);
|
||||
fprintf(fp, "end\n");
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* set signals */
|
||||
fprintf(fp, "//----- Set Stimuli ----\n");
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- SET GENERATOR\n");
|
||||
fprintf(fp, "%s = 1'b0;\n", top_tb_set_port_name);
|
||||
fprintf(fp, "//----- Set signal is always disabled -----\n");
|
||||
fprintf(fp, "end\n");
|
||||
fprintf(fp, "\n");
|
||||
|
||||
/* Inputs stimuli: BL/WL address lines */
|
||||
//dump_verilog_top_testbench_conf_bits_serial(fp, sram_verilog_orgz_info->conf_bit_head);
|
||||
|
||||
/* For each input_signal
|
||||
* TODO: this part is low-efficent for run-time concern... Need improve
|
||||
*/
|
||||
assert(NULL != iopad_verilog_model);
|
||||
for (iopad_idx = 0; iopad_idx < iopad_verilog_model->cnt; iopad_idx++) {
|
||||
/* Find if this inpad is mapped to a logical block */
|
||||
found_mapped_inpad = 0;
|
||||
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
|
||||
/* Bypass OUTPAD: donot put any voltage stimuli */
|
||||
/* Make sure We find the correct logical block !*/
|
||||
if ((iopad_verilog_model == logical_block[iblock].mapped_spice_model)
|
||||
&&(iopad_idx == logical_block[iblock].mapped_spice_model_index)) {
|
||||
/* Output PAD only need a short connection */
|
||||
if (VPACK_OUTPAD == logical_block[iblock].type) {
|
||||
fprintf(fp, "//----- Output %s does not need a Stimuli ----\n", logical_block[iblock].name);
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- Input %s[%d] GENERATOR\n", gio_inout_prefix, iopad_idx);
|
||||
fprintf(fp, " %s%s%s[%d] = 1'b%d;\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
verilog_default_signal_init_value);
|
||||
fprintf(fp, "end\n");
|
||||
found_mapped_inpad = 1;
|
||||
break;
|
||||
}
|
||||
/* Input PAD only need a short connection */
|
||||
assert(VPACK_INPAD == logical_block[iblock].type);
|
||||
cur_spice_net_info = NULL;
|
||||
for (inet = 0; inet < num_nets; inet++) {
|
||||
if (0 == strcmp(clb_net[inet].name, logical_block[iblock].name)) {
|
||||
cur_spice_net_info = clb_net[inet].spice_net_info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(NULL != cur_spice_net_info);
|
||||
assert(!(0 > cur_spice_net_info->density));
|
||||
assert(!(1 < cur_spice_net_info->density));
|
||||
assert(!(0 > cur_spice_net_info->probability));
|
||||
assert(!(1 < cur_spice_net_info->probability));
|
||||
/* Connect the reg to inouts */
|
||||
fprintf(fp, "//----- Input %s Stimuli ----\n", logical_block[iblock].name);
|
||||
fprintf(fp, "assign %s%s[%d] = %s%s%s[%d];\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx,
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx);
|
||||
/* Get the net information */
|
||||
/* TODO: Give the net name in the blif file !*/
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- Input %s GENERATOR\n", logical_block[iblock].name);
|
||||
fprintf(fp, " %s%s%s[%d] = 1'b%d;\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
cur_spice_net_info->init_val);
|
||||
fprintf(fp, "end\n");
|
||||
fprintf(fp, "always wait (~%s)\n", top_tb_reset_port_name);
|
||||
fprintf(fp, " begin \n");
|
||||
fprintf(fp, " %s%s%s[%d] = ~%s%s%s[%d];\n #%.2f\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
(op_clock_period * 2 * ((int)(cur_spice_net_info->probability / cur_spice_net_info->density)+ iblock) / verilog_sim_timescale));
|
||||
fprintf(fp, " %s%s%s[%d] = ~%s%s%s[%d];\n #%.2f;\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
(op_clock_period * 2 * ((int)((cur_spice_net_info->density / cur_spice_net_info->probability) * 2.5 + iblock)) / verilog_sim_timescale));
|
||||
fprintf(fp, " end \n");
|
||||
fprintf(fp, "\n");
|
||||
found_mapped_inpad++;
|
||||
}
|
||||
}
|
||||
assert((0 == found_mapped_inpad)||(1 == found_mapped_inpad));
|
||||
/* If we find one iopad already, we finished in this round here */
|
||||
if (1 == found_mapped_inpad) {
|
||||
continue;
|
||||
}
|
||||
/* if we cannot find any mapped inpad from tech.-mapped netlist, give a default */
|
||||
/* Connect the reg to inouts */
|
||||
fprintf(fp, "//----- Input %s[%d] Stimuli ----\n", gio_inout_prefix, iopad_idx);
|
||||
fprintf(fp, "assign %s%s[%d] = %s%s%s[%d];\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, iopad_idx,
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx);
|
||||
/* TODO: Give the net name in the blif file !*/
|
||||
fprintf(fp, "initial\n");
|
||||
fprintf(fp, " begin //--- Input %s[%d] GENERATOR\n", gio_inout_prefix, iopad_idx);
|
||||
fprintf(fp, " %s%s%s[%d] = 1'b%d;\n",
|
||||
gio_inout_prefix, iopad_verilog_model->prefix, top_tb_inout_reg_postfix, iopad_idx,
|
||||
verilog_default_signal_init_value);
|
||||
fprintf(fp, "end\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_verilog_top_auto_preconf_testbench(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog,
|
||||
char* postfix,
|
||||
char* hex_file_path) {
|
||||
FILE* fp = NULL;
|
||||
char* title = my_strcat("FPGA Verilog Testbench for Top-level netlist of Design: ", circuit_name);
|
||||
|
||||
/* Check if the path exists*/
|
||||
fp = fopen(top_netlist_name,"w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create top Verilog testbench %s!",__FILE__, __LINE__, top_netlist_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Autocheked and Preconfigured Testbench for FPGA Top-level Verilog netlist for %s...\n", circuit_name);
|
||||
|
||||
/* Print the title */
|
||||
dump_verilog_file_header(fp, title);
|
||||
my_free(title);
|
||||
|
||||
/* Start of testbench */
|
||||
dump_verilog_top_auto_testbench_ports(fp, circuit_name, syn_verilog_opts, postfix);
|
||||
|
||||
/* Call defined top-level module */
|
||||
dump_verilog_top_testbench_call_top_module(fp, circuit_name);
|
||||
|
||||
/* Call defined benchmark */
|
||||
dump_verilog_top_auto_testbench_call_benchmark(fp, blif_circuit_name);
|
||||
|
||||
/* Add stimuli for reset, set, clock and iopad signals */
|
||||
dump_verilog_top_preconf_testbench_stimuli(fp, num_clock, syn_verilog_opts, verilog, hex_file_path, verilog);
|
||||
|
||||
/* Add output autocheck */
|
||||
dump_verilog_top_auto_testbench_check(fp);
|
||||
|
||||
/* Testbench ends*/
|
||||
fprintf(fp, "endmodule\n");
|
||||
|
||||
/* Close the file*/
|
||||
fclose(fp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_fpga_spice_hex(char* hex_file_path,
|
||||
char* chomped_circuit_name,
|
||||
t_sram_orgz_info* sram_verilog_orgz_info) {
|
||||
FILE* fp = NULL;
|
||||
t_llist* temp = sram_verilog_orgz_info->conf_bit_head;
|
||||
t_conf_bit_info* cur_conf_bit_info = NULL;
|
||||
|
||||
fp = fopen(hex_file_path, "w");
|
||||
while (NULL != temp) {
|
||||
cur_conf_bit_info = (t_conf_bit_info*)(temp->dptr);
|
||||
fprintf(fp, "%d", cur_conf_bit_info->sram_bit->val);
|
||||
temp = temp->next;
|
||||
}
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
void dump_verilog_top_auto_testbench(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog,
|
||||
char* postfix);
|
||||
|
||||
|
||||
void dump_verilog_top_auto_preconf_testbench(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog,
|
||||
char* postfix,
|
||||
char* hex_file_path);
|
||||
|
||||
void dump_fpga_spice_hex(char* hex_file_path,
|
||||
char* chomped_circuit_name,
|
||||
t_sram_orgz_info* sram_verilog_orgz_info);
|
|
@ -1,230 +0,0 @@
|
|||
/***********************************/
|
||||
/* Synthesizable Verilog Dumping */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "vpr_utils.h"
|
||||
#include "path_delay.h"
|
||||
#include "stats.h"
|
||||
|
||||
/* Include FPGA-SPICE utils */
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "spice_mux.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
|
||||
/* Include verilog utils */
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_utils.h"
|
||||
|
||||
/***** Subroutines *****/
|
||||
void determine_verilog_blwl_decoder_size(INP t_sram_orgz_info* cur_sram_verilog_orgz_info,
|
||||
OUTP int* num_array_bl, OUTP int* num_array_wl,
|
||||
OUTP int* bl_decoder_size, OUTP int* wl_decoder_size) {
|
||||
t_spice_model* mem_model = NULL;
|
||||
int num_mem_bit;
|
||||
int num_reserved_bl, num_reserved_wl;
|
||||
|
||||
/* Check */
|
||||
assert(SPICE_SRAM_MEMORY_BANK == sram_verilog_orgz_info->type);
|
||||
|
||||
num_mem_bit = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
get_sram_orgz_info_num_blwl(sram_verilog_orgz_info, num_array_bl, num_array_wl);
|
||||
get_sram_orgz_info_reserved_blwl(sram_verilog_orgz_info, &num_reserved_bl, &num_reserved_wl);
|
||||
|
||||
/* Sizes of decodes depend on the Memory technology */
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
|
||||
switch (mem_model->design_tech) {
|
||||
/* CMOS SRAM*/
|
||||
case SPICE_MODEL_DESIGN_CMOS:
|
||||
/* SRAMs can efficiently share BLs and WLs,
|
||||
* Actual number of BLs and WLs will be sqrt(num_bls) and sqrt(num_wls)
|
||||
*/
|
||||
assert(0 == num_reserved_bl);
|
||||
assert(0 == num_reserved_wl);
|
||||
(*num_array_bl) = ceil(sqrt(*num_array_bl));
|
||||
(*num_array_wl) = ceil(sqrt(*num_array_wl));
|
||||
(*bl_decoder_size) = determine_decoder_size(*num_array_bl);
|
||||
(*wl_decoder_size) = determine_decoder_size(*num_array_wl);
|
||||
break;
|
||||
/* RRAM */
|
||||
case SPICE_MODEL_DESIGN_RRAM:
|
||||
/* Currently we do not have more efficient way to share the BLs and WLs as CMOS SRAMs */
|
||||
(*bl_decoder_size) = determine_decoder_size(*num_array_bl);
|
||||
(*wl_decoder_size) = determine_decoder_size(*num_array_wl);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology [CMOS|RRAM] for memory technology!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_verilog_decoder(char* submodule_dir) {
|
||||
int num_array_bl, num_array_wl;
|
||||
int bl_decoder_size, wl_decoder_size;
|
||||
FILE* fp = NULL;
|
||||
t_spice_model* mem_model = NULL;
|
||||
boolean bl_inverted = FALSE;
|
||||
boolean wl_inverted = FALSE;
|
||||
|
||||
char* verilog_name = my_strcat(submodule_dir, decoders_verilog_file_name);
|
||||
|
||||
/* Print the muxes netlist*/
|
||||
fp = fopen(verilog_name, "w");
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(FILE:%s,LINE[%d])Failure in create decoder SPICE netlist %s",__FILE__, __LINE__, verilog_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check */
|
||||
assert(SPICE_SRAM_MEMORY_BANK == sram_verilog_orgz_info->type);
|
||||
|
||||
/* Get number of BLs,WLs and decoder sizes */
|
||||
determine_verilog_blwl_decoder_size(sram_verilog_orgz_info,
|
||||
&num_array_bl, &num_array_wl,
|
||||
&bl_decoder_size, &wl_decoder_size);
|
||||
|
||||
/* Generate file header*/
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Writing Decoder verilog netlist...\n");
|
||||
|
||||
/* Generate the descriptions*/
|
||||
dump_verilog_file_header(fp, " Verilog Decoders");
|
||||
|
||||
/* Different design technology requires different BL decoder logic */
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
|
||||
/* Find if we need an inversion of the BL */
|
||||
check_mem_model_blwl_inverted(mem_model, SPICE_MODEL_PORT_BL, &bl_inverted);
|
||||
check_mem_model_blwl_inverted(mem_model, SPICE_MODEL_PORT_WL, &wl_inverted);
|
||||
|
||||
switch (mem_model->design_tech) {
|
||||
case SPICE_MODEL_DESIGN_CMOS: /* CMOS SRAM*/
|
||||
/* SRAM technology requires its BL decoder has an additional input called data_in
|
||||
* only the selected BL will be set to the value of data_in, other BLs will be in high-resistance state
|
||||
*/
|
||||
/* Start the BL decoder module definition */
|
||||
fprintf(fp, "//----- BL Decoder convert %d bits to binary %d bits -----\n",
|
||||
bl_decoder_size, num_array_bl);
|
||||
fprintf(fp, "module bl_decoder%dto%d (\n",
|
||||
bl_decoder_size, num_array_bl);
|
||||
fprintf(fp, "input wire enable,\n");
|
||||
fprintf(fp, "input wire [%d:0] addr_in,\n",
|
||||
bl_decoder_size - 1);
|
||||
fprintf(fp, "input wire data_in,\n");
|
||||
fprintf(fp, "output reg [0:%d] addr_out\n",
|
||||
num_array_bl - 1);
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Wee need to know the default value of bl port and wl port */
|
||||
|
||||
/* Internal logics */
|
||||
|
||||
fprintf(fp, "always@(addr_out,addr_in,enable, data_in)\n");
|
||||
fprintf(fp, "begin\n");
|
||||
fprintf(fp, "\taddr_out = %d'bz;\n", num_array_bl);
|
||||
fprintf(fp, "\tif (1'b1 == enable) begin\n");
|
||||
fprintf(fp, "\t\taddr_out[addr_in] = data_in;\n");
|
||||
fprintf(fp, "\tend\n");
|
||||
fprintf(fp, "end\n");
|
||||
|
||||
fprintf(fp, "endmodule\n");
|
||||
break;
|
||||
case SPICE_MODEL_DESIGN_RRAM: /* RRAM */
|
||||
/* For RRAM technology, BL decoder should be same as the WL decoder */
|
||||
/* Start the BL decoder module definition */
|
||||
fprintf(fp, "//----- BL Decoder convert %d bits to binary %d bits -----\n",
|
||||
bl_decoder_size, num_array_bl);
|
||||
fprintf(fp, "module bl_decoder%dto%d (\n",
|
||||
bl_decoder_size, num_array_bl);
|
||||
fprintf(fp, "input wire enable,\n");
|
||||
fprintf(fp, "input wire [%d:0] addr_in,\n",
|
||||
bl_decoder_size-1);
|
||||
fprintf(fp, "output reg [0:%d] addr_out\n",
|
||||
num_array_bl-1);
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Internal logics */
|
||||
fprintf(fp, "always@(addr_out,addr_in,enable)\n");
|
||||
fprintf(fp, "begin\n");
|
||||
if (TRUE == bl_inverted) {
|
||||
fprintf(fp, "\taddr_out = %d'b1;\n", num_array_bl);
|
||||
} else {
|
||||
assert (FALSE == bl_inverted);
|
||||
fprintf(fp, "\taddr_out = %d'b0;\n", num_array_bl);
|
||||
}
|
||||
fprintf(fp, "\tif (1'b1 == enable) begin\n");
|
||||
if (TRUE == bl_inverted) {
|
||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b0;\n");
|
||||
} else {
|
||||
assert (FALSE == bl_inverted);
|
||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b1;\n");
|
||||
}
|
||||
fprintf(fp, "\tend\n");
|
||||
fprintf(fp, "end\n");
|
||||
|
||||
fprintf(fp, "endmodule\n");
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid design technology [CMOS|RRAM] for memory technology!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* WL decoder logic is the same whatever SRAM or RRAM technology is considered */
|
||||
/* Start the WL module definition */
|
||||
fprintf(fp, "//----- WL Decoder convert %d bits to binary %d bits -----\n",
|
||||
wl_decoder_size, num_array_wl);
|
||||
fprintf(fp, "module wl_decoder%dto%d (\n",
|
||||
wl_decoder_size, num_array_wl);
|
||||
fprintf(fp, "input wire enable,\n");
|
||||
fprintf(fp, "input wire [%d:0] addr_in,\n",
|
||||
wl_decoder_size-1);
|
||||
fprintf(fp, "output reg [0:%d] addr_out\n",
|
||||
num_array_bl-1);
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Internal logics */
|
||||
fprintf(fp, "always@(addr_out,addr_in,enable)\n");
|
||||
fprintf(fp, "begin\n");
|
||||
if (TRUE == wl_inverted) {
|
||||
fprintf(fp, "\taddr_out = %d'b1;\n", num_array_wl);
|
||||
} else {
|
||||
assert (FALSE == wl_inverted);
|
||||
fprintf(fp, "\taddr_out = %d'b0;\n", num_array_wl);
|
||||
}
|
||||
fprintf(fp, "\tif (1'b1 == enable) begin\n");
|
||||
if (TRUE == wl_inverted) {
|
||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b0;\n");
|
||||
} else {
|
||||
assert (FALSE == wl_inverted);
|
||||
fprintf(fp, "\t\taddr_out[addr_in] = 1'b1;\n");
|
||||
}
|
||||
fprintf(fp, "\tend\n");
|
||||
fprintf(fp, "end\n");
|
||||
|
||||
fprintf(fp, "endmodule\n");
|
||||
|
||||
/* Close the file*/
|
||||
fclose(fp);
|
||||
|
||||
/* Add fname to the linked list */
|
||||
submodule_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(submodule_verilog_subckt_file_path_head, verilog_name);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
|
||||
void determine_verilog_blwl_decoder_size(INP t_sram_orgz_info* cur_sram_verilog_orgz_info,
|
||||
OUTP int* num_array_bl, OUTP int* num_array_wl,
|
||||
OUTP int* bl_decoder_size, OUTP int* wl_decoder_size);
|
||||
|
||||
void dump_verilog_decoder(char* submodule_dir);
|
|
@ -1,75 +0,0 @@
|
|||
/***********************************/
|
||||
/* Synthesizable Verilog Dumping */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include "spice_types.h"
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "verilog_global.h"
|
||||
|
||||
char* verilog_netlist_file_postfix = ".v";
|
||||
float verilog_sim_timescale = 1e-9; // Verilog Simulation time scale (minimum time unit) : 1ns
|
||||
char* verilog_timing_preproc_flag = "ENABLE_TIMING"; // the flag to enable timing definition during compilation
|
||||
char* verilog_init_sim_preproc_flag = "INITIALIZATION"; // the flag to enable initialization during simulation
|
||||
|
||||
char* default_verilog_dir_name = "syn_verilogs/";
|
||||
char* default_lb_dir_name = "lb/";
|
||||
char* default_rr_dir_name = "routing/";
|
||||
char* default_submodule_dir_name = "sub_module/";
|
||||
char* default_modelsim_dir_name = "msim_projects/";
|
||||
|
||||
char* modelsim_project_name_postfix = "_fpga_msim";
|
||||
char* modelsim_proc_script_name_postfix = "_proc.tcl";
|
||||
char* modelsim_top_script_name_postfix = "_runsim.tcl";
|
||||
char* modelsim_testbench_module_postfix = "_top_tb";
|
||||
char* modelsim_auto_testbench_module_postfix = "_top_auto_tb";
|
||||
char* modelsim_auto_preconf_testbench_module_postfix = "_top_auto_preconf_tb";
|
||||
char* modelsim_simulation_time_unit = "ns";
|
||||
|
||||
char* verilog_top_postfix = "_top.v";
|
||||
char* bitstream_verilog_file_postfix = ".bitstream";
|
||||
char* hex_verilog_file_postfix = ".hex";
|
||||
char* top_testbench_verilog_file_postfix = "_top_tb.v";
|
||||
char* top_auto_testbench_verilog_file_postfix = "_top_auto_tb.v";
|
||||
char* top_auto_preconf_testbench_verilog_file_postfix = "_top_auto_preconf_tb.v";
|
||||
char* blif_testbench_verilog_file_postfix = "_blif_tb.v";
|
||||
char* submodule_verilog_file_name = "sub_module.v";
|
||||
char* logic_block_verilog_file_name = "logic_blocks.v";
|
||||
char* luts_verilog_file_name = "luts.v";
|
||||
char* routing_verilog_file_name = "routing.v";
|
||||
char* sub_module_verilog_file_name = "sub_module.v";
|
||||
char* muxes_verilog_file_name = "muxes.v";
|
||||
char* wires_verilog_file_name = "wires.v";
|
||||
char* essentials_verilog_file_name = "inv_buf_passgate.v";
|
||||
char* decoders_verilog_file_name = "decoders.v";
|
||||
|
||||
char* verilog_mux_basis_posfix = "_basis";
|
||||
char* verilog_mux_special_basis_posfix = "_special_basis";
|
||||
|
||||
/* Prefix for subckt Verilog netlists */
|
||||
char* grid_verilog_file_name_prefix = "grid_";
|
||||
char* chanx_verilog_file_name_prefix = "chanx_";
|
||||
char* chany_verilog_file_name_prefix = "chany_";
|
||||
char* sb_verilog_file_name_prefix = "sb_";
|
||||
char* cbx_verilog_file_name_prefix = "cbx_";
|
||||
char* cby_verilog_file_name_prefix = "cby_";
|
||||
|
||||
/* SRAM SPICE MODEL should be set as global*/
|
||||
t_spice_model* sram_verilog_model = NULL;
|
||||
enum e_sram_orgz sram_verilog_orgz_type = SPICE_SRAM_STANDALONE;
|
||||
t_sram_orgz_info* sram_verilog_orgz_info = NULL;
|
||||
|
||||
/* Input and Output Pad spice model. should be set as global */
|
||||
t_spice_model* iopad_verilog_model = NULL;
|
||||
|
||||
/* Linked-list that stores all the configuration bits */
|
||||
t_llist* conf_bits_head = NULL;
|
||||
|
||||
/* Linked-list that stores submodule Verilog file mames */
|
||||
t_llist* grid_verilog_subckt_file_path_head = NULL;
|
||||
t_llist* routing_verilog_subckt_file_path_head = NULL;
|
||||
t_llist* submodule_verilog_subckt_file_path_head = NULL;
|
||||
|
||||
|
||||
int verilog_default_signal_init_value = 0;
|
|
@ -1,77 +0,0 @@
|
|||
/* global parameters for dumping synthesizable verilog */
|
||||
|
||||
extern char* verilog_netlist_file_postfix;
|
||||
extern float verilog_sim_timescale;
|
||||
extern char* verilog_timing_preproc_flag; // the flag to enable timing definition during compilation
|
||||
extern char* verilog_init_sim_preproc_flag; // the flag to enable initialization during simulation
|
||||
|
||||
extern char* default_verilog_dir_name;
|
||||
extern char* default_lb_dir_name;
|
||||
extern char* default_rr_dir_name;
|
||||
extern char* default_submodule_dir_name;
|
||||
extern char* default_modelsim_dir_name;
|
||||
|
||||
extern char* modelsim_project_name_postfix;
|
||||
extern char* modelsim_proc_script_name_postfix;
|
||||
extern char* modelsim_top_script_name_postfix;
|
||||
extern char* modelsim_testbench_module_postfix;
|
||||
extern char* modelsim_auto_testbench_module_postfix;
|
||||
extern char* modelsim_auto_preconf_testbench_module_postfix;
|
||||
extern char* modelsim_simulation_time_unit;
|
||||
|
||||
extern char* verilog_top_postfix;
|
||||
extern char* bitstream_verilog_file_postfix;
|
||||
extern char* hex_verilog_file_postfix;
|
||||
extern char* top_testbench_verilog_file_postfix;
|
||||
extern char* top_auto_testbench_verilog_file_postfix;
|
||||
extern char* top_auto_preconf_testbench_verilog_file_postfix;
|
||||
extern char* blif_testbench_verilog_file_postfix;
|
||||
extern char* submodule_verilog_file_name;
|
||||
extern char* logic_block_verilog_file_name;
|
||||
extern char* luts_verilog_file_name;
|
||||
extern char* routing_verilog_file_name;
|
||||
extern char* sub_module_verilog_file_name;
|
||||
extern char* muxes_verilog_file_name;
|
||||
extern char* muxes_verilog_file_name;
|
||||
extern char* wires_verilog_file_name;
|
||||
extern char* essentials_verilog_file_name;
|
||||
extern char* decoders_verilog_file_name;
|
||||
extern char* verilog_mux_basis_posfix;
|
||||
extern char* verilog_mux_special_basis_posfix;
|
||||
|
||||
/* Prefix for subckt Verilog netlists */
|
||||
extern char* grid_verilog_file_name_prefix;
|
||||
extern char* chanx_verilog_file_name_prefix;
|
||||
extern char* chany_verilog_file_name_prefix;
|
||||
extern char* sb_verilog_file_name_prefix;
|
||||
extern char* cbx_verilog_file_name_prefix;
|
||||
extern char* cby_verilog_file_name_prefix;
|
||||
|
||||
extern t_spice_model* sram_verilog_model;
|
||||
extern enum e_sram_orgz sram_verilog_orgz_type;
|
||||
extern t_sram_orgz_info* sram_verilog_orgz_info;
|
||||
|
||||
/* Input and Output Pad spice model. should be set as global */
|
||||
extern t_spice_model* inpad_verilog_model;
|
||||
extern t_spice_model* outpad_verilog_model;
|
||||
extern t_spice_model* iopad_verilog_model;
|
||||
|
||||
/* Linked-list that stores all the configuration bits */
|
||||
extern t_llist* conf_bits_head;
|
||||
|
||||
/* Linked-list that stores submodule Verilog file mames */
|
||||
extern t_llist* grid_verilog_subckt_file_path_head;
|
||||
extern t_llist* routing_verilog_subckt_file_path_head;
|
||||
extern t_llist* submodule_verilog_subckt_file_path_head;
|
||||
|
||||
|
||||
extern int verilog_default_signal_init_value;
|
||||
|
||||
enum e_dump_verilog_port_type {
|
||||
VERILOG_PORT_INPUT,
|
||||
VERILOG_PORT_OUTPUT,
|
||||
VERILOG_PORT_INOUT,
|
||||
VERILOG_PORT_WIRE,
|
||||
VERILOG_PORT_REG,
|
||||
VERILOG_PORT_CONKT
|
||||
};
|
|
@ -1,403 +0,0 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph_swseg.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
|
||||
/* Include verilog support headers*/
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_utils.h"
|
||||
#include "verilog_pbtypes.h"
|
||||
#include "verilog_lut.h"
|
||||
|
||||
|
||||
/***** Subroutines *****/
|
||||
void dump_verilog_pb_primitive_lut(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_pb* prim_pb,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* verilog_model,
|
||||
int lut_status,
|
||||
t_rr_node* pb_rr_graph) {
|
||||
int i;
|
||||
int* sram_bits = NULL; /* decoded SRAM bits */
|
||||
int truth_table_length = 0;
|
||||
char** truth_table = NULL;
|
||||
int lut_size = 0;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_sram_port = 0;
|
||||
t_spice_model_port** sram_ports = NULL;
|
||||
|
||||
int num_pb_type_input_port = 0;
|
||||
t_port** pb_type_input_ports = NULL;
|
||||
|
||||
int num_pb_type_output_port = 0;
|
||||
t_port** pb_type_output_ports = NULL;
|
||||
|
||||
char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* cur_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
int cur_num_sram = 0;
|
||||
int num_sram = 0;
|
||||
/* For each SRAM, we could have multiple BLs/WLs */
|
||||
int num_bl_ports = 0;
|
||||
t_spice_model_port** bl_port = NULL;
|
||||
int num_wl_ports = 0;
|
||||
t_spice_model_port** wl_port = NULL;
|
||||
int num_bl_per_sram = 0;
|
||||
int num_wl_per_sram = 0;
|
||||
int num_conf_bits = 0;
|
||||
int num_reserved_conf_bits = 0;
|
||||
int cur_bl, cur_wl;
|
||||
t_spice_model* mem_model = NULL;
|
||||
|
||||
int num_lut_pin_nets;
|
||||
int* lut_pin_net = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == cur_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid cur_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Asserts */
|
||||
assert(SPICE_MODEL_LUT == verilog_model->type);
|
||||
|
||||
/* Check if this is an idle logical block mapped*/
|
||||
switch (lut_status) {
|
||||
case PRIMITIVE_WIRED_LUT:
|
||||
assert(NULL != pb_rr_graph);
|
||||
if (NULL == mapped_logical_block) {
|
||||
/* Get the mapped vpack_net_num of this physical LUT pb */
|
||||
get_mapped_lut_pb_input_pin_vpack_net_num(cur_pb_graph_node, pb_rr_graph, &num_lut_pin_nets, &lut_pin_net);
|
||||
/* consider LUT pin remapping when assign lut truth tables */
|
||||
mapped_logical_block = &logical_block[get_pb_graph_node_wired_lut_logical_block_index(cur_pb_graph_node, pb_rr_graph)];
|
||||
/* Match truth table and post-routing results */
|
||||
truth_table = assign_post_routing_wired_lut_truth_table(mapped_logical_block,
|
||||
num_lut_pin_nets, lut_pin_net, &truth_table_length);
|
||||
} else {
|
||||
/* Give a special truth table */
|
||||
assert (VPACK_COMB == mapped_logical_block->type);
|
||||
/* Get the mapped vpack_net_num of this physical LUT pb */
|
||||
get_mapped_lut_pb_input_pin_vpack_net_num(cur_pb_graph_node, pb_rr_graph, &num_lut_pin_nets, &lut_pin_net);
|
||||
/* consider LUT pin remapping when assign lut truth tables */
|
||||
/* Match truth table and post-routing results */
|
||||
truth_table = assign_post_routing_wired_lut_truth_table(mapped_logical_block,
|
||||
num_lut_pin_nets, lut_pin_net, &truth_table_length);
|
||||
}
|
||||
break;
|
||||
case PRIMITIVE_IDLE:
|
||||
break;
|
||||
case PRIMITIVE_NORMAL:
|
||||
assert (NULL != mapped_logical_block);
|
||||
/* Back-annotate to logical block */
|
||||
mapped_logical_block->mapped_spice_model = verilog_model;
|
||||
mapped_logical_block->mapped_spice_model_index = verilog_model->cnt;
|
||||
|
||||
assert (VPACK_COMB == mapped_logical_block->type);
|
||||
/* Get the mapped vpack_net_num of this physical LUT pb */
|
||||
get_mapped_lut_pb_input_pin_vpack_net_num(cur_pb_graph_node, pb_rr_graph, &num_lut_pin_nets, &lut_pin_net);
|
||||
/* consider LUT pin remapping when assign lut truth tables */
|
||||
/* Match truth table and post-routing results */
|
||||
truth_table = assign_post_routing_lut_truth_table(mapped_logical_block,
|
||||
num_lut_pin_nets, lut_pin_net, &truth_table_length);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,
|
||||
"(FILE:%s, [LINE%d]) Invalid status(=%d) for LUT!\n",
|
||||
__FILE__, __LINE__, lut_status);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Determine size of LUT*/
|
||||
input_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
output_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
assert(1 == num_input_port);
|
||||
assert(1 == num_output_port);
|
||||
lut_size = input_ports[0]->size;
|
||||
assert(1 == output_ports[0]->size);
|
||||
/* Find SRAM ports */
|
||||
sram_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
||||
assert(1 == num_sram_port);
|
||||
/* Count the number of configuration bits */
|
||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
||||
/* Get memory model */
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
|
||||
|
||||
/* Find the number of BLs/WLs of each SRAM */
|
||||
switch (sram_verilog_orgz_type) {
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
/* Detect the SRAM SPICE model linked to this SRAM port */
|
||||
assert(NULL != sram_ports[0]->spice_model);
|
||||
assert(SPICE_MODEL_SRAM == sram_ports[0]->spice_model->type);
|
||||
find_bl_wl_ports_spice_model(sram_ports[0]->spice_model,
|
||||
&num_bl_ports, &bl_port, &num_wl_ports, &wl_port);
|
||||
assert(1 == num_bl_ports);
|
||||
assert(1 == num_wl_ports);
|
||||
num_bl_per_sram = bl_port[0]->size;
|
||||
num_wl_per_sram = wl_port[0]->size;
|
||||
/* Asserts */
|
||||
assert(num_bl_per_sram == num_wl_per_sram);
|
||||
break;
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Generate sram bits*/
|
||||
sram_bits = generate_lut_sram_bits(truth_table_length, truth_table,
|
||||
lut_size, sram_ports[0]->default_val);
|
||||
|
||||
/* Print the subckts*/
|
||||
cur_pb_type = cur_pb_graph_node->pb_type;
|
||||
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- LUT Verilog module: %s%s_%d_ -----\n",
|
||||
formatted_subckt_prefix, cur_pb_type->name, index);
|
||||
|
||||
/* Simplify the prefix, make the SPICE netlist readable*/
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(cur_pb_type->name) + 1 +
|
||||
strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s_%d_", cur_pb_type->name, index);
|
||||
|
||||
/* Subckt definition*/
|
||||
fprintf(fp, "module %s%s_%d_ (",
|
||||
formatted_subckt_prefix, cur_pb_type->name, index);
|
||||
fprintf(fp, "\n");
|
||||
/* Only dump the global ports belonging to a spice_model */
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* Print inputs, outputs, inouts, clocks, NO SRAMs*/
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, cur_pb_type, TRUE, TRUE);
|
||||
/* Print SRAM ports */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
get_sram_orgz_info_num_blwl(sram_verilog_orgz_info, &cur_bl, &cur_wl);
|
||||
/* connect to reserved BL/WLs ? */
|
||||
num_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model, sram_verilog_orgz_info->type, 0);
|
||||
/* Get the number of configuration bits required by this MUX */
|
||||
num_conf_bits = count_num_conf_bits_one_spice_model(verilog_model, sram_verilog_orgz_info->type, 0);
|
||||
/* Reserved sram ports */
|
||||
dump_verilog_reserved_sram_ports(fp, sram_verilog_orgz_info,
|
||||
0, num_reserved_conf_bits - 1,
|
||||
VERILOG_PORT_INPUT);
|
||||
if ( 0 < num_reserved_conf_bits) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* Normal sram ports */
|
||||
dump_verilog_sram_ports(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_conf_bits - 1,
|
||||
VERILOG_PORT_INPUT);
|
||||
/* Local Vdd and gnd*/
|
||||
fprintf(fp, ");\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Specify inputs are wires */
|
||||
pb_type_input_ports = find_pb_type_ports_match_spice_model_port_type(cur_pb_type, SPICE_MODEL_PORT_INPUT, &num_pb_type_input_port);
|
||||
assert(1 == num_pb_type_input_port);
|
||||
fprintf(fp, "wire [0:%d] %s__%s;\n",
|
||||
input_ports[0]->size - 1, port_prefix, pb_type_input_ports[0]->name);
|
||||
for (i = 0; i < input_ports[0]->size; i++) {
|
||||
fprintf(fp, "assign %s__%s[%d] = %s__%s_%d_;\n",
|
||||
port_prefix, pb_type_input_ports[0]->name, i,
|
||||
port_prefix, pb_type_input_ports[0]->name, i);
|
||||
}
|
||||
/* Specify outputs are wires */
|
||||
pb_type_output_ports = find_pb_type_ports_match_spice_model_port_type(cur_pb_type, SPICE_MODEL_PORT_OUTPUT, &num_pb_type_output_port);
|
||||
assert(1 == num_pb_type_output_port);
|
||||
fprintf(fp, "wire [0:%d] %s__%s;\n",
|
||||
output_ports[0]->size - 1, port_prefix, pb_type_output_ports[0]->name);
|
||||
for (i = 0; i < output_ports[0]->size; i++) {
|
||||
fprintf(fp, "assign %s__%s_%d_ = %s__%s[%d];\n",
|
||||
port_prefix, pb_type_output_ports[0]->name, i,
|
||||
port_prefix, pb_type_output_ports[0]->name, i);
|
||||
}
|
||||
|
||||
/* Specify SRAM output are wires */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
dump_verilog_sram_config_bus_internal_wires(fp, sram_verilog_orgz_info, cur_num_sram, cur_num_sram + num_sram - 1);
|
||||
/*
|
||||
fprintf(fp, "wire [%d:%d] %s_out;\n",
|
||||
cur_num_sram, cur_num_sram + num_sram - 1, mem_model->prefix);
|
||||
fprintf(fp, "wire [%d:%d] %s_outb;\n",
|
||||
cur_num_sram, cur_num_sram + num_sram - 1, mem_model->prefix);
|
||||
*/
|
||||
|
||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
|
||||
/* Call LUT subckt*/
|
||||
fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
||||
fprintf(fp, "\n");
|
||||
/* if we have to add global ports when dumping submodules of LUTs
|
||||
* otherwise, the port map here does not match that of submodules
|
||||
* Only dump the global ports belonging to a spice_model
|
||||
* DISABLE recursive here !
|
||||
*/
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* Connect inputs*/
|
||||
/* Connect outputs*/
|
||||
fprintf(fp, "//----- Input and output ports -----\n");
|
||||
dump_verilog_pb_type_bus_ports(fp, port_prefix, 0, cur_pb_type, FALSE, TRUE);
|
||||
fprintf(fp, "//----- SRAM ports -----\n");
|
||||
/* Connect srams: TODO: to find the SRAM model used by this Verilog model */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
/* TODO: switch depending on the type of configuration circuit */
|
||||
switch (sram_verilog_orgz_info->type) {
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
break;
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
dump_verilog_sram_one_port(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
||||
1, VERILOG_PORT_CONKT);
|
||||
fprintf(fp, ", ");
|
||||
dump_verilog_sram_one_outport(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
||||
1, VERILOG_PORT_CONKT);
|
||||
break;
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
dump_verilog_sram_one_outport(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
||||
0, VERILOG_PORT_CONKT);
|
||||
fprintf(fp, ", ");
|
||||
dump_verilog_sram_one_outport(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
||||
1, VERILOG_PORT_CONKT);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* vdd should be connected to special global wire gvdd_lut and gnd,
|
||||
* Every LUT has a special VDD for statistics
|
||||
*/
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Print the encoding in SPICE netlist for debugging */
|
||||
if (NULL != mapped_logical_block) {
|
||||
fprintf(fp, "//----- Truth Table for LUT node (%s). -----\n",
|
||||
mapped_logical_block->name);
|
||||
}
|
||||
fprintf(fp, "//----- Truth Table for LUT[%d], size=%d. -----\n",
|
||||
verilog_model->cnt, lut_size);
|
||||
for (i = 0; i < truth_table_length; i++) {
|
||||
fprintf(fp,"// %s \n", truth_table[i]);
|
||||
}
|
||||
|
||||
fprintf(fp, "//----- SRAM bits for LUT[%d], size=%d, num_sram=%d. -----\n",
|
||||
verilog_model->cnt, lut_size, num_sram);
|
||||
fprintf(fp, "//-----");
|
||||
fprint_commented_sram_bits(fp, num_sram, sram_bits);
|
||||
fprintf(fp, "-----\n");
|
||||
|
||||
/* Decode the SRAM bits to BL/WL bits. */
|
||||
switch (sram_verilog_orgz_type) {
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
/* TODO: should be more structural in coding !!! */
|
||||
/* Decode the SRAM bits to BL/WL bits.
|
||||
* first half part is BL, the other half part is WL
|
||||
*/
|
||||
decode_and_add_verilog_sram_membank_conf_bit_to_llist(sram_verilog_orgz_info, cur_num_sram + i,
|
||||
num_bl_per_sram, num_wl_per_sram,
|
||||
sram_bits[i]);
|
||||
}
|
||||
/* NUM_SRAM is set to be consistent with number of BL/WLs
|
||||
* TODO: NUM_SRAM should be the as they are.
|
||||
* Should use another variable i.e., num_bl
|
||||
*/
|
||||
break;
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
/* Store the configuraion bit to linked-list */
|
||||
add_mux_conf_bits_to_llist(0, sram_verilog_orgz_info,
|
||||
num_sram, sram_bits,
|
||||
verilog_model);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Call SRAM subckts only
|
||||
* when Configuration organization style is memory bank */
|
||||
/* No. of SRAMs is different from the number of configuration lines.
|
||||
* Especially when SRAMs/RRAMs are configured with BL/WLs
|
||||
*/
|
||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
/* Dump the configuration port bus */
|
||||
/*TODO: to be more smart!!! num_reserved_conf_bits and num_conf_bits/num_sram should be determined by each mem_bit */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
dump_verilog_mem_config_bus(fp, mem_model, sram_verilog_orgz_info,
|
||||
cur_num_sram, num_reserved_conf_bits, num_conf_bits/num_sram);
|
||||
/* This function should be called in the very end,
|
||||
* because we update the counter of mem_model after each sram submodule is dumped !!!
|
||||
*/
|
||||
dump_verilog_sram_submodule(fp, sram_verilog_orgz_info,
|
||||
mem_model); /* use the mem_model in sram_verilog_orgz_info */
|
||||
}
|
||||
|
||||
/* End of subckt*/
|
||||
fprintf(fp, "endmodule\n");
|
||||
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- END LUT Verilog module: %s%s_%d_ -----\n\n",
|
||||
formatted_subckt_prefix, cur_pb_type->name, index);
|
||||
|
||||
/* Update counter */
|
||||
verilog_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
my_free(formatted_subckt_prefix);
|
||||
my_free(input_ports);
|
||||
my_free(output_ports);
|
||||
my_free(sram_ports);
|
||||
my_free(sram_bits);
|
||||
my_free(port_prefix);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
void dump_verilog_pb_primitive_lut(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_pb* prim_pb,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* cur_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model,
|
||||
int lut_status,
|
||||
t_rr_node* pb_rr_graph);
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
void dump_verilog_modelsim_autodeck(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice spice,
|
||||
int num_operating_clock_cycles,
|
||||
char* verilog_dir_formatted,
|
||||
char* chomped_circuit_name,
|
||||
char* simulator_ini_path,
|
||||
boolean include_timing,
|
||||
boolean init_sim,
|
||||
boolean print_top_tb,
|
||||
boolean print_top_auto_tb,
|
||||
boolean tb_preconf);
|
||||
|
|
@ -1,514 +0,0 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph_swseg.h"
|
||||
#include "vpr_utils.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
|
||||
/* Include verilog support headers*/
|
||||
#include "verilog_global.h"
|
||||
#include "verilog_utils.h"
|
||||
#include "verilog_pbtypes.h"
|
||||
#include "verilog_primitives.h"
|
||||
|
||||
/* Subroutines */
|
||||
void dump_verilog_pb_primitive_ff(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* verilog_model) {
|
||||
int i;
|
||||
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_clock_port = 0;
|
||||
t_spice_model_port** clock_ports = NULL;
|
||||
|
||||
char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* prim_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == prim_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Find ports*/
|
||||
input_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INPUT, &num_input_port, FALSE);
|
||||
output_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
clock_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, FALSE);
|
||||
|
||||
/* Asserts */
|
||||
assert(3 == num_input_port); /* D, Set and Reset*/
|
||||
for (i = 0; i < num_input_port; i++) {
|
||||
assert(1 == input_ports[i]->size);
|
||||
}
|
||||
assert(1 == num_output_port);
|
||||
assert(1 == output_ports[0]->size);
|
||||
assert(1 == num_clock_port);
|
||||
assert(1 == clock_ports[0]->size);
|
||||
|
||||
assert(SPICE_MODEL_FF == verilog_model->type);
|
||||
|
||||
/* Initialize */
|
||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
||||
|
||||
/* Generate Subckt for pb_type*/
|
||||
/*
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(formatted_subckt_prefix) + strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s%s[%d]", formatted_subckt_prefix, prim_pb_type->name, index);
|
||||
*/
|
||||
/* Simplify the port prefix, make SPICE netlist readable */
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s_%d_", prim_pb_type->name, index);
|
||||
|
||||
|
||||
if (NULL != mapped_logical_block) {
|
||||
fprintf(fp, "//----- Flip-flop Verilog module: %s -----\n",
|
||||
mapped_logical_block->name);
|
||||
}
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- Flip-flop Verilog module: %s%s -----\n",
|
||||
formatted_subckt_prefix, port_prefix);
|
||||
/* Definition line */
|
||||
fprintf(fp, "module %s%s (", formatted_subckt_prefix, port_prefix);
|
||||
/* Only dump the global ports belonging to a spice_model */
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* print ports*/
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, TRUE, FALSE);
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, ");\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Call the dff subckt*/
|
||||
fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
||||
/* Only dump the global ports belonging to a spice_model */
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* print ports*/
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 1, prim_pb_type, FALSE, FALSE); /* Use global clock for each DFF...*/
|
||||
|
||||
/* Local vdd and gnd, verilog_model name
|
||||
* TODO: global vdd for ff
|
||||
*/
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Apply rising edge, and init value to the ff*/
|
||||
if (NULL != mapped_logical_block) {
|
||||
/* Back-annotate to logical block */
|
||||
mapped_logical_block->mapped_spice_model = verilog_model;
|
||||
mapped_logical_block->mapped_spice_model_index = verilog_model->cnt;
|
||||
}
|
||||
/* TODO: apply falling edge, initial value to FF!!!*/
|
||||
/*fprintf(fp, "\n");*/
|
||||
|
||||
/* End */
|
||||
fprintf(fp, "endmodule\n");
|
||||
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- END Flip-flop Verilog module: %s%s -----\n\n",
|
||||
formatted_subckt_prefix, port_prefix);
|
||||
|
||||
verilog_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
my_free(formatted_subckt_prefix);
|
||||
my_free(port_prefix);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print hardlogic SPICE subckt*/
|
||||
void dump_verilog_pb_primitive_hardlogic(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* verilog_model) {
|
||||
char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* prim_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == prim_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Asserts */
|
||||
assert(SPICE_MODEL_HARDLOGIC == verilog_model->type);
|
||||
|
||||
/* Initialize */
|
||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
||||
|
||||
/* Generate Subckt for pb_type*/
|
||||
/*
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(formatted_subckt_prefix) + strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s%s[%d]", formatted_subckt_prefix, prim_pb_type->name, index);
|
||||
*/
|
||||
/* Simplify the port prefix, make SPICE netlist readable */
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s_%d_", prim_pb_type->name, index);
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- Hardlogic Verilog module: %s%s -----\n",
|
||||
formatted_subckt_prefix, port_prefix);
|
||||
/* Definition line */
|
||||
fprintf(fp, "module %s%s (", formatted_subckt_prefix, port_prefix);
|
||||
fprintf(fp, "\n");
|
||||
/* Only dump the global ports belonging to a spice_model */
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* print ports*/
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, TRUE, FALSE);
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, ");\n");
|
||||
/* Definition ends*/
|
||||
|
||||
/* Back-annotate to logical block */
|
||||
if (NULL != mapped_logical_block) {
|
||||
mapped_logical_block->mapped_spice_model = verilog_model;
|
||||
mapped_logical_block->mapped_spice_model_index = verilog_model->cnt;
|
||||
}
|
||||
|
||||
/* Call the hardlogic subckt*/
|
||||
fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
||||
fprintf(fp, "\n");
|
||||
/* Only dump the global ports belonging to a spice_model */
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
/* print ports*/
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, FALSE, FALSE);
|
||||
/* Local vdd and gnd, verilog_model name,
|
||||
* Global vdd for hardlogic to split
|
||||
*/
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* End */
|
||||
fprintf(fp, "endmodule\n");
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- EDN Hardlogic Verilog module: %s%s -----\n",
|
||||
formatted_subckt_prefix, port_prefix);
|
||||
|
||||
verilog_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
free(formatted_subckt_prefix);
|
||||
free(port_prefix);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dump a I/O pad primitive node */
|
||||
void dump_verilog_pb_primitive_io(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* verilog_model) {
|
||||
int num_pad_port = 0; /* INOUT port */
|
||||
t_spice_model_port** pad_ports = NULL;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int num_output_port = 0;
|
||||
t_spice_model_port** output_ports = NULL;
|
||||
int num_clock_port = 0;
|
||||
t_spice_model_port** clock_ports = NULL;
|
||||
int num_sram_port = 0;
|
||||
t_spice_model_port** sram_ports = NULL;
|
||||
|
||||
int i;
|
||||
int num_sram = 0;
|
||||
int* sram_bits = NULL;
|
||||
|
||||
char* formatted_subckt_prefix = format_verilog_node_prefix(subckt_prefix); /* Complete a "_" at the end if needed*/
|
||||
t_pb_type* prim_pb_type = NULL;
|
||||
char* port_prefix = NULL;
|
||||
|
||||
/* For each SRAM, we could have multiple BLs/WLs */
|
||||
int num_bl_ports = 0;
|
||||
t_spice_model_port** bl_port = NULL;
|
||||
int num_wl_ports = 0;
|
||||
t_spice_model_port** wl_port = NULL;
|
||||
int num_bl_per_sram = 0;
|
||||
int num_wl_per_sram = 0;
|
||||
int expected_num_sram;
|
||||
|
||||
int cur_num_sram = 0;
|
||||
int num_conf_bits = 0;
|
||||
int num_reserved_conf_bits = 0;
|
||||
t_spice_model* mem_model = NULL;
|
||||
int cur_bl, cur_wl;
|
||||
|
||||
/* Ensure a valid file handler*/
|
||||
if (NULL == fp) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid file handler!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Ensure a valid pb_graph_node */
|
||||
if (NULL == prim_pb_graph_node) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid prim_pb_graph_node!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Find ports*/
|
||||
pad_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INOUT, &num_pad_port, TRUE);
|
||||
input_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
output_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_OUTPUT, &num_output_port, TRUE);
|
||||
clock_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_CLOCK, &num_clock_port, TRUE);
|
||||
sram_ports = find_spice_model_ports(verilog_model, SPICE_MODEL_PORT_SRAM, &num_sram_port, TRUE);
|
||||
|
||||
/* Asserts */
|
||||
assert(SPICE_MODEL_IOPAD == verilog_model->type); /* Support IO PAD which matches the physical design */
|
||||
|
||||
/* Initialize */
|
||||
get_sram_orgz_info_mem_model(sram_verilog_orgz_info, &mem_model);
|
||||
|
||||
prim_pb_type = prim_pb_graph_node->pb_type;
|
||||
|
||||
/* Generate Subckt for pb_type*/
|
||||
/* Simplify the port prefix, make SPICE netlist readable */
|
||||
port_prefix = (char*)my_malloc(sizeof(char)*
|
||||
(strlen(prim_pb_type->name) + 1
|
||||
+ strlen(my_itoa(index)) + 1 + 1));
|
||||
sprintf(port_prefix, "%s_%d_", prim_pb_type->name, index);
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- IO Verilog module: %s%s -----\n",
|
||||
formatted_subckt_prefix, port_prefix);
|
||||
/* Definition line */
|
||||
fprintf(fp, "module %s%s (", formatted_subckt_prefix, port_prefix);
|
||||
fprintf(fp, "\n");
|
||||
/* Only dump the global ports belonging to a spice_model
|
||||
*/
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, TRUE, TRUE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
|
||||
/* TODO: assert this is physical mode */
|
||||
assert((1 == num_sram_port)&&(NULL != sram_ports)&&(1 == sram_ports[0]->size));
|
||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
||||
/* Get current counter of mem_bits, bl and wl */
|
||||
cur_num_sram = get_sram_orgz_info_num_mem_bit(sram_verilog_orgz_info);
|
||||
get_sram_orgz_info_num_blwl(sram_verilog_orgz_info, &cur_bl, &cur_wl);
|
||||
/* print ports --> input ports */
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, TRUE, TRUE);
|
||||
/* Print output port */
|
||||
fprintf(fp, "inout [%d:%d] %s%s\n",
|
||||
verilog_model->cnt, verilog_model->cnt,
|
||||
gio_inout_prefix, verilog_model->prefix);
|
||||
/* Print SRAM ports */
|
||||
/* connect to reserved BL/WLs ? */
|
||||
num_reserved_conf_bits = count_num_reserved_conf_bits_one_spice_model(verilog_model, sram_verilog_orgz_info->type, 0);
|
||||
/* Get the number of configuration bits required by this MUX */
|
||||
num_conf_bits = count_num_conf_bits_one_spice_model(verilog_model, sram_verilog_orgz_info->type, 0);
|
||||
/* Reserved sram ports */
|
||||
if (0 < num_reserved_conf_bits) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
dump_verilog_reserved_sram_ports(fp, sram_verilog_orgz_info,
|
||||
0, num_reserved_conf_bits - 1,
|
||||
VERILOG_PORT_INPUT);
|
||||
/* Normal sram ports */
|
||||
if (0 < num_conf_bits) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
dump_verilog_sram_ports(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_sram - 1,
|
||||
VERILOG_PORT_INPUT);
|
||||
/* Local vdd and gnd*/
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
dump_verilog_sram_config_bus_internal_wires(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram + num_sram - 1);
|
||||
switch (sram_verilog_orgz_type) {
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
/* Local wires */
|
||||
/* Find the number of BLs/WLs of each SRAM */
|
||||
/* Detect the SRAM SPICE model linked to this SRAM port */
|
||||
assert(NULL != sram_ports[0]->spice_model);
|
||||
assert(SPICE_MODEL_SRAM == sram_ports[0]->spice_model->type);
|
||||
find_bl_wl_ports_spice_model(sram_ports[0]->spice_model,
|
||||
&num_bl_ports, &bl_port, &num_wl_ports, &wl_port);
|
||||
assert(1 == num_bl_ports);
|
||||
assert(1 == num_wl_ports);
|
||||
num_bl_per_sram = bl_port[0]->size;
|
||||
num_wl_per_sram = wl_port[0]->size;
|
||||
break;
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Definition ends*/
|
||||
|
||||
/* Dump the configuration port bus */
|
||||
dump_verilog_mem_config_bus(fp, mem_model, sram_verilog_orgz_info,
|
||||
cur_num_sram, num_reserved_conf_bits, num_conf_bits);
|
||||
|
||||
/* Call the I/O subckt*/
|
||||
fprintf(fp, "%s %s_%d_ (", verilog_model->name, verilog_model->prefix, verilog_model->cnt);
|
||||
fprintf(fp, "\n");
|
||||
/* Only dump the global ports belonging to a spice_model
|
||||
* Disable recursive here !
|
||||
*/
|
||||
if (0 < rec_dump_verilog_spice_model_global_ports(fp, verilog_model, FALSE, FALSE)) {
|
||||
fprintf(fp, ",\n");
|
||||
}
|
||||
|
||||
/* assert */
|
||||
assert((1 == num_sram_port)&&(NULL != sram_ports)&&(1 == sram_ports[0]->size));
|
||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
||||
/* print ports --> input ports */
|
||||
dump_verilog_pb_type_ports(fp, port_prefix, 0, prim_pb_type, FALSE, TRUE);
|
||||
/* Print inout port */
|
||||
fprintf(fp, "%s%s[%d], ", gio_inout_prefix,
|
||||
verilog_model->prefix, verilog_model->cnt);
|
||||
/* Print SRAM ports */
|
||||
/* Connect srams: TODO: to find the SRAM model used by this Verilog model */
|
||||
dump_verilog_sram_one_outport(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram,
|
||||
0, VERILOG_PORT_CONKT);
|
||||
fprintf(fp, ", ");
|
||||
dump_verilog_sram_one_outport(fp, sram_verilog_orgz_info,
|
||||
cur_num_sram, cur_num_sram,
|
||||
1, VERILOG_PORT_CONKT);
|
||||
|
||||
/* Local vdd and gnd, verilog_model name,
|
||||
* TODO: Global vdd for i/o pad to split?
|
||||
*/
|
||||
fprintf(fp, ");\n");
|
||||
|
||||
/* Call SRAM subckt */
|
||||
assert((1 == num_sram_port)&&(NULL != sram_ports)&&(1 == sram_ports[0]->size));
|
||||
/* what is the SRAM bit of a mode? */
|
||||
/* If logical block is not NULL, we need to decode the sram bit */
|
||||
if (NULL != mapped_logical_block) {
|
||||
assert(NULL != mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits);
|
||||
sram_bits = decode_mode_bits(mapped_logical_block->pb->pb_graph_node->pb_type->mode_bits, &expected_num_sram);
|
||||
assert(expected_num_sram == num_sram);
|
||||
} else {
|
||||
/* Initialize */
|
||||
sram_bits = (int*)my_calloc(num_sram, sizeof(int));
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
sram_bits[i] = sram_ports[0]->default_val;
|
||||
}
|
||||
}
|
||||
/* SRAM_bit will be later reconfigured according to operating mode */
|
||||
switch (sram_verilog_orgz_type) {
|
||||
case SPICE_SRAM_MEMORY_BANK:
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
/* Decode the SRAM bits to BL/WL bits.
|
||||
* first half part is BL, the other half part is WL
|
||||
*/
|
||||
decode_and_add_verilog_sram_membank_conf_bit_to_llist(sram_verilog_orgz_info, cur_num_sram + i,
|
||||
num_bl_per_sram, num_wl_per_sram,
|
||||
sram_bits[i]);
|
||||
}
|
||||
break;
|
||||
case SPICE_SRAM_STANDALONE:
|
||||
case SPICE_SRAM_SCAN_CHAIN:
|
||||
/* Store the configuraion bit to linked-list */
|
||||
add_mux_conf_bits_to_llist(0, sram_verilog_orgz_info,
|
||||
num_sram, sram_bits,
|
||||
verilog_model);
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid SRAM organization type!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
/* Call SRAM subckts only
|
||||
* when Configuration organization style is memory bank */
|
||||
num_sram = count_num_sram_bits_one_spice_model(verilog_model, -1);
|
||||
for (i = 0; i < num_sram; i++) {
|
||||
dump_verilog_sram_submodule(fp, sram_verilog_orgz_info,
|
||||
mem_model); /* use the mem_model in sram_verilog_orgz_info */
|
||||
}
|
||||
|
||||
/* End */
|
||||
fprintf(fp, "endmodule\n");
|
||||
/* Comment lines */
|
||||
fprintf(fp, "//----- END IO Verilog module: %s%s -----\n\n",
|
||||
formatted_subckt_prefix, port_prefix);
|
||||
|
||||
/* Back-annotate to logical block */
|
||||
if (NULL != mapped_logical_block) {
|
||||
mapped_logical_block->mapped_spice_model = verilog_model;
|
||||
mapped_logical_block->mapped_spice_model_index = verilog_model->cnt;
|
||||
}
|
||||
|
||||
/* Update the verilog_model counter */
|
||||
verilog_model->cnt++;
|
||||
|
||||
/*Free*/
|
||||
free(formatted_subckt_prefix);
|
||||
free(port_prefix);
|
||||
my_free(input_ports);
|
||||
my_free(output_ports);
|
||||
my_free(pad_ports);
|
||||
my_free(clock_ports);
|
||||
my_free(sram_ports);
|
||||
my_free(sram_bits);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
void dump_verilog_pb_primitive_ff(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
|
||||
void dump_verilog_pb_primitive_hardlogic(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void dump_verilog_pb_primitive_io(FILE* fp,
|
||||
char* subckt_prefix,
|
||||
t_logical_block* mapped_logical_block,
|
||||
t_pb_graph_node* prim_pb_graph_node,
|
||||
int index,
|
||||
t_spice_model* spice_model);
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
void dump_verilog_routing_chan_subckt(FILE* fp,
|
||||
int x, int y, t_rr_type chan_type,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_segment, t_segment_inf* segments);
|
||||
|
||||
void dump_verilog_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
|
||||
int pin_index, int side,
|
||||
int x, int y,
|
||||
boolean dump_port_type);
|
||||
|
||||
void dump_verilog_grid_side_pins(FILE* fp,
|
||||
t_rr_type pin_type, int x, int y, int side,
|
||||
boolean dump_port_type);
|
||||
|
||||
void dump_verilog_switch_box_chan_port(FILE* fp,
|
||||
t_sb* cur_sb_info,
|
||||
int chan_side,
|
||||
t_rr_node* cur_rr_node,
|
||||
enum PORTS cur_rr_node_direction);
|
||||
|
||||
void dump_verilog_switch_box_short_interc(FILE* fp,
|
||||
t_sb* cur_sb_info,
|
||||
int chan_side,
|
||||
t_rr_node* cur_rr_node,
|
||||
int actual_fan_in,
|
||||
t_rr_node* drive_rr_node);
|
||||
|
||||
void dump_verilog_switch_box_mux(FILE* fp,
|
||||
t_sb* cur_sb_info,
|
||||
int chan_side,
|
||||
t_rr_node* cur_rr_node,
|
||||
int mux_size,
|
||||
t_rr_node** drive_rr_nodes,
|
||||
int switch_index);
|
||||
|
||||
int count_verilog_switch_box_interc_conf_bits(t_sb cur_sb_info, int chan_side,
|
||||
t_rr_node* cur_rr_node);
|
||||
|
||||
int count_verilog_switch_box_interc_reserved_conf_bits(t_sb cur_sb_info, int chan_side,
|
||||
t_rr_node* cur_rr_node);
|
||||
|
||||
void dump_verilog_switch_box_interc(FILE* fp,
|
||||
t_sb* cur_sb_info,
|
||||
int chan_side,
|
||||
t_rr_node* cur_rr_node);
|
||||
|
||||
int count_verilog_switch_box_reserved_conf_bits(t_sb cur_sb_info);
|
||||
int count_verilog_switch_box_conf_bits(t_sb cur_sb_info);
|
||||
|
||||
void dump_verilog_routing_switch_box_subckt(FILE* fp, t_sb* cur_sb_info,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
||||
void dump_verilog_connection_box_short_interc(FILE* fp,
|
||||
t_cb* cur_cb_info,
|
||||
t_rr_node* src_rr_node);
|
||||
|
||||
void dump_verilog_connection_box_mux(FILE* fp,
|
||||
t_cb* cur_cb_info,
|
||||
t_rr_node* src_rr_node);
|
||||
|
||||
void dump_verilog_connection_box_interc(FILE* fp,
|
||||
t_cb* cur_cb_info,
|
||||
t_rr_node* src_rr_node);
|
||||
|
||||
|
||||
int count_verilog_connection_box_interc_conf_bits(t_rr_node* cur_rr_node);
|
||||
int count_verilog_connection_box_interc_reserved_conf_bits(t_rr_node* cur_rr_node);
|
||||
int count_verilog_connection_box_one_side_conf_bits(int num_ipin_rr_nodes,
|
||||
t_rr_node** ipin_rr_node);
|
||||
int count_verilog_connection_box_one_side_reserved_conf_bits(int num_ipin_rr_nodes,
|
||||
t_rr_node** ipin_rr_node);
|
||||
int count_verilog_connection_box_conf_bits(t_cb* cur_cb_info);
|
||||
int count_verilog_connection_box_reserved_conf_bits(t_cb* cur_cb_info);
|
||||
|
||||
void dump_verilog_routing_connection_box_subckt(FILE* fp, t_cb* cur_cb_info,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
||||
void dump_verilog_routing_resources(char* subckt_dir,
|
||||
t_arch arch,
|
||||
t_det_routing_arch* routing_arch,
|
||||
int LL_num_rr_nodes, t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
void dump_verilog_submodules(char* submodule_dir,
|
||||
t_arch Arch,
|
||||
t_det_routing_arch* routing_arch,
|
||||
boolean include_timing,
|
||||
boolean init_sim);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,37 +0,0 @@
|
|||
|
||||
void dump_verilog_top_netlist(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_spice spice);
|
||||
|
||||
void dump_verilog_top_netlist_tile_orgz(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
char* include_dir_path,
|
||||
char* subckt_dir_path,
|
||||
int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices,
|
||||
int num_clock,
|
||||
t_spice verilog);
|
||||
|
||||
void dump_verilog_top_testbench(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog);
|
||||
|
||||
void dump_verilog_input_blif_testbench(char* circuit_name,
|
||||
char* top_netlist_name,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog);
|
||||
|
||||
void dump_verilog_top_testbench_stimuli(FILE* fp,
|
||||
int num_clock,
|
||||
t_syn_verilog_opts syn_verilog_opts,
|
||||
t_spice verilog);
|
|
@ -1,158 +0,0 @@
|
|||
|
||||
|
||||
void init_list_include_verilog_netlists(t_spice* spice);
|
||||
|
||||
void init_include_user_defined_verilog_netlists(t_spice spice);
|
||||
|
||||
void dump_include_user_defined_verilog_netlists(FILE* fp,
|
||||
t_spice spice);
|
||||
|
||||
void dump_verilog_file_header(FILE* fp,
|
||||
char* usage);
|
||||
|
||||
void dump_verilog_preproc(FILE* fp,
|
||||
boolean include_timing);
|
||||
|
||||
FILE* verilog_create_one_subckt_file(char* subckt_dir,
|
||||
char* subckt_name_prefix,
|
||||
char* verilog_subckt_file_name_prefix,
|
||||
int grid_x, int grid_y,
|
||||
char** verilog_fname);
|
||||
|
||||
void dump_verilog_subckt_header_file(t_llist* subckt_llist_head,
|
||||
char* subckt_dir,
|
||||
char* header_file_name);
|
||||
|
||||
char determine_verilog_generic_port_split_sign(enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_generic_port(FILE* fp,
|
||||
enum e_dump_verilog_port_type dump_port_type,
|
||||
char* port_name, int port_lsb, int port_msb);
|
||||
|
||||
void decode_verilog_memory_bank_sram(t_spice_model* cur_sram_spice_model, int sram_bit,
|
||||
int bl_len, int wl_len, int bl_offset, int wl_offset,
|
||||
int* bl_conf_bits, int* wl_conf_bits);
|
||||
|
||||
void
|
||||
decode_and_add_verilog_sram_membank_conf_bit_to_llist(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int mem_index,
|
||||
int num_bl_per_sram, int num_wl_per_sram,
|
||||
int cur_sram_bit);
|
||||
|
||||
|
||||
void decode_verilog_one_level_4t1r_mux(int path_id,
|
||||
int bit_len, int* conf_bits);
|
||||
|
||||
void decode_verilog_rram_mux(t_spice_model* mux_spice_model,
|
||||
int mux_size, int path_id,
|
||||
int* bit_len, int** conf_bits, int* mux_level);
|
||||
|
||||
int determine_decoder_size(int num_addr_out);
|
||||
|
||||
char* chomp_verilog_node_prefix(char* verilog_node_prefix);
|
||||
|
||||
char* format_verilog_node_prefix(char* verilog_node_prefix);
|
||||
|
||||
char* verilog_convert_port_type_to_string(enum e_spice_model_port_type port_type);
|
||||
|
||||
int rec_dump_verilog_spice_model_global_ports(FILE* fp,
|
||||
t_spice_model* cur_spice_model,
|
||||
boolean dump_port_type,
|
||||
boolean recursive);
|
||||
|
||||
int dump_verilog_global_ports(FILE* fp, t_llist* head,
|
||||
boolean dump_port_type);
|
||||
|
||||
void dump_verilog_mux_sram_one_outport(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* cur_mux_spice_model, int mux_size,
|
||||
int sram_lsb, int sram_msb,
|
||||
int port_type_index,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_sram_one_outport(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int sram_lsb, int sram_msb,
|
||||
int port_type_index,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_sram_outports(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int sram_lsb, int sram_msb,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_sram_one_port(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int sram_lsb, int sram_msb,
|
||||
int port_type_index,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_sram_ports(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int sram_lsb, int sram_msb,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_reserved_sram_one_port(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int sram_lsb, int sram_msb,
|
||||
int port_type_index,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_reserved_sram_ports(FILE* fp,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int sram_lsb, int sram_msb,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_mux_sram_submodule(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* cur_mux_verilog_model, int mux_size,
|
||||
t_spice_model* cur_sram_verilog_model);
|
||||
|
||||
void dump_verilog_sram_submodule(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* sram_verilog_model);
|
||||
|
||||
void dump_verilog_scff_config_bus(FILE* fp,
|
||||
t_spice_model* mem_spice_model,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int lsb, int msb,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_mem_config_bus(FILE* fp, t_spice_model* mem_spice_model,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int cur_num_sram,
|
||||
int num_mem_reserved_conf_bits,
|
||||
int num_mem_conf_bits);
|
||||
|
||||
void dump_verilog_cmos_mux_config_bus(FILE* fp, t_spice_model* mux_spice_model,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int mux_size, int cur_num_sram,
|
||||
int num_mux_reserved_conf_bits,
|
||||
int num_mux_conf_bits);
|
||||
|
||||
void dump_verilog_mux_config_bus(FILE* fp, t_spice_model* mux_spice_model,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int mux_size, int cur_num_sram,
|
||||
int num_mux_reserved_conf_bits,
|
||||
int num_mux_conf_bits);
|
||||
|
||||
void dump_verilog_cmos_mux_config_bus_ports(FILE* fp, t_spice_model* mux_spice_model,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int mux_size, int cur_num_sram,
|
||||
int num_mux_reserved_conf_bits,
|
||||
int num_mux_conf_bits);
|
||||
|
||||
void dump_verilog_mux_config_bus_ports(FILE* fp, t_spice_model* mux_spice_model,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int mux_size, int cur_num_sram,
|
||||
int num_mux_reserved_conf_bits,
|
||||
int num_mux_conf_bits);
|
||||
|
||||
void dump_verilog_grid_common_port(FILE* fp, t_spice_model* cur_verilog_model,
|
||||
char* general_port_prefix, int lsb, int msb,
|
||||
enum e_dump_verilog_port_type dump_port_type);
|
||||
|
||||
void dump_verilog_sram_config_bus_internal_wires(FILE* fp, t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int lsb, int msb);
|
||||
|
||||
void dump_verilog_toplevel_one_grid_side_pin_with_given_index(FILE* fp, t_rr_type pin_type,
|
||||
int pin_index, int side,
|
||||
int x, int y,
|
||||
boolean dump_port_type);
|
|
@ -23,37 +23,53 @@
|
|||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_spice_backannotate_utils.h"
|
||||
#include "fpga_spice_setup.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
#include "fpga_x2p_backannotate_utils.h"
|
||||
#include "fpga_x2p_setup.h"
|
||||
#include "spice_api.h"
|
||||
#include "verilog_api.h"
|
||||
#include "fpga_bitstream.h"
|
||||
|
||||
/* Top-level API of FPGA-SPICE */
|
||||
void vpr_fpga_spice_tool_suites(t_vpr_setup vpr_setup,
|
||||
void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
|
||||
t_arch Arch) {
|
||||
t_sram_orgz_info* sram_bitstream_orgz_info = NULL;
|
||||
|
||||
/* Common initializations and malloc operations */
|
||||
/* If FPGA-SPICE is not called, we should initialize the spice_models */
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.do_fpga_spice) {
|
||||
fpga_spice_setup(vpr_setup, &Arch);
|
||||
fpga_x2p_setup(vpr_setup, &Arch);
|
||||
}
|
||||
|
||||
/* Xifan TANG: SPICE Modeling, SPICE Netlist Output */
|
||||
if (vpr_setup.FPGA_SPICE_Opts.SpiceOpts.do_spice) {
|
||||
vpr_print_spice_netlists(vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName);
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.do_spice) {
|
||||
vpr_fpga_spice(vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName);
|
||||
}
|
||||
|
||||
/* Xifan TANG: Synthesizable verilog dumping */
|
||||
if (vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog) {
|
||||
vpr_dump_syn_verilog(vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName);
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog) {
|
||||
vpr_fpga_verilog(vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName);
|
||||
}
|
||||
|
||||
/* Xifan Tang: Bitstream Generator */
|
||||
if ((TRUE == vpr_setup.FPGA_SPICE_Opts.BitstreamGenOpts.gen_bitstream)
|
||||
&&(FALSE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.do_spice)
|
||||
&&(FALSE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog)) {
|
||||
/* Run bitstream generation here only when other functionalities are disabled;
|
||||
* bitstream will be run inside SPICE and Verilog Generators
|
||||
*/
|
||||
vpr_fpga_bitstream_generator(vpr_setup, Arch, vpr_setup.FileNameOpts.CircuitName, &sram_bitstream_orgz_info);
|
||||
/* Free sram_orgz_info */
|
||||
free_sram_orgz_info(sram_bitstream_orgz_info,
|
||||
sram_bitstream_orgz_info->type);
|
||||
}
|
||||
|
||||
/* Free */
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.do_fpga_spice) {
|
||||
/* Free all the backannotation containing post routing information */
|
||||
free_backannotate_vpr_post_route_info();
|
||||
/* TODO: free other linked lists ! */
|
||||
fpga_spice_free(&Arch);
|
||||
fpga_x2p_free(&Arch);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
|
||||
void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
|
||||
t_arch Arch);
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,10 @@
|
|||
|
||||
int get_ff_output_init_val(t_logical_block* ff_logical_block);
|
||||
|
||||
int get_lut_output_init_val(t_logical_block* lut_logical_block);
|
||||
|
||||
int get_logical_block_output_init_val(t_logical_block* cur_logical_block);
|
||||
|
||||
void init_one_sb_info(t_sb* cur_sb);
|
||||
|
||||
void free_one_sb_info(t_sb* cur_sb);
|
||||
|
@ -73,10 +79,27 @@ void build_one_connection_block_info(t_cb* cur_cb, int cb_x, int cb_y, t_rr_type
|
|||
t_rr_node* LL_rr_node,
|
||||
t_ivec*** LL_rr_node_indices);
|
||||
|
||||
void update_one_grid_pack_prev_node_edge(int x, int y);
|
||||
|
||||
void update_grid_pbs_post_route_rr_graph();
|
||||
|
||||
void free_backannotate_vpr_post_route_info();
|
||||
|
||||
void rec_annotate_pb_type_primitive_node_physical_mode_pin(t_pb_type* top_pb_type,
|
||||
t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_mark_pb_graph_node_primitive_placement_index_in_top_node(t_pb_graph_node* cur_pb_graph_node,
|
||||
int* start_index);
|
||||
|
||||
void rec_link_primitive_pb_graph_node_pin_to_phy_pb_graph_pin(t_pb_graph_node* top_pb_graph_node,
|
||||
t_pb_graph_node* cur_pb_graph_node);
|
||||
|
||||
void annotate_physical_mode_pins_in_pb_graph_node();
|
||||
|
||||
void alloc_and_load_phy_pb_for_mapped_block(int num_mapped_blocks, t_block* mapped_block,
|
||||
int L_num_vpack_nets, t_net* L_vpack_net);
|
||||
|
||||
void spice_backannotate_vpr_post_route_info(t_det_routing_arch RoutingArch,
|
||||
boolean parasitic_net_estimation_off);
|
||||
|
||||
void backannotate_vpr_post_route_info(t_det_routing_arch RoutingArch);
|
||||
boolean read_activity_file,
|
||||
boolean parasitic_net_estimation);
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,80 @@
|
|||
|
||||
int determine_decoder_size(int num_addr_out);
|
||||
|
||||
int count_num_sram_bits_one_spice_model(t_spice_model* cur_spice_model,
|
||||
int mux_size);
|
||||
|
||||
int count_num_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
int count_num_mode_bits_one_spice_model(t_spice_model* cur_spice_model);
|
||||
|
||||
int count_num_reserved_conf_bits_one_lut_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
int count_num_reserved_conf_bits_one_rram_sram_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
void
|
||||
add_mux_scff_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_mux_sram_bits, int* mux_sram_bits,
|
||||
t_spice_model* mux_spice_model);
|
||||
|
||||
void
|
||||
add_mux_membank_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_mux_sram_bits, int* mux_sram_bits,
|
||||
t_spice_model* mux_spice_model);
|
||||
|
||||
void
|
||||
add_mux_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_mux_sram_bits, int* mux_sram_bits,
|
||||
t_spice_model* mux_spice_model);
|
||||
|
||||
void add_sram_membank_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info, int mem_index,
|
||||
int num_bls, int num_wls,
|
||||
int* bl_conf_bits, int* wl_conf_bits);
|
||||
|
||||
void
|
||||
add_sram_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info, int mem_index,
|
||||
int num_sram_bits, int* sram_bits);
|
||||
|
||||
|
||||
void decode_memory_bank_sram(t_spice_model* cur_sram_spice_model, int sram_bit,
|
||||
int bl_len, int wl_len, int bl_offset, int wl_offset,
|
||||
int* bl_conf_bits, int* wl_conf_bits);
|
||||
|
||||
void
|
||||
decode_and_add_sram_membank_conf_bit_to_llist(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int mem_index,
|
||||
int num_bl_per_sram, int num_wl_per_sram,
|
||||
int cur_sram_bit);
|
||||
|
||||
void determine_blwl_decoder_size(INP t_sram_orgz_info* cur_sram_orgz_info,
|
||||
OUTP int* num_array_bl, OUTP int* num_array_wl,
|
||||
OUTP int* bl_decoder_size, OUTP int* wl_decoder_size) ;
|
||||
|
||||
void init_sram_orgz_info_reserved_blwl(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_switch,
|
||||
t_switch_inf* switches,
|
||||
t_spice* spice,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
void add_one_conf_bit_to_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info) ;
|
||||
|
||||
void add_sram_conf_bits_to_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* cur_spice_model) ;
|
||||
|
||||
void add_mux_conf_bits_to_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* mux_spice_model, int mux_size) ;
|
|
@ -5,7 +5,7 @@
|
|||
#include <stdio.h>
|
||||
#include "spice_types.h"
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "fpga_x2p_globals.h"
|
||||
|
||||
/* Global variables to be shared by different tools of FPGA-SPICE */
|
||||
/* SRAM SPICE MODEL should be set as global*/
|
||||
|
@ -40,3 +40,10 @@ boolean run_parasitic_net_estimation = TRUE;
|
|||
boolean run_testbench_load_extraction = TRUE;
|
||||
|
||||
char* renaming_report_postfix = "_io_renaming.rpt";
|
||||
char* fpga_spice_bitstream_output_file_postfix = ".bitstream";
|
||||
char* fpga_spice_bitstream_logic_block_log_file_postfix = "_lb_bitstream.log";
|
||||
char* fpga_spice_bitstream_routing_log_file_postfix = "_routing_bitstream.log";
|
||||
char* default_sdc_folder = "SDC/";
|
||||
|
||||
|
||||
|
|
@ -30,14 +30,7 @@ extern t_llist* global_ports_head;
|
|||
/* Linked list for verilog and spice syntax char */
|
||||
extern t_llist* reserved_syntax_char_head;
|
||||
|
||||
/* Enumeration */
|
||||
enum e_pin2pin_interc_type {
|
||||
INPUT2INPUT_INTERC, OUTPUT2OUTPUT_INTERC
|
||||
};
|
||||
|
||||
|
||||
extern char* renaming_report_postfix;
|
||||
|
||||
#define PRIMITIVE_WIRED_LUT -1
|
||||
#define PRIMITIVE_IDLE 1
|
||||
#define PRIMITIVE_NORMAL 0
|
||||
extern char* fpga_spice_bitstream_output_file_postfix;
|
||||
extern char* fpga_spice_bitstream_logic_block_log_file_postfix;
|
||||
extern char* fpga_spice_bitstream_routing_log_file_postfix;
|
|
@ -0,0 +1,751 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Include vpr structs*/
|
||||
#include "util.h"
|
||||
#include "physical_types.h"
|
||||
#include "vpr_types.h"
|
||||
#include "globals.h"
|
||||
#include "rr_graph_util.h"
|
||||
#include "rr_graph.h"
|
||||
#include "rr_graph2.h"
|
||||
#include "vpr_utils.h"
|
||||
#include "route_common.h"
|
||||
|
||||
/* Include SPICE support headers*/
|
||||
#include "quicksort.h"
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_x2p_types.h"
|
||||
#include "fpga_x2p_globals.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
#include "fpga_x2p_pbtypes_utils.h"
|
||||
#include "fpga_x2p_lut_utils.h"
|
||||
|
||||
|
||||
char* complete_truth_table_line(int lut_size,
|
||||
char* input_truth_table_line) {
|
||||
char* ret = NULL;
|
||||
int num_token = 0;
|
||||
char** tokens = NULL;
|
||||
int cover_len = 0;
|
||||
int j;
|
||||
|
||||
/* Due to the size of truth table may be less than the lut size.
|
||||
* i.e. in LUT-6 architecture, there exists LUT1-6 in technology-mapped netlists
|
||||
* So, in truth table line, there may be 10- 1
|
||||
* In this case, we should complete it by --10- 1
|
||||
*/
|
||||
/*Malloc the completed truth table, lut_size + space + truth_val + '\0'*/
|
||||
ret = (char*)my_malloc(sizeof(char)*lut_size + 3);
|
||||
/* Split one line of truth table line*/
|
||||
tokens = fpga_spice_strtok(input_truth_table_line, " ", &num_token);
|
||||
/* Check, only 2 tokens*/
|
||||
/* Sometimes, the truth table is ' 0' or ' 1', which corresponds to a constant */
|
||||
if (1 == num_token) {
|
||||
/* restore the token[0]*/
|
||||
tokens = (char**)realloc(tokens, 2 * sizeof(char*));
|
||||
tokens[1] = tokens[0];
|
||||
tokens[0] = my_strdup("-");
|
||||
num_token = 2;
|
||||
}
|
||||
|
||||
/* In Most cases, there should be 2 tokens. */
|
||||
assert(2 == num_token);
|
||||
/* We may have two truth table from two LUTs which contain both 0 and 1*/
|
||||
/*
|
||||
if ((0 != strcmp(tokens[1], "1"))&&(0 != strcmp(tokens[1], "0"))) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Last token of truth table line should be [0|1]!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
/* Complete the truth table line*/
|
||||
cover_len = strlen(tokens[0]);
|
||||
assert((cover_len < lut_size)||(cover_len == lut_size));
|
||||
|
||||
/* Copy the original truth table line */
|
||||
for (j = 0; j < cover_len; j++) {
|
||||
ret[j] = tokens[0][j];
|
||||
}
|
||||
/* Add the number of '-' we should add in the back !!! */
|
||||
for (j = cover_len; j < lut_size; j++) {
|
||||
ret[j] = '-';
|
||||
}
|
||||
|
||||
/* Copy the original truth table line */
|
||||
sprintf(ret + lut_size, " %s", tokens[1]);
|
||||
|
||||
/* Free */
|
||||
for (j = 0; j < num_token; j++) {
|
||||
my_free(tokens[j]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* For each lut_bit_lines, we should recover the truth table,
|
||||
* and then set the sram bits to "1" if the truth table defines so.
|
||||
* Start_point: the position we start decode recursively
|
||||
*/
|
||||
void configure_lut_sram_bits_per_line_rec(int** sram_bits,
|
||||
int lut_size,
|
||||
char* truth_table_line,
|
||||
int start_point) {
|
||||
int i;
|
||||
int num_sram_bit = (int)pow(2., (double)(lut_size));
|
||||
char* temp_line = my_strdup(truth_table_line);
|
||||
int do_config = 1;
|
||||
int sram_id = 0;
|
||||
|
||||
/* Check the length of sram bits and truth table line */
|
||||
//assert((sizeof(int)*num_sram_bit) == sizeof(*sram_bits)); /*TODO: fix this assert*/
|
||||
if ((unsigned)(lut_size + 1 + 1) != strlen(truth_table_line)){ /* lut_size + space + '1' */
|
||||
assert((unsigned)(lut_size + 1 + 1) == strlen(truth_table_line)); /* lut_size + space + '1' */
|
||||
}
|
||||
/* End of truth_table_line should be "space" and "1" */
|
||||
assert((0 == strcmp(" 1", truth_table_line + lut_size))||(0 == strcmp(" 0", truth_table_line + lut_size)));
|
||||
/* Make sure before start point there is no '-' */
|
||||
for (i = 0; i < start_point; i++) {
|
||||
assert('-' != truth_table_line[i]);
|
||||
}
|
||||
|
||||
/* Configure sram bits recursively */
|
||||
for (i = start_point; i < lut_size; i++) {
|
||||
if ('-' == truth_table_line[i]) {
|
||||
do_config = 0;
|
||||
/* if we find a dont_care, we don't do configure now but recursively*/
|
||||
/* '0' branch */
|
||||
temp_line[i] = '0';
|
||||
configure_lut_sram_bits_per_line_rec(sram_bits, lut_size, temp_line, start_point + 1);
|
||||
/* '1' branch */
|
||||
temp_line[i] = '1';
|
||||
configure_lut_sram_bits_per_line_rec(sram_bits, lut_size, temp_line, start_point + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* do_config*/
|
||||
if (do_config) {
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
/* Should be either '0' or '1' */
|
||||
switch (truth_table_line[i]) {
|
||||
case '0':
|
||||
/* We assume the 1-lut pass sram1 when input = 0 */
|
||||
sram_id += (int)pow(2., (double)(i));
|
||||
break;
|
||||
case '1':
|
||||
/* We assume the 1-lut pass sram0 when input = 1 */
|
||||
break;
|
||||
case '-':
|
||||
assert('-' != truth_table_line[i]); /* Make sure there is no dont_care */
|
||||
default :
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s, [LINE%d])Invalid truth_table bit(%c), should be [0|1|'-]!\n",
|
||||
__FILE__, __LINE__, truth_table_line[i]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/* Set the sram bit to '1'*/
|
||||
assert((-1 < sram_id) && (sram_id < num_sram_bit));
|
||||
if (0 == strcmp(" 1", truth_table_line + lut_size)) {
|
||||
(*sram_bits)[sram_id] = 1; /* on set*/
|
||||
} else if (0 == strcmp(" 0", truth_table_line + lut_size)) {
|
||||
(*sram_bits)[sram_id] = 0; /* off set */
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid truth_table_line ending(=%s)!\n",
|
||||
__FILE__, __LINE__, truth_table_line + lut_size);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free */
|
||||
my_free(temp_line);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine if the truth table of a LUT is a on-set or a off-set */
|
||||
int determine_lut_truth_table_on_set(int truth_table_len,
|
||||
char** truth_table) {
|
||||
int on_set = 0;
|
||||
int off_set = 0;
|
||||
int i, tt_line_len;
|
||||
|
||||
for (i = 0; i < truth_table_len; i++) {
|
||||
tt_line_len = strlen(truth_table[i]);
|
||||
switch (truth_table[i][tt_line_len - 1]) {
|
||||
case '1':
|
||||
on_set = 1;
|
||||
break;
|
||||
case '0':
|
||||
off_set = 1;
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid truth_table_line ending(=%c)!\n",
|
||||
__FILE__, __LINE__, truth_table[i][tt_line_len - 1]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prefer on_set if both are true */
|
||||
if (2 == (on_set + off_set)) {
|
||||
on_set = 1; off_set = 0;
|
||||
}
|
||||
|
||||
return on_set;
|
||||
}
|
||||
|
||||
/* Generate the LUT SRAM bits for a given truth table
|
||||
* As truth tables may come from different logic blocks, truth tables could be in on and off sets
|
||||
* We first build a base SRAM bits, where different parts are set to tbe on/off sets
|
||||
* Then, we can decode SRAM bits as regular process
|
||||
*/
|
||||
int* generate_lut_sram_bits(int truth_table_len,
|
||||
char** truth_table,
|
||||
int lut_size,
|
||||
int default_sram_bit_value) {
|
||||
int num_sram = (int)pow(2.,(double)(lut_size));
|
||||
int* ret = (int*)my_calloc(num_sram, sizeof(int));
|
||||
char** completed_truth_table = (char**)my_malloc(sizeof(char*)*truth_table_len);
|
||||
int on_set = 0;
|
||||
int off_set = 0;
|
||||
int i;
|
||||
|
||||
/* if No truth_table, do default*/
|
||||
if (0 == truth_table_len) {
|
||||
switch (default_sram_bit_value) {
|
||||
case 0:
|
||||
off_set = 0;
|
||||
on_set = 1;
|
||||
break;
|
||||
case 1:
|
||||
off_set = 1;
|
||||
on_set = 0;
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid default_signal_init_value(=%d)!\n",
|
||||
__FILE__, __LINE__, default_sram_bit_value);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
on_set = determine_lut_truth_table_on_set(truth_table_len, truth_table);
|
||||
off_set = 1 - on_set;
|
||||
}
|
||||
|
||||
/* Read in truth table lines, decode one by one */
|
||||
for (i = 0; i < truth_table_len; i++) {
|
||||
/* Complete the truth table line by line*/
|
||||
//printf("truth_table[%d] = %s\n", i, truth_table[i]);
|
||||
completed_truth_table[i] = complete_truth_table_line(lut_size, truth_table[i]);
|
||||
//printf("Completed_truth_table[%d] = %s\n", i, completed_truth_table[i]);
|
||||
}
|
||||
|
||||
if (1 == on_set) {
|
||||
/* Initial all sram bits to 0*/
|
||||
for (i = 0 ; i < num_sram; i++) {
|
||||
ret[i] = 0;
|
||||
}
|
||||
} else if (1 == off_set) {
|
||||
/* Initial all sram bits to 1*/
|
||||
for (i = 0 ; i < num_sram; i++) {
|
||||
ret[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < truth_table_len; i++) {
|
||||
/* Update the truth table, sram_bits */
|
||||
configure_lut_sram_bits_per_line_rec(&ret, lut_size, completed_truth_table[i], 0);
|
||||
}
|
||||
|
||||
/* Free */
|
||||
for (i = 0; i < truth_table_len; i++) {
|
||||
my_free(completed_truth_table[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Generate the base SRAM bits:
|
||||
* Check type of truth table of each mapped logical block
|
||||
* if it is on-set, we give a all 0 base sram-bit
|
||||
* if it is off-set, we give a all 1 base sram-bit */
|
||||
int* generate_frac_lut_sram_bits(t_phy_pb* lut_phy_pb,
|
||||
int* truth_table_length,
|
||||
char*** truth_table,
|
||||
int default_sram_bit_value) {
|
||||
int num_sram, lut_size;
|
||||
int* sram_bits = NULL;
|
||||
int* temp_sram_bits = NULL;
|
||||
int ilb;
|
||||
int lut_frac_level, lut_output_mask;
|
||||
int num_input_port = 0;
|
||||
t_spice_model_port** input_ports = NULL;
|
||||
int offset, len_to_cpy;
|
||||
|
||||
/* Find the input ports for LUT size */
|
||||
input_ports = find_spice_model_ports(lut_phy_pb->pb_graph_node->pb_type->spice_model, SPICE_MODEL_PORT_INPUT, &num_input_port, TRUE);
|
||||
assert(1 == num_input_port);
|
||||
lut_size = input_ports[0]->size;
|
||||
num_sram = (int)pow(2.,(double)(lut_size));
|
||||
sram_bits = (int*)my_calloc(num_sram, sizeof(int));
|
||||
|
||||
/* Initialization */
|
||||
for (ilb = 0; ilb < num_sram; ilb++) {
|
||||
sram_bits[ilb] = default_sram_bit_value;
|
||||
}
|
||||
|
||||
for (ilb = 0; ilb < lut_phy_pb->num_logical_blocks; ilb++) {
|
||||
/* find the corresponding SPICE model output port and assoicated lut_output_mask */
|
||||
lut_frac_level = get_pb_graph_pin_lut_frac_level(lut_phy_pb->lut_output_pb_graph_pin[ilb]);
|
||||
lut_output_mask = get_pb_graph_pin_lut_output_mask(lut_phy_pb->lut_output_pb_graph_pin[ilb]);
|
||||
/* Decode lut sram bits */
|
||||
temp_sram_bits = generate_lut_sram_bits(truth_table_length[ilb], truth_table[ilb], lut_size, default_sram_bit_value);
|
||||
/* Depending on the frac-level, we get the location(starting/end points) of sram bits */
|
||||
len_to_cpy = (int)pow(2., (double)(lut_frac_level));
|
||||
offset = len_to_cpy * lut_output_mask;
|
||||
/*TODO: copy to the sram_bits to return:
|
||||
* Should check if we will overwrite anything!
|
||||
*/
|
||||
memcpy(sram_bits + offset, temp_sram_bits + offset,
|
||||
len_to_cpy * sizeof(int));
|
||||
/* Free */
|
||||
my_free(temp_sram_bits);
|
||||
}
|
||||
|
||||
/* Free */
|
||||
my_free(input_ports);
|
||||
|
||||
return sram_bits;
|
||||
}
|
||||
|
||||
|
||||
/* Provide the truth table of a mapped logical block
|
||||
* 1. Reorgainze the truth table to be consistent with the mapped nets of a LUT
|
||||
* 2. Allocate the truth table in a clean char array and return
|
||||
*/
|
||||
char** assign_lut_truth_table(t_logical_block* mapped_logical_block,
|
||||
int* truth_table_length) {
|
||||
char** truth_table = NULL;
|
||||
t_linked_vptr* head = NULL;
|
||||
int cur = 0;
|
||||
|
||||
if (NULL == mapped_logical_block) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid mapped_logical_block!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Count the lines of truth table*/
|
||||
head = mapped_logical_block->truth_table;
|
||||
while(head) {
|
||||
(*truth_table_length)++;
|
||||
head = head->next;
|
||||
}
|
||||
/* Allocate truth_tables */
|
||||
truth_table = (char**)my_malloc(sizeof(char*)*(*truth_table_length));
|
||||
/* Fill truth_tables*/
|
||||
cur = 0;
|
||||
head = mapped_logical_block->truth_table;
|
||||
while(head) {
|
||||
truth_table[cur] = my_strdup((char*)(head->data_vptr));
|
||||
head = head->next;
|
||||
cur++;
|
||||
}
|
||||
assert(cur == (*truth_table_length));
|
||||
|
||||
return truth_table;
|
||||
}
|
||||
|
||||
/* Return the truth table of a wired LUT */
|
||||
char** get_wired_lut_truth_table() {
|
||||
char** tt = (char**) my_malloc(sizeof(char*));
|
||||
tt[0] = my_strdup("1 1");
|
||||
|
||||
return tt;
|
||||
}
|
||||
|
||||
/* Adapt the truth from the actual connection from the input nets of a LUT,
|
||||
*/
|
||||
char** assign_post_routing_wired_lut_truth_table(int lut_output_vpack_net_num,
|
||||
int lut_size, int* lut_pin_vpack_net_num,
|
||||
int* truth_table_length) {
|
||||
int inet, iport;
|
||||
char** tt = (char**) my_malloc(sizeof(char*));
|
||||
|
||||
/* truth_table_length will be always 1*/
|
||||
(*truth_table_length) = 1;
|
||||
|
||||
/* Malloc */
|
||||
tt[0] = (char*)my_malloc((lut_size + 3) * sizeof(char));
|
||||
/* Fill the truth table !!! */
|
||||
for (inet = 0; inet < lut_size; inet++) {
|
||||
/* Find the vpack_num in the lut_input_pin, we fix it to be 1 */
|
||||
if (lut_output_vpack_net_num == lut_pin_vpack_net_num[inet]) {
|
||||
tt[0][inet] = '1';
|
||||
} else {
|
||||
/* Otherwise it should be don't care */
|
||||
tt[0][inet] = '-';
|
||||
}
|
||||
}
|
||||
memcpy(tt[0] + lut_size, " 1", 3);
|
||||
|
||||
return tt;
|
||||
}
|
||||
|
||||
/* Provide the truth table of a mapped logical block
|
||||
* 1. Reorgainze the truth table to be consistent with the mapped nets of a LUT
|
||||
* 2. Allocate the truth table in a clean char array and return
|
||||
*/
|
||||
char** assign_post_routing_lut_truth_table(t_logical_block* mapped_logical_block,
|
||||
int lut_size, int* lut_pin_vpack_net_num,
|
||||
int* truth_table_length) {
|
||||
char** truth_table = NULL;
|
||||
t_linked_vptr* head = NULL;
|
||||
int cur = 0;
|
||||
int inet, jnet;
|
||||
int* lut_to_lb_net_mapping = NULL;
|
||||
int num_lb_pin = 0;
|
||||
int* lb_pin_vpack_net_num = NULL;
|
||||
int lb_truth_table_size = 0;
|
||||
|
||||
if (NULL == mapped_logical_block) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,[LINE%d])Invalid mapped_logical_block!\n",
|
||||
__FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Allocate */
|
||||
lut_to_lb_net_mapping = (int*) my_malloc (sizeof(int) * lut_size);
|
||||
/* Find nets mapped to a logical block */
|
||||
get_lut_logical_block_input_pin_vpack_net_num(mapped_logical_block,
|
||||
&num_lb_pin, &lb_pin_vpack_net_num);
|
||||
/* Create a pin-to-pin net_num mapping */
|
||||
for (inet = 0; inet < lut_size; inet++) {
|
||||
lut_to_lb_net_mapping[inet] = OPEN;
|
||||
/* Bypass open nets */
|
||||
if (OPEN == lut_pin_vpack_net_num[inet]) {
|
||||
continue;
|
||||
}
|
||||
assert (OPEN != lut_pin_vpack_net_num[inet]);
|
||||
/* Find the position (offset) of each vpack_net_num in lb_pins */
|
||||
for (jnet = 0; jnet < num_lb_pin; jnet++) {
|
||||
if (lut_pin_vpack_net_num[inet] == lb_pin_vpack_net_num[jnet]) {
|
||||
lut_to_lb_net_mapping[inet] = jnet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Not neccesary to find a one, some luts just share part of their pins */
|
||||
}
|
||||
|
||||
/* Initialization */
|
||||
(*truth_table_length) = 0;
|
||||
/* Count the lines of truth table*/
|
||||
head = mapped_logical_block->truth_table;
|
||||
while(head) {
|
||||
(*truth_table_length)++;
|
||||
head = head->next;
|
||||
}
|
||||
/* Allocate truth_tables */
|
||||
truth_table = (char**)my_malloc(sizeof(char*)*(*truth_table_length));
|
||||
/* Fill truth_tables*/
|
||||
cur = 0;
|
||||
head = mapped_logical_block->truth_table;
|
||||
while(head) {
|
||||
/* Handle the truth table pin remapping */
|
||||
truth_table[cur] = (char*) my_malloc((lut_size + 3) * sizeof(char));
|
||||
/* Initialize */
|
||||
lb_truth_table_size = strlen((char*)(head->data_vptr));
|
||||
strcpy(truth_table[cur] + lut_size, (char*)(head->data_vptr) + lb_truth_table_size - 2);
|
||||
truth_table[cur][lut_size + 2] = '\0';
|
||||
/* Add */
|
||||
for (inet = 0; inet < lut_size; inet++) {
|
||||
/* Open net implies a don't care, or some nets are not in the list */
|
||||
if ((OPEN == lut_pin_vpack_net_num[inet])
|
||||
|| (OPEN == lut_to_lb_net_mapping[inet])) {
|
||||
truth_table[cur][inet] = '-';
|
||||
continue;
|
||||
}
|
||||
/* Find the desired truth table bit */
|
||||
truth_table[cur][inet] = ((char*)(head->data_vptr))[lut_to_lb_net_mapping[inet]];
|
||||
}
|
||||
|
||||
head = head->next;
|
||||
cur++;
|
||||
}
|
||||
assert(cur == (*truth_table_length));
|
||||
|
||||
return truth_table;
|
||||
}
|
||||
|
||||
/* Find the output port of LUT that this logical block is mapped to */
|
||||
t_pb_graph_pin* get_mapped_lut_phy_pb_output_pin(t_phy_pb* lut_phy_pb,
|
||||
t_logical_block* lut_logical_block) {
|
||||
int iport, ipin;
|
||||
int num_lut_output_ports;
|
||||
int* num_lut_output_pins;
|
||||
int** lut_output_vpack_net_num;
|
||||
int pin_rr_node_index;
|
||||
t_pb_graph_pin* ret_pin = NULL; /* The pin to return */
|
||||
int found_num_pins = 0;
|
||||
|
||||
/* Find the vpack_net_num of the output of the lut_logical_block */
|
||||
get_logical_block_output_vpack_net_num(lut_logical_block,
|
||||
&num_lut_output_ports,
|
||||
&num_lut_output_pins,
|
||||
&lut_output_vpack_net_num);
|
||||
|
||||
/* Check */
|
||||
assert ( 1 == num_lut_output_ports);
|
||||
assert ( 1 == num_lut_output_pins[0]);
|
||||
assert ( OPEN != lut_output_vpack_net_num[0][0]);
|
||||
|
||||
/* Search the output pins of lut_phy_pb in rr_graph in find */
|
||||
for (iport = 0; iport < lut_phy_pb->pb_graph_node->num_output_ports; iport++) {
|
||||
for (ipin = 0; ipin < lut_phy_pb->pb_graph_node->num_output_pins[iport]; ipin++) {
|
||||
/* Get the rr_node index of the pin */
|
||||
pin_rr_node_index = lut_phy_pb->pb_graph_node->output_pins[iport][ipin].rr_node_index_physical_pb;
|
||||
/* Get the vpack_net_num in the local rr_graph, see if we have a match */
|
||||
if (lut_output_vpack_net_num[0][0] != lut_phy_pb->rr_graph->rr_node[pin_rr_node_index].vpack_net_num) {
|
||||
continue;
|
||||
}
|
||||
/* Reach here, it means we have a match! */
|
||||
ret_pin = &(lut_phy_pb->pb_graph_node->output_pins[iport][ipin]);
|
||||
found_num_pins++;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should have only one match! */
|
||||
assert (1 == found_num_pins);
|
||||
|
||||
/* Free */
|
||||
my_free(num_lut_output_pins);
|
||||
for (iport = 0; iport < num_lut_output_ports; iport++) {
|
||||
my_free(lut_output_vpack_net_num);
|
||||
}
|
||||
|
||||
return ret_pin;
|
||||
}
|
||||
|
||||
/* Get LUT fracturable level of a pb_graph_pin */
|
||||
int get_pb_graph_pin_lut_frac_level(t_pb_graph_pin* out_pb_graph_pin) {
|
||||
/* search the corresponding spice_model_port */
|
||||
return out_pb_graph_pin->port->spice_model_port->lut_frac_level;
|
||||
}
|
||||
|
||||
/* Get LUT output mask of a pb_graph_pin */
|
||||
int get_pb_graph_pin_lut_output_mask(t_pb_graph_pin* out_pb_graph_pin) {
|
||||
int pin_number = out_pb_graph_pin->pin_number;
|
||||
/* search the corresponding spice_model_port */
|
||||
return out_pb_graph_pin->port->spice_model_port->lut_output_mask[pin_number];
|
||||
}
|
||||
|
||||
/* Adapt truth table for a fracturable LUT
|
||||
* Determine fixed input bits for this truth table:
|
||||
* 1. input bits within frac_level (all '-' if not specified)
|
||||
* 2. input bits outside frac_level, decoded to its output mask (0 -> first part -> all '1')
|
||||
*/
|
||||
void adapt_truth_table_for_frac_lut(t_pb_graph_pin* lut_out_pb_graph_pin,
|
||||
int truth_table_length,
|
||||
char** truth_table) {
|
||||
int lut_frac_level;
|
||||
int lut_output_mask;
|
||||
int i, lut_size, num_mask_bits;
|
||||
int temp;
|
||||
char* mask_bits = NULL;
|
||||
|
||||
/* Find the output port of LUT that this logical block is mapped to */
|
||||
assert(NULL != lut_out_pb_graph_pin);
|
||||
/* find the corresponding SPICE model output port and assoicated lut_output_mask */
|
||||
lut_frac_level = get_pb_graph_pin_lut_frac_level(lut_out_pb_graph_pin);
|
||||
lut_output_mask = get_pb_graph_pin_lut_output_mask(lut_out_pb_graph_pin);
|
||||
|
||||
/* Apply modification to the truth table */
|
||||
for (i = 0; i < truth_table_length; i++) {
|
||||
/* Last two chars are fixed */
|
||||
lut_size = strlen(truth_table[i]) - 2;
|
||||
/* Get the number of bits to be masked (modified) */
|
||||
num_mask_bits = lut_size - lut_frac_level;
|
||||
/* Check if we need to modify any bits */
|
||||
assert (-1 < num_mask_bits);
|
||||
if ( 0 == num_mask_bits ) {
|
||||
continue;
|
||||
}
|
||||
/* Modify bits starting from lut_frac_level */
|
||||
/* decode the lut_output_mask to LUT input codes */
|
||||
temp = pow(2., num_mask_bits) - 1 - lut_output_mask;
|
||||
mask_bits = my_itobin(temp, num_mask_bits);
|
||||
/* copy the bits to the truth table line */
|
||||
memcpy(truth_table[i] + lut_frac_level, mask_bits, num_mask_bits);
|
||||
/* free */
|
||||
my_free(mask_bits);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int determine_lut_path_id(int lut_size,
|
||||
int* lut_inputs) {
|
||||
int path_id = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
switch (lut_inputs[i]) {
|
||||
case 0:
|
||||
path_id += (int)pow(2., (double)(i));
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,[LINE%d])Invalid sram_bits[%d]!\n",
|
||||
__FILE__, __LINE__, i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return path_id;
|
||||
}
|
||||
|
||||
/* Identify if this is an unallocated pb that is used as a wired LUT */
|
||||
boolean is_pb_wired_lut(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_type* cur_pb_type,
|
||||
t_rr_node* pb_rr_graph) {
|
||||
boolean is_used = FALSE;
|
||||
|
||||
is_used = is_pb_used_for_wiring(cur_pb_graph_node,
|
||||
cur_pb_type,
|
||||
pb_rr_graph);
|
||||
/* Return TRUE if this block is not used and it is a LUT ! */
|
||||
if ((TRUE == is_used)
|
||||
&& (LUT_CLASS == cur_pb_type->class_type)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Find and return the net_name that this LUT is wiring*/
|
||||
int get_wired_lut_net_name(t_pb_graph_node* lut_pb_graph_node,
|
||||
t_pb_type* lut_pb_type,
|
||||
t_rr_node* pb_rr_graph) {
|
||||
int iport, ipin;
|
||||
int num_used_lut_input_pins = 0;
|
||||
int num_used_lut_output_pins = 0;
|
||||
int temp_rr_node_index;
|
||||
int wired_lut_net_num = OPEN;
|
||||
|
||||
/* Return if this is not a LUT */
|
||||
if ((LUT_CLASS != lut_pb_type->class_type)
|
||||
|| (LUT_CLASS != lut_pb_graph_node->pb_type->class_type)) {
|
||||
return OPEN;
|
||||
}
|
||||
|
||||
num_used_lut_input_pins = 0;
|
||||
/* Find the used input pin of this LUT and rr_node in the graph */
|
||||
for (iport = 0; iport < lut_pb_graph_node->num_input_ports; iport++) {
|
||||
for (ipin = 0; ipin < lut_pb_graph_node->num_input_pins[iport]; ipin++) {
|
||||
temp_rr_node_index = lut_pb_graph_node->input_pins[iport][ipin].pin_count_in_cluster;
|
||||
if (OPEN != pb_rr_graph[temp_rr_node_index].net_num) {
|
||||
num_used_lut_input_pins++;
|
||||
wired_lut_net_num = pb_rr_graph[temp_rr_node_index].net_num;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Make sure we only have 1 used input pin */
|
||||
assert (1 == num_used_lut_input_pins);
|
||||
|
||||
/* Find the used output*/
|
||||
num_used_lut_output_pins = 0;
|
||||
/* Find the used output pin of this LUT and rr_node in the graph */
|
||||
for (iport = 0; iport < lut_pb_graph_node->num_output_ports; iport++) {
|
||||
for (ipin = 0; ipin < lut_pb_graph_node->num_output_pins[iport]; ipin++) {
|
||||
temp_rr_node_index = lut_pb_graph_node->output_pins[iport][ipin].pin_count_in_cluster;
|
||||
if (wired_lut_net_num == pb_rr_graph[temp_rr_node_index].net_num) {
|
||||
num_used_lut_output_pins++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Make sure we only have 1 used output pin */
|
||||
assert (1 == num_used_lut_output_pins);
|
||||
|
||||
assert (OPEN != wired_lut_net_num);
|
||||
|
||||
return wired_lut_net_num;
|
||||
}
|
||||
|
||||
/* This function aims to allocate and load pbs for wired LUTs
|
||||
* 1. if the pbs are not allocated at all, allocate and load the full array
|
||||
* Otherwise just allocate the specific pb
|
||||
* 2. Get the net_name that this LUT is wiring
|
||||
* and load it to the pb
|
||||
*/
|
||||
void allocate_wired_lut_pbs(t_pb*** wired_lut_pbs,
|
||||
int num_pb_type_children,
|
||||
int num_pbs,
|
||||
int wired_lut_child_id,
|
||||
int wired_lut_pb_id) {
|
||||
int ipb;
|
||||
|
||||
/* 1. if the pbs are not allocated at all, allocate and load the full array */
|
||||
if (NULL == (*wired_lut_pbs)) {
|
||||
(*wired_lut_pbs) = (t_pb**) my_calloc(num_pb_type_children, sizeof(t_pb*));
|
||||
for (ipb = 0 ; ipb < num_pb_type_children; ipb++) {
|
||||
(*wired_lut_pbs)[ipb] = (t_pb*) my_calloc(num_pbs, sizeof(t_pb));
|
||||
}
|
||||
} else if (NULL == (*wired_lut_pbs)[wired_lut_child_id]) {
|
||||
/* 2. if the pb row is not allocated, just allocate that row */
|
||||
(*wired_lut_pbs)[wired_lut_child_id] = (t_pb*) my_calloc(num_pbs, sizeof(t_pb));
|
||||
} else if (NULL == (*wired_lut_pbs)[wired_lut_child_id][wired_lut_pb_id].name) {
|
||||
/* 3. if this pb is allocated, we do nothing */
|
||||
}
|
||||
|
||||
/* Find the net_name this LUT is wiring */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* 1. Find the net_name that this wire LUT is mapped to
|
||||
* 2. Give a name to the pb
|
||||
* 3. Update the mapping information (net_num) in the rr_graph of pb
|
||||
* 4. Create the wired LUTs in logical block array
|
||||
* 5. Create new vpack & clb nets to rewire the logical blocks
|
||||
* 6. Update the vpack_to_clb_net_mapping and clb_to_vpack_net_mapping !!!
|
||||
*/
|
||||
void load_wired_lut_pbs(t_pb* lut_pb,
|
||||
t_pb_graph_node* lut_pb_graph_node,
|
||||
t_pb_type* lut_pb_type,
|
||||
t_rr_node* pb_rr_graph,
|
||||
int* L_num_logical_blocks, t_net** L_logical_block,
|
||||
int* L_num_vpack_nets, t_net** L_vpack_net) {
|
||||
int lut_wire_net_name = OPEN;
|
||||
|
||||
/* 1. Find the net_name that this wire LUT is mapped to */
|
||||
lut_wire_net_name = get_wired_lut_net_name(lut_pb_graph_node,
|
||||
lut_pb_type,
|
||||
pb_rr_graph);
|
||||
assert (OPEN != lut_wire_net_name);
|
||||
|
||||
/* Fill basic information */
|
||||
lut_pb->pb_graph_node = lut_pb_graph_node;
|
||||
lut_pb->rr_graph = pb_rr_graph;
|
||||
|
||||
/* Check and give a new name to this pb */
|
||||
|
||||
/* Update rr_graph,
|
||||
* 1. find the downstream logical blocks and their pbs
|
||||
* 2. Update their rr_nodes with new net_name
|
||||
* 3. backtrace all the rr_nodes and update net_name
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/* Useful functions for LUT decoding */
|
||||
char* complete_truth_table_line(int lut_size,
|
||||
char* input_truth_table_line);
|
||||
|
||||
void configure_lut_sram_bits_per_line_rec(int** sram_bits,
|
||||
int lut_size,
|
||||
char* truth_table_line,
|
||||
int start_point);
|
||||
|
||||
int* generate_lut_sram_bits(int truth_table_len,
|
||||
char** truth_table,
|
||||
int lut_size,
|
||||
int default_sram_bit_value);
|
||||
|
||||
int* generate_frac_lut_sram_bits(t_phy_pb* lut_phy_pb,
|
||||
int* truth_table_length,
|
||||
char*** truth_table,
|
||||
int default_sram_bit_value);
|
||||
|
||||
char** assign_lut_truth_table(t_logical_block* mapped_logical_block,
|
||||
int* truth_table_length);
|
||||
|
||||
char** get_wired_lut_truth_table();
|
||||
|
||||
char** assign_post_routing_wired_lut_truth_table(int lut_output_vpack_net_num,
|
||||
int lut_size, int* lut_pin_vpack_net_num,
|
||||
int* truth_table_length);
|
||||
|
||||
char** assign_post_routing_lut_truth_table(t_logical_block* mapped_logical_block,
|
||||
int num_lut_pins, int* lut_pin_vpack_net_num,
|
||||
int* truth_table_length);
|
||||
|
||||
t_pb_graph_pin* get_mapped_lut_phy_pb_output_pin(t_phy_pb* lut_phy_pb,
|
||||
t_logical_block* lut_logical_block);
|
||||
|
||||
int get_pb_graph_pin_lut_frac_level(t_pb_graph_pin* out_pb_graph_pin);
|
||||
|
||||
int get_pb_graph_pin_lut_output_mask(t_pb_graph_pin* out_pb_graph_pin);
|
||||
|
||||
void adapt_truth_table_for_frac_lut(t_pb_graph_pin* lut_out_pb_graph_pin,
|
||||
int truth_table_length,
|
||||
char** truth_table);
|
||||
|
||||
int determine_lut_path_id(int lut_size,
|
||||
int* lut_inputs);
|
||||
|
||||
boolean is_pb_wired_lut(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_type* cur_pb_type,
|
||||
t_rr_node* pb_rr_graph);
|
||||
|
||||
int get_wired_lut_net_name(t_pb_graph_node* lut_pb_graph_node,
|
||||
t_pb_type* lut_pb_type,
|
||||
t_rr_node* pb_rr_graph);
|
||||
|
||||
void allocate_wired_lut_pbs(t_pb*** wired_lut_pbs,
|
||||
int num_pb_type_children,
|
||||
int num_pbs,
|
||||
int wired_lut_child_id,
|
||||
int wired_lut_pb_id);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,85 @@
|
|||
|
||||
int determine_num_sram_bits_mux_basis_subckt(t_spice_model* mux_spice_model,
|
||||
int mux_size,
|
||||
int num_input_per_level,
|
||||
boolean special_basis);
|
||||
|
||||
int determine_tree_mux_level(int mux_size);
|
||||
|
||||
int determine_num_input_basis_multilevel_mux(int mux_size,
|
||||
int mux_level);
|
||||
|
||||
int tree_mux_last_level_input_num(int num_level,
|
||||
int mux_size);
|
||||
|
||||
int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
|
||||
int mux_size);
|
||||
|
||||
int* decode_onelevel_mux_sram_bits(int fan_in,
|
||||
int mux_level,
|
||||
int path_id);
|
||||
|
||||
int* decode_multilevel_mux_sram_bits(int fan_in,
|
||||
int mux_level,
|
||||
int path_id);
|
||||
|
||||
int* decode_tree_mux_sram_bits(int fan_in,
|
||||
int mux_level,
|
||||
int path_id);
|
||||
|
||||
int get_mux_default_path_id(t_spice_model* mux_spice_model,
|
||||
int mux_size, int path_id);
|
||||
|
||||
int get_mux_full_input_size(t_spice_model* mux_spice_model,
|
||||
int mux_size);
|
||||
|
||||
void decode_cmos_mux_sram_bits(t_spice_model* mux_spice_model,
|
||||
int mux_size, int path_id,
|
||||
int* bit_len, int** conf_bits, int* mux_level);
|
||||
|
||||
void decode_one_level_4t1r_mux(int path_id,
|
||||
int bit_len, int* conf_bits);
|
||||
|
||||
void decode_rram_mux(t_spice_model* mux_spice_model,
|
||||
int mux_size, int path_id,
|
||||
int* bit_len, int** conf_bits, int* mux_level);
|
||||
|
||||
void init_spice_mux_arch(t_spice_model* spice_model,
|
||||
t_spice_mux_arch* spice_mux_arch,
|
||||
int mux_size);
|
||||
|
||||
int find_spice_mux_arch_special_basis_size(t_spice_mux_arch spice_mux_arch);
|
||||
|
||||
t_llist* search_mux_linked_list(t_llist* mux_head,
|
||||
int mux_size,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void check_and_add_mux_to_linked_list(t_llist** muxes_head,
|
||||
int mux_size,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void free_muxes_llist(t_llist* muxes_head);
|
||||
|
||||
void stats_lut_spice_mux(t_llist** muxes_head,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
|
||||
void stats_spice_muxes_routing_arch(t_llist** muxes_head,
|
||||
int num_switch,
|
||||
t_switch_inf* switches,
|
||||
t_spice* spice,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
void stats_mux_spice_model_pb_type_rec(t_llist** muxes_head,
|
||||
t_pb_type* cur_pb_type);
|
||||
|
||||
void stats_mux_spice_model_pb_node_rec(t_llist** muxes_head,
|
||||
t_pb_graph_node* cur_pb_node);
|
||||
|
||||
t_llist* stats_spice_muxes(int num_switch,
|
||||
t_switch_inf* switches,
|
||||
t_spice* spice,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,242 @@
|
|||
void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge);
|
||||
|
||||
void check_pb_graph_pin_edges(t_pb_graph_pin pb_graph_pin);
|
||||
|
||||
void backup_one_pb_rr_node_pack_prev_node_edge(t_rr_node* pb_rr_node);
|
||||
|
||||
int find_parent_pb_type_child_index(t_pb_type* parent_pb_type,
|
||||
int mode_index,
|
||||
t_pb_type* child_pb_type);
|
||||
|
||||
void gen_spice_name_tag_phy_pb_rec(t_phy_pb* cur_phy_pb,
|
||||
char* prefix);
|
||||
|
||||
void gen_spice_name_tag_pb_rec(t_pb* cur_pb,
|
||||
char* prefix);
|
||||
|
||||
void gen_spice_name_tags_all_pbs();
|
||||
|
||||
void gen_spice_name_tags_all_phy_pbs();
|
||||
|
||||
int find_pb_mapped_logical_block_rec(t_pb* cur_pb,
|
||||
t_spice_model* pb_spice_model,
|
||||
char* pb_spice_name_tag);
|
||||
|
||||
int find_grid_mapped_logical_block(int x, int y,
|
||||
t_spice_model* pb_spice_model,
|
||||
char* pb_spice_name_tag);
|
||||
|
||||
void stats_pb_graph_node_port_pin_numbers(t_pb_graph_node* cur_pb_graph_node,
|
||||
int* num_inputs,
|
||||
int* num_outputs,
|
||||
int* num_clock_pins);
|
||||
|
||||
int find_pb_type_idle_mode_index(t_pb_type cur_pb_type);
|
||||
|
||||
int find_pb_type_physical_mode_index(t_pb_type cur_pb_type);
|
||||
|
||||
void mark_grid_type_pb_graph_node_pins_temp_net_num(int x, int y);
|
||||
|
||||
void assign_pb_graph_node_pin_temp_net_num_by_mode_index(t_pb_graph_pin* cur_pb_graph_pin,
|
||||
int mode_index);
|
||||
|
||||
void mark_pb_graph_node_input_pins_temp_net_num(t_pb_graph_node* cur_pb_graph_node,
|
||||
int mode_index);
|
||||
|
||||
void mark_pb_graph_node_clock_pins_temp_net_num(t_pb_graph_node* cur_pb_graph_node,
|
||||
int mode_index);
|
||||
|
||||
void mark_pb_graph_node_output_pins_temp_net_num(t_pb_graph_node* cur_pb_graph_node,
|
||||
int mode_index);
|
||||
|
||||
void rec_mark_pb_graph_node_temp_net_num(t_pb_graph_node* cur_pb_graph_node);
|
||||
|
||||
void load_one_pb_graph_pin_temp_net_num_from_pb(t_phy_pb* cur_pb,
|
||||
t_pb_graph_pin* cur_pb_graph_pin);
|
||||
|
||||
void load_pb_graph_node_temp_net_num_from_pb(t_phy_pb* cur_pb);
|
||||
|
||||
void rec_mark_one_pb_unused_pb_graph_node_temp_net_num(t_phy_pb* cur_pb);
|
||||
|
||||
void update_pb_vpack_net_num_from_temp_net_num(t_phy_pb* cur_pb,
|
||||
t_pb_graph_pin* cur_pb_graph_pin);
|
||||
|
||||
void update_pb_graph_node_temp_net_num_to_pb(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_phy_pb* cur_pb);
|
||||
|
||||
void rec_load_unused_pb_graph_node_temp_net_num_to_pb(t_phy_pb* cur_pb);
|
||||
|
||||
void mark_one_pb_parasitic_nets(t_phy_pb* cur_pb);
|
||||
|
||||
int count_num_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_conf_bits_pb_type_mode_interc(t_mode* cur_pb_type_mode,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int rec_count_num_conf_bits_pb_type_default_mode(t_pb_type* cur_pb_type,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
int rec_count_num_conf_bits_pb_type_physical_mode(t_pb_type* cur_pb_type,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
int rec_count_num_conf_bits_pb(t_pb* cur_pb,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
void init_one_grid_num_conf_bits(int ix, int iy,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
void init_grids_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
void map_clb_pins_to_pb_graph_pins();
|
||||
|
||||
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
||||
t_spice_model_port* spice_model_port);
|
||||
|
||||
t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
|
||||
enum e_spice_model_port_type port_type,
|
||||
int* port_num);
|
||||
|
||||
|
||||
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin);
|
||||
|
||||
t_spice_model* find_pb_graph_pin_in_edges_interc_spice_model(t_pb_graph_pin pb_graph_pin);
|
||||
|
||||
int find_path_id_between_pb_rr_nodes(t_rr_node* local_rr_graph,
|
||||
int src_node,
|
||||
int des_node);
|
||||
|
||||
t_pb* get_child_pb_for_phy_pb_graph_node(t_pb* cur_pb, int ipb, int jpb);
|
||||
|
||||
t_phy_pb* get_phy_child_pb_for_phy_pb_graph_node(t_phy_pb* cur_phy_pb, int ipb, int jpb);
|
||||
|
||||
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin) ;
|
||||
|
||||
t_spice_model* find_pb_graph_pin_in_edges_interc_model(t_pb_graph_pin pb_graph_pin) ;
|
||||
|
||||
void find_interc_fan_in_des_pb_graph_pin(t_pb_graph_pin* des_pb_graph_pin,
|
||||
t_mode* cur_mode,
|
||||
t_interconnect** cur_interc,
|
||||
int* fan_in) ;
|
||||
|
||||
void find_interc_des_pb_graph_pin(t_pb_graph_pin* des_pb_graph_pin,
|
||||
int cur_mode,
|
||||
t_interconnect** cur_interc);
|
||||
|
||||
void rec_count_num_iopads_pb_type_physical_mode(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_count_num_iopads_pb_type_default_mode(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_count_num_iopads_pb(t_pb* cur_pb);
|
||||
|
||||
void init_one_grid_num_iopads(int ix, int iy);
|
||||
|
||||
void init_grids_num_iopads();
|
||||
|
||||
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_count_num_mode_bits_pb(t_pb* cur_pb);
|
||||
|
||||
void init_one_grid_num_mode_bits(int ix, int iy);
|
||||
|
||||
void init_grids_num_mode_bits();
|
||||
|
||||
t_pb* get_lut_child_pb(t_pb* cur_lut_pb,
|
||||
int mode_index);
|
||||
|
||||
t_phy_pb* get_lut_child_phy_pb(t_phy_pb* cur_lut_pb,
|
||||
int mode_index);
|
||||
|
||||
t_pb* get_hardlogic_child_pb(t_pb* cur_hardlogic_pb,
|
||||
int mode_index);
|
||||
|
||||
int get_grid_pin_height(int grid_x, int grid_y, int pin_index);
|
||||
|
||||
int get_grid_pin_side(int grid_x, int grid_y, int pin_index);
|
||||
|
||||
int* decode_mode_bits(char* mode_bits, int* num_sram_bits);
|
||||
|
||||
enum e_interconnect determine_actual_pb_interc_type(t_interconnect* def_interc,
|
||||
int fan_in) ;
|
||||
|
||||
int count_pin_number_one_port_pb_graph_node(int num_ports, int* num_pins);
|
||||
|
||||
int count_pin_number_one_pb_graph_node(t_pb_graph_node* cur_pb_graph_node);
|
||||
|
||||
int count_pb_graph_node_input_edge_in_phy_mode(t_pb_graph_pin* cur_pb_graph_pin,
|
||||
int phy_mode_index);
|
||||
|
||||
int count_pb_graph_node_output_edge_in_phy_mode(t_pb_graph_pin* cur_pb_graph_pin,
|
||||
int phy_mode_index);
|
||||
|
||||
t_pb_type* rec_get_pb_type_by_name(t_pb_type* cur_pb_type,
|
||||
char* pb_type_name);
|
||||
|
||||
void decode_physical_mode_pin_annotation(int phy_pb_type_port_size,
|
||||
char* phy_mode_pin,
|
||||
char** port_name,
|
||||
int* pin_msb, int* pin_lsb);
|
||||
|
||||
void annotate_physical_mode_pin_to_pb_type(t_port* cur_pb_type_port,
|
||||
t_pb_type* phy_pb_type);
|
||||
|
||||
void annotate_pb_type_port_to_phy_pb_type(t_pb_type* cur_pb_type,
|
||||
t_pb_type* phy_pb_type);
|
||||
|
||||
t_pb_graph_node* rec_get_pb_graph_node_by_pb_type_and_placement_index_in_top_node(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_type* target_pb_type,
|
||||
int target_placement_index);
|
||||
|
||||
boolean check_pin_number_match_phy_pb_graph_pin(t_pb_graph_pin* cur_pb_graph_pin,
|
||||
t_pb_graph_pin* phy_pb_graph_pin);
|
||||
|
||||
void link_one_pb_graph_node_pin_to_phy_pb_graph_pin(t_pb_graph_pin* cur_pb_graph_pin,
|
||||
t_pb_graph_node* phy_pb_graph_node);
|
||||
|
||||
void link_pb_graph_node_pins_to_phy_pb_graph_pins(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_graph_node* phy_pb_graph_node);
|
||||
|
||||
void rec_reset_pb_graph_node_rr_node_index_physical_pb(t_pb_graph_node* cur_pb_graph_node);
|
||||
|
||||
void rec_alloc_phy_pb_children(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_phy_pb* cur_phy_pb);
|
||||
|
||||
t_phy_pb* rec_get_phy_pb_by_name(t_phy_pb* cur_phy_pb,
|
||||
char* phy_pb_name);
|
||||
|
||||
int get_pb_graph_node_wired_lut_logical_block_index(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_rr_node* op_pb_rr_graph);
|
||||
|
||||
void rec_reset_pb_graph_node_rr_node_index_physical_pb(t_pb_graph_node* cur_pb_graph_node);
|
||||
|
||||
void sync_wired_lut_to_one_phy_pb(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_phy_pb* cur_phy_pb,
|
||||
t_rr_node* op_pb_rr_graph);
|
||||
|
||||
void rec_sync_op_pb_mapping_to_phy_pb_children(t_pb* cur_op_pb,
|
||||
t_phy_pb* cur_phy_pb);
|
||||
|
||||
void alloc_and_load_phy_pb_children_for_one_mapped_block(t_pb* cur_pb,
|
||||
t_phy_pb* cur_phy_pb);
|
||||
|
||||
void get_mapped_lut_phy_pb_input_pin_vpack_net_num(t_phy_pb* lut_phy_pb,
|
||||
int* num_lut_pin, int** lut_pin_net);
|
||||
|
||||
void get_mapped_lut_pb_input_pin_vpack_net_num(t_pb* lut_pb,
|
||||
int* num_lut_pin, int** lut_pin_net);
|
||||
|
||||
void get_lut_logical_block_input_pin_vpack_net_num(t_logical_block* lut_logical_block,
|
||||
int* num_lut_pin, int** lut_pin_net);
|
||||
|
||||
void rec_reset_pb_type_temp_placement_index(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_reset_pb_type_phy_pb_type(t_pb_type* cur_pb_type);
|
||||
|
||||
boolean is_pb_used_for_wiring(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_type* cur_pb_type,
|
||||
t_rr_node* pb_rr_graph);
|
||||
|
||||
char* get_pb_graph_full_name_in_hierarchy(t_pb_graph_node* cur_pb_graph_node);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,108 @@
|
|||
|
||||
void init_rr_graph(INOUTP t_rr_graph* local_rr_graph);
|
||||
|
||||
void alloc_rr_graph_net_rr_sources_and_sinks(t_rr_graph* local_rr_graph);
|
||||
|
||||
void alloc_rr_graph_net_rr_terminals(t_rr_graph* local_rr_graph);
|
||||
|
||||
void alloc_rr_graph_route_static_structs(t_rr_graph* local_rr_graph,
|
||||
int heap_size);
|
||||
|
||||
void load_rr_graph_chan_rr_indices(t_rr_graph* local_rr_graph,
|
||||
INP int nodes_per_chan, INP int chan_len,
|
||||
INP int num_chans, INP t_rr_type type, INP t_seg_details * seg_details,
|
||||
INOUTP int *index);
|
||||
|
||||
void alloc_and_load_rr_graph_rr_node(INOUTP t_rr_graph* local_rr_graph,
|
||||
int local_num_rr_nodes);
|
||||
|
||||
void alloc_and_load_rr_graph_rr_node_indices(t_rr_graph* local_rr_graph,
|
||||
INP int nodes_per_chan,
|
||||
INP int L_nx, INP int L_ny, t_grid_tile** L_grid,
|
||||
INOUTP int *index, INP t_seg_details * seg_details);
|
||||
|
||||
void alloc_and_load_rr_graph_switch_inf(INOUTP t_rr_graph* local_rr_graph,
|
||||
int num_switch_inf,
|
||||
INP t_switch_inf* switch_inf);
|
||||
|
||||
void alloc_and_load_rr_graph_route_structs(t_rr_graph* local_rr_graph);
|
||||
|
||||
t_trace* alloc_rr_graph_trace_data(t_rr_graph* local_rr_graph);
|
||||
|
||||
t_heap * get_rr_graph_heap_head(t_rr_graph* local_rr_graph);
|
||||
|
||||
t_linked_f_pointer* alloc_rr_graph_linked_f_pointer(t_rr_graph* local_rr_graph);
|
||||
|
||||
t_heap * alloc_rr_graph_heap_data(t_rr_graph* local_rr_graph);
|
||||
|
||||
void add_to_rr_graph_mod_list(t_rr_graph* local_rr_graph,
|
||||
float *fptr);
|
||||
|
||||
void empty_rr_graph_heap(t_rr_graph* local_rr_graph);
|
||||
|
||||
void reset_rr_graph_rr_node_route_structs(t_rr_graph* local_rr_graph);
|
||||
|
||||
t_trace* update_rr_graph_traceback(t_rr_graph* local_rr_graph,
|
||||
t_heap *hptr, int inet);
|
||||
|
||||
void reset_rr_graph_path_costs(t_rr_graph* local_rr_graph);
|
||||
|
||||
void alloc_rr_graph_rr_indexed_data(t_rr_graph* local_rr_graph, int L_num_rr_indexed_data);
|
||||
|
||||
float get_rr_graph_rr_cong_cost(t_rr_graph* local_rr_graph,
|
||||
int rr_node_index);
|
||||
|
||||
|
||||
void add_heap_node_to_rr_graph_heap(t_rr_graph* local_rr_graph,
|
||||
t_heap *hptr);
|
||||
|
||||
void add_node_to_rr_graph_heap(t_rr_graph* local_rr_graph,
|
||||
int inode, float cost, int prev_node, int prev_edge,
|
||||
float backward_path_cost, float R_upstream);
|
||||
|
||||
void mark_rr_graph_sinks(t_rr_graph* local_rr_graph,
|
||||
int inet, int start_isink, boolean* net_sink_routed);
|
||||
|
||||
void mark_rr_graph_ends(t_rr_graph* local_rr_graph,
|
||||
int inet);
|
||||
|
||||
void invalidate_rr_graph_heap_entries(t_rr_graph* local_rr_graph,
|
||||
int sink_node, int ipin_node);
|
||||
|
||||
float get_rr_graph_rr_node_pack_intrinsic_cost(t_rr_graph* local_rr_graph,
|
||||
int inode);
|
||||
|
||||
void free_rr_graph_rr_nodes(t_rr_graph* local_rr_graph);
|
||||
|
||||
void free_rr_graph_switch_inf(INOUTP t_rr_graph* local_rr_graph);
|
||||
|
||||
void free_rr_graph_route_structs(t_rr_graph* local_rr_graph);
|
||||
|
||||
void free_rr_graph(t_rr_graph* local_rr_graph);
|
||||
|
||||
void free_rr_graph_heap_data(t_rr_graph* local_rr_graph,
|
||||
t_heap *hptr);
|
||||
|
||||
void free_rr_graph_traceback(t_rr_graph* local_rr_graph,
|
||||
int inet);
|
||||
|
||||
void build_prev_node_list_rr_nodes(int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node);
|
||||
|
||||
void alloc_and_load_prev_node_list_rr_graph_rr_nodes(t_rr_graph* local_rr_graph);
|
||||
|
||||
void backannotate_rr_graph_routing_results_to_net_name(t_rr_graph* local_rr_graph);
|
||||
|
||||
int get_rr_graph_net_vpack_net_index(t_rr_graph* local_rr_graph,
|
||||
int net_index);
|
||||
|
||||
int get_rr_graph_net_index_with_vpack_net(t_rr_graph* local_rr_graph,
|
||||
int vpack_net_index);
|
||||
|
||||
void get_chan_rr_node_start_coordinate(t_rr_node* chan_rr_node,
|
||||
int* x_start, int* y_start);
|
||||
|
||||
void get_chan_rr_node_end_coordinate(t_rr_node* chan_rr_node,
|
||||
int* x_end, int* y_end);
|
||||
|
||||
int get_rr_node_wire_length(t_rr_node* src_rr_node);
|
|
@ -20,15 +20,18 @@
|
|||
#include "vpr_utils.h"
|
||||
#include "path_delay.h"
|
||||
#include "stats.h"
|
||||
#include "route_common.h"
|
||||
|
||||
/* Include spice support headers*/
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_spice_timing_utils.h"
|
||||
#include "fpga_spice_backannotate_utils.h"
|
||||
#include "fpga_x2p_types.h"
|
||||
#include "fpga_x2p_globals.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
#include "fpga_x2p_timing_utils.h"
|
||||
#include "fpga_x2p_backannotate_utils.h"
|
||||
#include "fpga_x2p_pbtypes_utils.h"
|
||||
#include "verilog_api.h"
|
||||
#include "fpga_spice_setup.h"
|
||||
#include "fpga_x2p_setup.h"
|
||||
|
||||
/***** Subroutines Declarations *****/
|
||||
static
|
||||
|
@ -152,49 +155,30 @@ void match_pb_types_spice_model_rec(t_pb_type* cur_pb_type,
|
|||
return;
|
||||
}
|
||||
|
||||
/* If there is a spice_model_name, this is a leaf node!*/
|
||||
if (NULL != cur_pb_type->spice_model_name) {
|
||||
/* If there is a spice_model_name or refer to a physical pb type , this is a leaf node!*/
|
||||
if ((NULL != cur_pb_type->spice_model_name) || (NULL != cur_pb_type->physical_pb_type_name)) {
|
||||
/* What annoys me is VPR create a sub pb_type for each lut which suppose to be a leaf node
|
||||
* This may bring software convience but ruins SPICE modeling
|
||||
*/
|
||||
/* if this is not a physical pb_type, we do not care the spice model name and associated checking */
|
||||
if (NULL != cur_pb_type->physical_pb_type_name) {
|
||||
vpr_printf(TIO_MESSAGE_INFO, "(File:%s,LINE[%d]) Bypass spice model checking for pb_type(%s)!\n",
|
||||
__FILE__, __LINE__, cur_pb_type->name);
|
||||
return;
|
||||
}
|
||||
/* Let's find a matched spice model!*/
|
||||
printf("INFO: matching cur_pb_type=%s with spice_model_name=%s...\n",cur_pb_type->name, cur_pb_type->spice_model_name);
|
||||
assert(NULL == cur_pb_type->spice_model);
|
||||
cur_pb_type->spice_model = find_name_matched_spice_model(cur_pb_type->spice_model_name, num_spice_model, spice_models);
|
||||
if (NULL == cur_pb_type->spice_model) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,LINE[%d]) Fail to find a defined SPICE model called %s, in pb_type(%s)!\n",__FILE__, __LINE__, cur_pb_type->spice_model_name, cur_pb_type->name);
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "(File:%s,LINE[%d]) Fail to find a defined SPICE model called %s, in pb_type(%s)!\n",
|
||||
__FILE__, __LINE__, cur_pb_type->spice_model_name, cur_pb_type->name);
|
||||
exit(1);
|
||||
}
|
||||
/* Map pb_type ports to SPICE model ports*/
|
||||
map_pb_type_port_to_spice_model_ports(cur_pb_type,cur_pb_type->spice_model);
|
||||
return;
|
||||
} else {
|
||||
/* Find default spice model if this is a primitive block */
|
||||
if (LUT_CLASS == cur_pb_type->class_type) {
|
||||
cur_pb_type->spice_model = get_default_spice_model(SPICE_MODEL_LUT, num_spice_model, spice_models);
|
||||
/* Complete the name */
|
||||
cur_pb_type->spice_model_name = my_strdup(cur_pb_type->spice_model->name);
|
||||
if (NULL == cur_pb_type->spice_model) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,LINE[%d]) Fail to find a defined SPICE model called %s, in pb_type(%s)!\n",__FILE__, __LINE__, cur_pb_type->spice_model_name, cur_pb_type->name);
|
||||
exit(1);
|
||||
}
|
||||
/* Map pb_type ports to SPICE model ports*/
|
||||
map_pb_type_port_to_spice_model_ports(cur_pb_type,cur_pb_type->spice_model);
|
||||
return;
|
||||
} else if (LATCH_CLASS == cur_pb_type->class_type) {
|
||||
cur_pb_type->spice_model = get_default_spice_model(SPICE_MODEL_FF, num_spice_model, spice_models);
|
||||
/* Complete the name */
|
||||
cur_pb_type->spice_model_name = my_strdup(cur_pb_type->spice_model->name);
|
||||
if (NULL == cur_pb_type->spice_model) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"(File:%s,LINE[%d]) Fail to find a defined SPICE model called %s, in pb_type(%s)!\n",__FILE__, __LINE__, cur_pb_type->spice_model_name, cur_pb_type->name);
|
||||
exit(1);
|
||||
}
|
||||
/* Map pb_type ports to SPICE model ports*/
|
||||
map_pb_type_port_to_spice_model_ports(cur_pb_type,cur_pb_type->spice_model);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Traversal the hierarchy*/
|
||||
for (imode = 0; imode < cur_pb_type->num_modes; imode++) {
|
||||
/* Task 1: Find the interconnections and match the spice_model */
|
||||
|
@ -219,11 +203,23 @@ void match_pb_types_spice_model_rec(t_pb_type* cur_pb_type,
|
|||
} else {
|
||||
cur_pb_type->modes[imode].interconnect[jinterc].spice_model =
|
||||
get_default_spice_model(SPICE_MODEL_MUX,num_spice_model,spice_models);
|
||||
if (NULL != cur_pb_type->modes[imode].interconnect[jinterc].loop_breaker_string) {
|
||||
if (NULL == cur_pb_type->modes[imode].interconnect[jinterc].spice_model->input_buffer) {
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Line[%d] Cannot disable an interconnect without input buffering",
|
||||
cur_pb_type->modes[imode].interconnect[jinterc].line_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MUX_INTERC:
|
||||
cur_pb_type->modes[imode].interconnect[jinterc].spice_model =
|
||||
get_default_spice_model(SPICE_MODEL_MUX,num_spice_model,spice_models);
|
||||
if (NULL != cur_pb_type->modes[imode].interconnect[jinterc].loop_breaker_string) {
|
||||
if (NULL == cur_pb_type->modes[imode].interconnect[jinterc].spice_model->input_buffer) {
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Line[%d] Cannot disable an interconnect without input buffering",
|
||||
cur_pb_type->modes[imode].interconnect[jinterc].line_num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -262,6 +258,12 @@ void match_pb_types_spice_model_rec(t_pb_type* cur_pb_type,
|
|||
exit(1);
|
||||
}
|
||||
}
|
||||
if (NULL != cur_pb_type->modes[imode].interconnect[jinterc].loop_breaker_string) {
|
||||
if (NULL == cur_pb_type->modes[imode].interconnect[jinterc].spice_model->input_buffer) {
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Line[%d] Cannot disable an interconnect without input buffering",
|
||||
cur_pb_type->modes[imode].interconnect[jinterc].line_num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MUX_INTERC:
|
||||
if (SPICE_MODEL_MUX != cur_pb_type->modes[imode].interconnect[jinterc].spice_model->type) {
|
||||
|
@ -269,6 +271,12 @@ void match_pb_types_spice_model_rec(t_pb_type* cur_pb_type,
|
|||
__FILE__, __LINE__, cur_pb_type->modes[imode].interconnect[jinterc].spice_model_name, cur_pb_type->name);
|
||||
exit(1);
|
||||
}
|
||||
if (NULL != cur_pb_type->modes[imode].interconnect[jinterc].loop_breaker_string) {
|
||||
if (NULL == cur_pb_type->modes[imode].interconnect[jinterc].spice_model->input_buffer) {
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Line[%d] Cannot disable an interconnect without input buffering",
|
||||
cur_pb_type->modes[imode].interconnect[jinterc].line_num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -600,14 +608,94 @@ void init_check_arch_spice_models(t_arch* arch,
|
|||
}
|
||||
}
|
||||
|
||||
/* 7. Create timing graph for spice models */
|
||||
for (i = 0; i < arch->spice->num_spice_model; i++) {
|
||||
/* See if we need a timing graph */
|
||||
if (0 == arch->spice->spice_models[i].num_delay_info) {
|
||||
continue;
|
||||
}
|
||||
annotate_spice_model_timing(&(arch->spice->spice_models[i]));
|
||||
}
|
||||
/* 7. Create timing graph for spice models */
|
||||
for (i = 0; i < arch->spice->num_spice_model; i++) {
|
||||
/* See if we need a timing graph */
|
||||
if (0 == arch->spice->spice_models[i].num_delay_info) {
|
||||
continue;
|
||||
}
|
||||
annotate_spice_model_timing(&(arch->spice->spice_models[i]));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Recursively traverse pb_type graph and mark idle mode
|
||||
* Only one idle mode is allowed under each pb_type
|
||||
*/
|
||||
static
|
||||
void rec_identify_pb_type_idle_mode(t_pb_type* cur_pb_type) {
|
||||
int imode, ichild, idle_mode_idx;
|
||||
|
||||
/* Do it only when we have modes */
|
||||
if ( 0 < cur_pb_type->num_modes) {
|
||||
/* Find idle mode index */
|
||||
idle_mode_idx = find_pb_type_idle_mode_index(*cur_pb_type);
|
||||
cur_pb_type->modes[idle_mode_idx].define_idle_mode = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Traverse all the modes for identifying idle mode */
|
||||
for (imode = 0; cur_pb_type->num_modes; imode++) {
|
||||
/* Check each pb_type_child */
|
||||
for (ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ichild++) {
|
||||
rec_identify_pb_type_idle_mode(&(cur_pb_type->modes[imode].pb_type_children[ichild]));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Recursively traverse pb_type graph and mark idle and physical mode
|
||||
* Only one idle mode and one physical mode is allowed under each pb_type
|
||||
* In particular, a physical mode should appear only when its parent is a physical mode.
|
||||
*/
|
||||
static
|
||||
void rec_identify_pb_type_phy_mode(t_pb_type* cur_pb_type) {
|
||||
int imode, ichild, phy_mode_idx;
|
||||
|
||||
/* Only try to find physical mode when parent is a physical mode or this is the top cur_pb_type! */
|
||||
if (FALSE == is_primitive_pb_type(cur_pb_type)) {
|
||||
if ((NULL == cur_pb_type->parent_mode)
|
||||
|| (TRUE == cur_pb_type->parent_mode->define_physical_mode)) {
|
||||
/* Find physical mode index */
|
||||
phy_mode_idx = find_pb_type_physical_mode_index(*cur_pb_type);
|
||||
cur_pb_type->modes[phy_mode_idx].define_physical_mode = TRUE;
|
||||
} else {
|
||||
/* The parent must not be a physical mode*/
|
||||
assert (FALSE == cur_pb_type->parent_mode->define_physical_mode);
|
||||
phy_mode_idx = -1;
|
||||
/* Traverse all the modes for identifying idle mode */
|
||||
for (imode = 0; cur_pb_type->num_modes; imode++) {
|
||||
cur_pb_type->modes[imode].define_physical_mode = FALSE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Traverse all the modes for identifying idle mode */
|
||||
for (imode = 0; cur_pb_type->num_modes; imode++) {
|
||||
/* Check each pb_type_child */
|
||||
for (ichild = 0; ichild < cur_pb_type->modes[imode].num_pb_type_children; ichild++) {
|
||||
rec_identify_pb_type_phy_mode(&(cur_pb_type->modes[imode].pb_type_children[ichild]));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Identify physical mode of pb_types in each defined complex block */
|
||||
static
|
||||
void init_check_arch_pb_type_idle_and_phy_mode(t_arch* Arch) {
|
||||
int itype;
|
||||
|
||||
for (itype = 0; itype < num_types; itype++) {
|
||||
if (type_descriptors[itype].pb_type) {
|
||||
rec_identify_pb_type_idle_mode(type_descriptors[itype].pb_type);
|
||||
rec_identify_pb_type_phy_mode(type_descriptors[itype].pb_type);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -667,9 +755,9 @@ void rec_add_pb_type_keywords_to_list(t_pb_type* cur_pb_type,
|
|||
if (NULL == cur_pb_type->modes[imode].pb_type_children[jpb].spice_model) {
|
||||
rec_add_pb_type_keywords_to_list(&(cur_pb_type->modes[imode].pb_type_children[jpb]),
|
||||
cur, keywords, pass_on_prefix);
|
||||
my_free(pass_on_prefix);
|
||||
}
|
||||
}
|
||||
my_free(pass_on_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -872,7 +960,6 @@ void check_keywords_conflict(t_arch Arch) {
|
|||
static
|
||||
t_llist* check_and_add_one_global_port_to_llist(t_llist* old_head,
|
||||
t_spice_model_port* candidate_port) {
|
||||
boolean is_new_global_port = TRUE;
|
||||
t_llist* temp = old_head;
|
||||
t_llist* new_head = NULL;
|
||||
|
||||
|
@ -880,7 +967,6 @@ t_llist* check_and_add_one_global_port_to_llist(t_llist* old_head,
|
|||
if (0 == strcmp(candidate_port->prefix,
|
||||
((t_spice_model_port*)(temp->dptr))->prefix) ) {
|
||||
/* Find a same global port name, we do nothing, return directly */
|
||||
is_new_global_port = FALSE;
|
||||
return old_head;
|
||||
}
|
||||
/* Go to the next */
|
||||
|
@ -1167,8 +1253,7 @@ int check_and_rename_logical_block_and_net_names(t_llist* LL_reserved_syntax_cha
|
|||
fprintf(fp, "-------VPACK_NET renaming report END ----------\n");
|
||||
|
||||
if ((0 < num_violations) && ( FALSE == rename_illegal_port )) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "Detect %d port violate syntax rules while renaming port is disabled\n", num_violations);
|
||||
exit(1);
|
||||
vpr_printf(TIO_MESSAGE_WARNING, "Detect %d port violate syntax rules while renaming port is disabled\n", num_violations);
|
||||
}
|
||||
|
||||
/* close fp */
|
||||
|
@ -1209,16 +1294,16 @@ void spice_net_info_add_density_weight(float signal_density_weight) {
|
|||
}
|
||||
}
|
||||
|
||||
void fpga_spice_free(t_arch* Arch) {
|
||||
void fpga_x2p_free(t_arch* Arch) {
|
||||
/* Free index low and high */
|
||||
free_spice_model_grid_index_low_high(Arch->spice->num_spice_model, Arch->spice->spice_models);
|
||||
free_spice_model_routing_index_low_high(Arch->spice->num_spice_model, Arch->spice->spice_models);
|
||||
}
|
||||
|
||||
/* Top-level function of FPGA-SPICE setup */
|
||||
void fpga_spice_setup(t_vpr_setup vpr_setup,
|
||||
void fpga_x2p_setup(t_vpr_setup vpr_setup,
|
||||
t_arch* Arch) {
|
||||
|
||||
int num_rename_violation = 0;
|
||||
int num_clocks = 0;
|
||||
float vpr_crit_path_delay = 0.;
|
||||
float vpr_clock_freq = 0.;
|
||||
|
@ -1230,6 +1315,9 @@ void fpga_spice_setup(t_vpr_setup vpr_setup,
|
|||
/* Initialize Arch SPICE MODELS*/
|
||||
init_check_arch_spice_models(Arch, &(vpr_setup.RoutingArch));
|
||||
|
||||
/* Initialize idle mode and physical mode of each pb_type and pb_graph_node */
|
||||
init_check_arch_pb_type_idle_and_phy_mode(Arch);
|
||||
|
||||
/* Create and initialize a linked list for global ports */
|
||||
global_ports_head = init_llist_global_ports(Arch->spice);
|
||||
vpr_printf(TIO_MESSAGE_INFO, "Detect %d global ports...\n",
|
||||
|
@ -1248,41 +1336,60 @@ void fpga_spice_setup(t_vpr_setup vpr_setup,
|
|||
reserved_syntax_char_head);
|
||||
|
||||
|
||||
/* Check and rename io names to avoid violating SPICE or Verilog syntax */
|
||||
/* Check and rename io names to avoid violating SPICE or Verilog syntax
|
||||
* Only valid when Verilog generator or SPICE generator is enabled
|
||||
*/
|
||||
num_rename_violation =
|
||||
check_and_rename_logical_block_and_net_names(reserved_syntax_char_head,
|
||||
vpr_setup.FileNameOpts.CircuitName,
|
||||
vpr_setup.FPGA_SPICE_Opts.rename_illegal_port,
|
||||
num_logical_blocks, logical_block,
|
||||
num_nets, clb_net,
|
||||
num_logical_nets, vpack_net);
|
||||
|
||||
/* Check Activity file is valid */
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.read_act_file) {
|
||||
if (1 == try_access_file(vpr_setup.FileNameOpts.ActFile)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"Activity file (%s) does not exists! Please provide a valid file path!\n",
|
||||
vpr_setup.FileNameOpts.ActFile);
|
||||
exit(1);
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Check Activity file (%s) is a valid file path!\n",
|
||||
vpr_setup.FileNameOpts.ActFile);
|
||||
}
|
||||
/* Violation is not allowed for SPICE and Verilog Generator! */
|
||||
if (((0 < num_rename_violation) && (FALSE == vpr_setup.FPGA_SPICE_Opts.rename_illegal_port))
|
||||
&& ((TRUE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.do_spice)
|
||||
|| (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.dump_syn_verilog))) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR, "Port name syntax violations is not allowed for SPICE and Verilog Generators!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Update global options:
|
||||
* 1. run_parasitic_net_estimation
|
||||
* 2. run_testbench_load_extraction
|
||||
*/
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_parasitic_net_estimation_off) {
|
||||
run_parasitic_net_estimation = TRUE;
|
||||
if (FALSE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_parasitic_net_estimation) {
|
||||
run_parasitic_net_estimation = FALSE;
|
||||
}
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_testbench_load_extraction_off) {
|
||||
|
||||
run_testbench_load_extraction = TRUE;
|
||||
if (FALSE == vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_testbench_load_extraction) {
|
||||
run_testbench_load_extraction = FALSE;
|
||||
vpr_printf(TIO_MESSAGE_WARNING, "SPICE testbench load extraction is turned off...Accuracy loss may be expected!\n");
|
||||
}
|
||||
|
||||
/* Check Activity file is valid */
|
||||
if (TRUE == vpr_setup.FPGA_SPICE_Opts.read_act_file) {
|
||||
if (1 == try_access_file(vpr_setup.FileNameOpts.ActFile)) {
|
||||
vpr_printf(TIO_MESSAGE_ERROR,"Activity file (%s) does not exists! Please provide a valid file path!\n",
|
||||
vpr_setup.FileNameOpts.ActFile);
|
||||
exit(1);
|
||||
} else {
|
||||
vpr_printf(TIO_MESSAGE_INFO,"Check Activity file (%s) is a valid file path!\n",
|
||||
vpr_setup.FileNameOpts.ActFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* Backannotation for post routing information */
|
||||
spice_backannotate_vpr_post_route_info(vpr_setup.RoutingArch,
|
||||
vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_parasitic_net_estimation_off);
|
||||
vpr_setup.FPGA_SPICE_Opts.read_act_file,
|
||||
vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_parasitic_net_estimation);
|
||||
|
||||
/* Not should be done when read_act_file is disabled */
|
||||
if (FALSE == vpr_setup.FPGA_SPICE_Opts.read_act_file) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Auto check the density and recommend sim_num_clock_cylce */
|
||||
vpr_crit_path_delay = get_critical_path_delay()/1e9;
|
|
@ -4,7 +4,7 @@ void init_check_arch_spice_models(t_arch* arch,
|
|||
|
||||
void check_keywords_conflict(t_arch Arch);
|
||||
|
||||
void fpga_spice_free(t_arch* Arch);
|
||||
void fpga_x2p_free(t_arch* Arch);
|
||||
|
||||
void fpga_spice_setup(t_vpr_setup vpr_setup,
|
||||
void fpga_x2p_setup(t_vpr_setup vpr_setup,
|
||||
t_arch* Arch);
|
|
@ -28,8 +28,8 @@
|
|||
/* Include SPICE support headers*/
|
||||
#include "quicksort.h"
|
||||
#include "linkedlist.h"
|
||||
#include "fpga_spice_globals.h"
|
||||
#include "fpga_spice_utils.h"
|
||||
#include "fpga_x2p_globals.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
|
||||
/* Build the list of spice_model_ports provided in the cur_spice_model delay_info */
|
||||
t_spice_model_port** get_spice_model_delay_info_ports(t_spice_model* cur_spice_model,
|
||||
|
@ -41,7 +41,7 @@ t_spice_model_port** get_spice_model_delay_info_ports(t_spice_model* cur_spice_m
|
|||
t_spice_model_port** port = NULL;
|
||||
|
||||
/* Get input ports */
|
||||
tokens = my_strtok(port_list, " ", &num_token);
|
||||
tokens = fpga_spice_strtok(port_list, " ", &num_token);
|
||||
/* allocate in_port */
|
||||
port = (t_spice_model_port**) my_malloc(sizeof(t_spice_model_port*) * num_token);
|
||||
/* Find corresponding spice_model_port */
|
|
@ -0,0 +1,137 @@
|
|||
/* Define the basic data structures used for FPGA-SPICE */
|
||||
|
||||
/* Default ID of switch used in rr_node */
|
||||
#define DEFAULT_SWITCH_ID 0
|
||||
|
||||
/* Default prev_node ID of a rr_node */
|
||||
#define DEFAULT_PREV_NODE -1
|
||||
|
||||
/* Default path ID of a unused multiplexer */
|
||||
#define DEFAULT_PATH_ID -1
|
||||
|
||||
/* Default path ID of a unused multiplexer when there are no constant inputs*/
|
||||
#define DEFAULT_MUX_PATH_ID 0
|
||||
|
||||
/* Index of logical block indicating a wired LUT */
|
||||
#define WIRED_LUT_LOGICAL_BLOCK_ID -2
|
||||
|
||||
#define BLIF_LUT_KEYWORD "names"
|
||||
|
||||
/* Mode Index of a LUT:
|
||||
* 0 indicates a wired mode (a buffer)
|
||||
* 0 indicates a regular mode (a buffer)
|
||||
*/
|
||||
#define WIRED_LUT_MODE_INDEX 0
|
||||
#define NORMAL_LUT_MODE_INDEX 1
|
||||
|
||||
/* Key data structure for router: routing resource graph
|
||||
* This data structure store the key parameters that
|
||||
* models a routing resource graph used by router.
|
||||
* 1. number of routing resource nodes in the graph
|
||||
* 2. all the routing resource nodes
|
||||
* 3. router information for each routing resource node
|
||||
*/
|
||||
typedef struct fpga_spice_rr_graph t_rr_graph;
|
||||
struct fpga_spice_rr_graph {
|
||||
/* Routing Resource nodes */
|
||||
int num_rr_nodes;
|
||||
t_rr_node* rr_node;
|
||||
t_ivec*** rr_node_indices;
|
||||
|
||||
/* Switches between routing resource nodes */
|
||||
int num_switch_inf;
|
||||
t_switch_inf* switch_inf;
|
||||
int delayless_switch_index;
|
||||
|
||||
int num_nets; /* number of nets to route */
|
||||
t_net** net; /* nets to route, this is pointer to the existing nets */
|
||||
int* net_to_vpack_net_mapping;
|
||||
int* net_num_sources;
|
||||
int* net_num_sinks;
|
||||
|
||||
/* Gives the rr_node indices of net terminals. */
|
||||
int **net_rr_sources; /* [0..num_nets-1][0..num_pins-1] */
|
||||
int **net_rr_sinks; /* [0..num_nets-1][0..num_pins-1] */
|
||||
int **net_rr_terminals; /* [0..num_nets-1][0..num_pins-1] */
|
||||
t_chunk rr_mem_ch;
|
||||
|
||||
/* Routing statisitics */
|
||||
int num_rr_indexed_data;
|
||||
t_rr_indexed_data *rr_indexed_data; /* [0..(num_rr_indexed_data-1)] */
|
||||
|
||||
t_rr_node_route_inf* rr_node_route_inf;
|
||||
t_bb *route_bb; /* [0..num_nets-1]. Limits area in which each */
|
||||
|
||||
/* Linked list start pointers. Define the routing. */
|
||||
t_trace **trace_head; /* [0..(num_nets-1)] */
|
||||
t_trace **trace_tail; /* [0..(num_nets-1)] */
|
||||
t_trace *trace_free_head;
|
||||
t_chunk trace_ch;
|
||||
|
||||
/**************** Static variables local to route_common.c ******************/
|
||||
t_heap **heap; /* Indexed from [1..heap_size] */
|
||||
int heap_size; /* Number of slots in the heap array */
|
||||
int heap_tail; /* Index of first unused slot in the heap array */
|
||||
|
||||
/* For managing my own list of currently free heap data structures. */
|
||||
t_heap *heap_free_head;
|
||||
/* For keeping track of the sudo malloc memory for the heap*/
|
||||
t_chunk heap_ch;
|
||||
|
||||
t_linked_f_pointer *rr_modified_head;
|
||||
t_linked_f_pointer *linked_f_pointer_free_head;
|
||||
|
||||
t_chunk linked_f_pointer_ch;
|
||||
|
||||
#ifdef DEBUG
|
||||
int num_trace_allocated; /* To watch for memory leaks. */
|
||||
int num_heap_allocated;
|
||||
int num_linked_f_pointer_allocated;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/* Key data structure for physical pb
|
||||
* This data structure store the key parameters that
|
||||
* models a physical_pb.
|
||||
* This is a simplified copy of original t_pb
|
||||
* except the rr_graph part
|
||||
*/
|
||||
typedef struct fpga_spice_phy_pb t_phy_pb;
|
||||
struct fpga_spice_phy_pb {
|
||||
char *name; /* Name of this physical block */
|
||||
t_pb_graph_node *pb_graph_node; /* pointer to pb_graph_node this pb corresponds to */
|
||||
int num_logical_blocks;
|
||||
int* logical_block; /* If this is a terminating pb, gives the logical (netlist) block that it contains */
|
||||
boolean* is_wired_lut; /* Specify if this is a wired LUT (used as buffer) */
|
||||
t_pb_graph_pin** lut_output_pb_graph_pin;
|
||||
int* lut_size;
|
||||
|
||||
int mode; /* mode that this pb is set to */
|
||||
char* mode_bits; /* Mode bits for the logical block */
|
||||
|
||||
t_phy_pb **child_pbs; /* children pbs attached to this pb [0..num_child_pb_types - 1][0..child_type->num_pb - 1] */
|
||||
t_phy_pb *parent_pb; /* pointer to parent node */
|
||||
|
||||
/* Xifan TANG: FPGA-SPICE*/
|
||||
t_rr_graph* rr_graph;
|
||||
/* END */
|
||||
t_phy_pb **rr_node_to_pb_mapping; /* [0..num_local_rr_nodes-1] pointer look-up of which pb this rr_node belongs based on index, NULL if pb does not exist */
|
||||
|
||||
int *lut_pin_remap; /* [0..num_lut_inputs-1] applies only to LUT primitives, stores how LUT inputs were swapped during CAD flow,
|
||||
LUT inputs can be swapped by changing the logic in the LUT, this is useful because the fastest LUT input compared to the slowest is often significant (2-5x),
|
||||
so this optimization is crucial for handling LUT based FPGAs.
|
||||
*/
|
||||
|
||||
/* Xifan TANG: SPICE model support*/
|
||||
char* spice_name_tag;
|
||||
|
||||
/* Xifan TANG: FPGA-SPICE and SynVerilog */
|
||||
int num_reserved_conf_bits;
|
||||
int num_conf_bits;
|
||||
int num_mode_bits;
|
||||
int num_inpads;
|
||||
int num_outpads;
|
||||
int num_iopads;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -34,6 +34,11 @@ t_spice_model* get_default_spice_model(enum e_spice_model_type default_spice_mod
|
|||
t_spice_model_port* find_spice_model_port_by_name(t_spice_model* cur_spice_model,
|
||||
char* port_name);
|
||||
|
||||
void config_one_spice_model_buffer(int num_spice_models,
|
||||
t_spice_model* spice_model,
|
||||
t_spice_model* cur_spice_model,
|
||||
t_spice_model_buffer* cur_spice_model_buffer);
|
||||
|
||||
void config_spice_model_input_output_buffers_pass_gate(int num_spice_models,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
|
@ -49,6 +54,8 @@ t_spice_model_port** find_spice_model_config_done_ports(t_spice_model* spice_mod
|
|||
t_spice_transistor_type* find_mosfet_tech_lib(t_spice_tech_lib tech_lib,
|
||||
e_spice_trans_type trans_type);
|
||||
|
||||
char* my_itobin(int in_int, int bin_len);
|
||||
|
||||
char* my_itoa(int input);
|
||||
|
||||
char* fpga_spice_create_one_subckt_filename(char* file_name_prefix,
|
||||
|
@ -59,64 +66,29 @@ char* chomp_spice_node_prefix(char* spice_node_prefix);
|
|||
|
||||
char* format_spice_node_prefix(char* spice_node_prefix);
|
||||
|
||||
t_port* find_pb_type_port_match_spice_model_port(t_pb_type* pb_type,
|
||||
t_spice_model_port* spice_model_port);
|
||||
|
||||
char* format_spice_node_prefix(char* spice_node_prefix);
|
||||
|
||||
t_port** find_pb_type_ports_match_spice_model_port_type(t_pb_type* pb_type,
|
||||
enum e_spice_model_port_type port_type,
|
||||
int* port_num);
|
||||
|
||||
|
||||
t_block* search_mapped_block(int x, int y, int z);
|
||||
|
||||
|
||||
int determine_num_sram_bits_mux_basis_subckt(t_spice_model* mux_spice_model,
|
||||
int mux_size,
|
||||
int num_input_per_level,
|
||||
boolean special_basis);
|
||||
|
||||
int determine_tree_mux_level(int mux_size);
|
||||
|
||||
int determine_num_input_basis_multilevel_mux(int mux_size,
|
||||
int mux_level);
|
||||
|
||||
int tree_mux_last_level_input_num(int num_level,
|
||||
int mux_size);
|
||||
|
||||
int multilevel_mux_last_level_input_num(int num_level, int num_input_per_unit,
|
||||
int mux_size);
|
||||
|
||||
int determine_lut_path_id(int lut_size,
|
||||
int* lut_inputs);
|
||||
|
||||
int* decode_onelevel_mux_sram_bits(int fan_in,
|
||||
int mux_level,
|
||||
int path_id);
|
||||
|
||||
int* decode_multilevel_mux_sram_bits(int fan_in,
|
||||
int mux_level,
|
||||
int path_id);
|
||||
|
||||
int* decode_tree_mux_sram_bits(int fan_in,
|
||||
int mux_level,
|
||||
int path_id);
|
||||
|
||||
void decode_cmos_mux_sram_bits(t_spice_model* mux_spice_model,
|
||||
int mux_size, int path_id,
|
||||
int* bit_len, int** conf_bits, int* mux_level);
|
||||
|
||||
char** my_strtok(char* str,
|
||||
char* delims,
|
||||
int* len);
|
||||
char** fpga_spice_strtok(char* str,
|
||||
char* delims,
|
||||
int* len);
|
||||
|
||||
int get_opposite_side(int side);
|
||||
|
||||
char* convert_side_index_to_string(int side);
|
||||
|
||||
char* convert_process_corner_to_string(enum e_process_corner process_corner);
|
||||
|
||||
char* convert_chan_type_to_string(t_rr_type chan_type);
|
||||
|
||||
char* convert_cb_type_to_string(t_rr_type chan_type);
|
||||
|
||||
char* convert_chan_rr_node_direction_to_string(enum PORTS chan_rr_node_direction);
|
||||
|
||||
void init_spice_net_info(t_spice_net_info* spice_net_info);
|
||||
|
@ -160,41 +132,6 @@ float get_rr_node_net_probability(t_rr_node node);
|
|||
|
||||
int get_rr_node_net_init_value(t_rr_node node);
|
||||
|
||||
|
||||
int find_parent_pb_type_child_index(t_pb_type* parent_pb_type,
|
||||
int mode_index,
|
||||
t_pb_type* child_pb_type);
|
||||
|
||||
void gen_spice_name_tag_pb_rec(t_pb* cur_pb,
|
||||
char* prefix);
|
||||
|
||||
void gen_spice_name_tags_all_pbs();
|
||||
|
||||
void check_pb_graph_edge(t_pb_graph_edge pb_graph_edge);
|
||||
|
||||
void check_pb_graph_pin_edges(t_pb_graph_pin pb_graph_pin);
|
||||
|
||||
void backup_one_pb_rr_node_pack_prev_node_edge(t_rr_node* pb_rr_node);
|
||||
|
||||
void update_one_grid_pack_prev_node_edge(int x, int y);
|
||||
|
||||
void update_grid_pbs_post_route_rr_graph();
|
||||
|
||||
int find_pb_mapped_logical_block_rec(t_pb* cur_pb,
|
||||
t_spice_model* pb_spice_model,
|
||||
char* pb_spice_name_tag);
|
||||
|
||||
int find_grid_mapped_logical_block(int x, int y,
|
||||
t_spice_model* pb_spice_model,
|
||||
char* pb_spice_name_tag);
|
||||
|
||||
void stats_pb_graph_node_port_pin_numbers(t_pb_graph_node* cur_pb_graph_node,
|
||||
int* num_inputs,
|
||||
int* num_outputs,
|
||||
int* num_clock_pins);
|
||||
|
||||
void map_clb_pins_to_pb_graph_pins();
|
||||
|
||||
int recommend_num_sim_clock_cycle();
|
||||
|
||||
void auto_select_num_sim_clock_cycle(t_spice* spice,
|
||||
|
@ -230,46 +167,13 @@ char* gen_str_spice_model_structure(enum e_spice_model_structure spice_model_str
|
|||
|
||||
boolean check_spice_model_structure_match_switch_inf(t_switch_inf target_switch_inf);
|
||||
|
||||
int find_pb_type_idle_mode_index(t_pb_type cur_pb_type);
|
||||
|
||||
int find_pb_type_physical_mode_index(t_pb_type cur_pb_type);
|
||||
|
||||
void mark_grid_type_pb_graph_node_pins_temp_net_num(int x, int y);
|
||||
|
||||
void assign_pb_graph_node_pin_temp_net_num_by_mode_index(t_pb_graph_pin* cur_pb_graph_pin,
|
||||
int mode_index);
|
||||
|
||||
void mark_pb_graph_node_input_pins_temp_net_num(t_pb_graph_node* cur_pb_graph_node,
|
||||
int mode_index);
|
||||
|
||||
void mark_pb_graph_node_clock_pins_temp_net_num(t_pb_graph_node* cur_pb_graph_node,
|
||||
int mode_index);
|
||||
|
||||
void mark_pb_graph_node_output_pins_temp_net_num(t_pb_graph_node* cur_pb_graph_node,
|
||||
int mode_index);
|
||||
|
||||
void rec_mark_pb_graph_node_temp_net_num(t_pb_graph_node* cur_pb_graph_node);
|
||||
|
||||
void load_one_pb_graph_pin_temp_net_num_from_pb(t_pb* cur_pb,
|
||||
t_pb_graph_pin* cur_pb_graph_pin);
|
||||
|
||||
void load_pb_graph_node_temp_net_num_from_pb(t_pb* cur_pb);
|
||||
|
||||
void rec_mark_one_pb_unused_pb_graph_node_temp_net_num(t_pb* cur_pb);
|
||||
|
||||
void update_pb_vpack_net_num_from_temp_net_num(t_pb* cur_pb,
|
||||
t_pb_graph_pin* cur_pb_graph_pin);
|
||||
|
||||
void update_pb_graph_node_temp_net_num_to_pb(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb* cur_pb);
|
||||
|
||||
void rec_load_unused_pb_graph_node_temp_net_num_to_pb(t_pb* cur_pb);
|
||||
|
||||
void mark_one_pb_parasitic_nets(t_pb* cur_pb);
|
||||
|
||||
void init_rr_nodes_vpack_net_num_changed(int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node);
|
||||
|
||||
void init_rr_nodes_is_parasitic_net(int LL_num_rr_nodes,
|
||||
t_rr_node* LL_rr_node);
|
||||
|
||||
boolean is_net_pi(t_net* cur_net);
|
||||
|
||||
int check_consistency_logical_block_net_num(t_logical_block* lgk_blk,
|
||||
|
@ -290,50 +194,6 @@ void find_drive_rr_nodes_switch_box(int switch_box_x,
|
|||
t_rr_node*** drive_rr_nodes,
|
||||
int* switch_index);
|
||||
|
||||
int count_num_sram_bits_one_spice_model(t_spice_model* cur_spice_model,
|
||||
int mux_size);
|
||||
|
||||
int count_num_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
int count_num_reserved_conf_bits_one_lut_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bits_one_mux_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
int count_num_reserved_conf_bits_one_rram_sram_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bits_one_spice_model(t_spice_model* cur_spice_model,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int mux_size);
|
||||
|
||||
int count_num_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_reserved_conf_bit_one_interc(t_interconnect* cur_interc,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int count_num_conf_bits_pb_type_mode_interc(t_mode* cur_pb_type_mode,
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
int rec_count_num_conf_bits_pb_type_default_mode(t_pb_type* cur_pb_type,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
int rec_count_num_conf_bits_pb_type_physical_mode(t_pb_type* cur_pb_type,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
int rec_count_num_conf_bits_pb(t_pb* cur_pb,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
void init_one_grid_num_conf_bits(int ix, int iy,
|
||||
t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
void init_grids_num_conf_bits(t_sram_orgz_info* cur_sram_orgz_info);
|
||||
|
||||
void zero_spice_models_cnt(int num_spice_models, t_spice_model* spice_model);
|
||||
|
||||
void zero_one_spice_model_routing_index_low_high(t_spice_model* cur_spice_model);
|
||||
|
@ -362,23 +222,6 @@ void update_spice_models_routing_index_low(int x, int y, t_rr_type chan_type,
|
|||
int num_spice_models,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void rec_count_num_iopads_pb_type_physical_mode(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_count_num_iopads_pb_type_default_mode(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_count_num_iopads_pb(t_pb* cur_pb);
|
||||
|
||||
void init_one_grid_num_iopads(int ix, int iy);
|
||||
|
||||
void init_grids_num_iopads();
|
||||
|
||||
void rec_count_num_mode_bits_pb_type_default_mode(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_count_num_mode_bits_pb(t_pb* cur_pb);
|
||||
|
||||
void init_one_grid_num_mode_bits(int ix, int iy);
|
||||
|
||||
void init_grids_num_mode_bits();
|
||||
|
||||
void check_sram_spice_model_ports(t_spice_model* cur_spice_model,
|
||||
boolean include_bl_wl);
|
||||
|
@ -401,31 +244,6 @@ add_conf_bit_info_to_llist(t_llist* head, int index,
|
|||
t_conf_bit* sram_val, t_conf_bit* bl_val, t_conf_bit* wl_val,
|
||||
t_spice_model* parent_spice_model);
|
||||
|
||||
void
|
||||
add_mux_scff_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_mux_sram_bits, int* mux_sram_bits,
|
||||
t_spice_model* mux_spice_model);
|
||||
|
||||
void
|
||||
add_mux_membank_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_mux_sram_bits, int* mux_sram_bits,
|
||||
t_spice_model* mux_spice_model);
|
||||
|
||||
void
|
||||
add_mux_conf_bits_to_llist(int mux_size,
|
||||
t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int num_mux_sram_bits, int* mux_sram_bits,
|
||||
t_spice_model* mux_spice_model);
|
||||
|
||||
void add_sram_membank_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info, int mem_index,
|
||||
int num_bls, int num_wls,
|
||||
int* bl_conf_bits, int* wl_conf_bits);
|
||||
|
||||
void
|
||||
add_sram_conf_bits_to_llist(t_sram_orgz_info* cur_sram_orgz_info, int mem_index,
|
||||
int num_sram_bits, int* sram_bits);
|
||||
|
||||
void find_bl_wl_ports_spice_model(t_spice_model* cur_spice_model,
|
||||
int* num_bl_ports, t_spice_model_port*** bl_ports,
|
||||
|
@ -435,51 +253,7 @@ void find_blb_wlb_ports_spice_model(t_spice_model* cur_spice_model,
|
|||
int* num_blb_ports, t_spice_model_port*** blb_ports,
|
||||
int* num_wlb_ports, t_spice_model_port*** wlb_ports);
|
||||
|
||||
int* decode_mode_bits(char* mode_bits, int* num_sram_bits);
|
||||
|
||||
/* Useful functions for LUT decoding */
|
||||
void stats_lut_spice_mux(t_llist** muxes_head,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
char* complete_truth_table_line(int lut_size,
|
||||
char* input_truth_table_line);
|
||||
|
||||
void configure_lut_sram_bits_per_line_rec(int** sram_bits,
|
||||
int lut_size,
|
||||
char* truth_table_line,
|
||||
int start_point);
|
||||
|
||||
int* generate_lut_sram_bits(int truth_table_len,
|
||||
char** truth_table,
|
||||
int lut_size,
|
||||
int default_sram_bit_value);
|
||||
|
||||
char** assign_lut_truth_table(t_logical_block* mapped_logical_block,
|
||||
int* truth_table_length);
|
||||
|
||||
void get_lut_logical_block_input_pin_vpack_net_num(t_logical_block* lut_logical_block,
|
||||
int* num_lut_pin, int** lut_pin_net);
|
||||
|
||||
void get_logical_block_output_vpack_net_num(t_logical_block* cur_logical_block,
|
||||
int* num_lb_output_ports, int** num_lb_output_pins,
|
||||
int*** lb_output_vpack_net_num);
|
||||
|
||||
int get_pb_graph_node_wired_lut_logical_block_index(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_rr_node* op_pb_rr_graph);
|
||||
|
||||
char** assign_post_routing_wired_lut_truth_table(t_logical_block* wired_lut_logical_block,
|
||||
int lut_size, int* lut_pin_vpack_net_num,
|
||||
int* truth_table_length);
|
||||
|
||||
char** assign_post_routing_lut_truth_table(t_logical_block* mapped_logical_block,
|
||||
int lut_size, int* lut_pin_vpack_net_num,
|
||||
int* truth_table_length);
|
||||
|
||||
int get_ff_output_init_val(t_logical_block* ff_logical_block);
|
||||
|
||||
int get_lut_output_init_val(t_logical_block* lut_logical_block);
|
||||
|
||||
int get_logical_block_output_init_val(t_logical_block* cur_logical_block);
|
||||
|
||||
/* Functions to manipulate structs of SRAM orgz */
|
||||
t_sram_orgz_info* alloc_one_sram_orgz_info();
|
||||
|
@ -534,9 +308,13 @@ void init_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
t_spice_model* cur_mem_model,
|
||||
int grid_nx, int grid_ny);
|
||||
|
||||
t_sram_orgz_info* snapshot_sram_orgz_info(t_sram_orgz_info* src_sram_orgz_info);
|
||||
|
||||
t_sram_orgz_info* diff_sram_orgz_info(t_sram_orgz_info* des_sram_orgz_info,
|
||||
t_sram_orgz_info* base_sram_orgz_info);
|
||||
|
||||
void free_sram_orgz_info(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
enum e_sram_orgz cur_sram_orgz_type,
|
||||
int grid_nx, int grid_ny);
|
||||
enum e_sram_orgz cur_sram_orgz_type);
|
||||
|
||||
void update_sram_orgz_info_reserved_blwl(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
int updated_reserved_bl, int updated_reserved_wl);
|
||||
|
@ -555,6 +333,12 @@ void update_sram_orgz_info_num_blwl(t_sram_orgz_info* cur_sram_orgz_info,
|
|||
void get_sram_orgz_info_mem_model(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model** mem_model_ptr);
|
||||
|
||||
void update_sram_orgz_info_mem_model(t_sram_orgz_info* cur_sram_orgz_info,
|
||||
t_spice_model* cur_mem_model);
|
||||
|
||||
void copy_sram_orgz_info(t_sram_orgz_info* des_sram_orgz_info,
|
||||
t_sram_orgz_info* src_sram_orgz_info);
|
||||
|
||||
void init_reserved_syntax_char(t_reserved_syntax_char* cur_reserved_syntax_char,
|
||||
char cur_syntax_char, boolean cur_verilog_reserved, boolean cur_spice_reserved);
|
||||
|
||||
|
@ -562,48 +346,6 @@ void check_mem_model_blwl_inverted(t_spice_model* cur_mem_model,
|
|||
enum e_spice_model_port_type blwl_port_type,
|
||||
boolean* blwl_inverted);
|
||||
|
||||
void init_spice_mux_arch(t_spice_model* spice_model,
|
||||
t_spice_mux_arch* spice_mux_arch,
|
||||
int mux_size);
|
||||
|
||||
int find_spice_mux_arch_special_basis_size(t_spice_mux_arch spice_mux_arch);
|
||||
|
||||
t_llist* search_mux_linked_list(t_llist* mux_head,
|
||||
int mux_size,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void check_and_add_mux_to_linked_list(t_llist** muxes_head,
|
||||
int mux_size,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
void free_muxes_llist(t_llist* muxes_head);
|
||||
|
||||
void stats_spice_muxes_routing_arch(t_llist** muxes_head,
|
||||
int num_switch,
|
||||
t_switch_inf* switches,
|
||||
t_spice* spice,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
void stats_mux_spice_model_pb_type_rec(t_llist** muxes_head,
|
||||
t_pb_type* cur_pb_type);
|
||||
|
||||
void stats_mux_spice_model_pb_node_rec(t_llist** muxes_head,
|
||||
t_pb_graph_node* cur_pb_node);
|
||||
|
||||
t_llist* stats_spice_muxes(int num_switch,
|
||||
t_switch_inf* switches,
|
||||
t_spice* spice,
|
||||
t_det_routing_arch* routing_arch);
|
||||
|
||||
enum e_interconnect find_pb_graph_pin_in_edges_interc_type(t_pb_graph_pin pb_graph_pin);
|
||||
|
||||
t_spice_model* find_pb_graph_pin_in_edges_interc_spice_model(t_pb_graph_pin pb_graph_pin);
|
||||
|
||||
int find_path_id_between_pb_rr_nodes(t_rr_node* local_rr_graph,
|
||||
int src_node,
|
||||
int des_node);
|
||||
|
||||
t_pb* get_child_pb_for_phy_pb_graph_node(t_pb* cur_pb, int ipb, int jpb);
|
||||
|
||||
void config_spice_model_port_inv_spice_model(int num_spice_models,
|
||||
t_spice_model* spice_model);
|
||||
|
@ -611,15 +353,6 @@ void config_spice_model_port_inv_spice_model(int num_spice_models,
|
|||
void config_spice_models_sram_port_spice_model(int num_spice_model,
|
||||
t_spice_model* spice_models,
|
||||
t_spice_model* default_sram_spice_model);
|
||||
t_pb* get_lut_child_pb(t_pb* cur_lut_pb,
|
||||
int mode_index);
|
||||
|
||||
t_pb* get_hardlogic_child_pb(t_pb* cur_hardlogic_pb,
|
||||
int mode_index);
|
||||
|
||||
int get_grid_pin_height(int grid_x, int grid_y, int pin_index);
|
||||
|
||||
int get_grid_pin_side(int grid_x, int grid_y, int pin_index);
|
||||
|
||||
void determine_sb_port_coordinator(t_sb cur_sb_info, int side,
|
||||
int* port_x, int* port_y);
|
||||
|
@ -650,18 +383,29 @@ t_llist* add_one_subckt_file_name_to_llist(t_llist* cur_head,
|
|||
boolean check_subckt_file_exist_in_llist(t_llist* subckt_llist_head,
|
||||
char* subckt_file_name);
|
||||
|
||||
void get_mapped_lut_pb_input_pin_vpack_net_num(t_pb_graph_node* lut_pb_graph_node,
|
||||
t_rr_node* pb_rr_graph,
|
||||
int* num_lut_pin, int** lut_pin_net);
|
||||
boolean is_primitive_pb_type(t_pb_type* cur_pb_type);
|
||||
|
||||
void rec_stats_spice_model_global_ports(t_spice_model* cur_spice_model,
|
||||
boolean recursive,
|
||||
t_llist** spice_model_head);
|
||||
|
||||
boolean is_pb_used_for_wiring(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_type* cur_pb_type,
|
||||
t_rr_node* pb_rr_graph);
|
||||
int* snapshot_spice_model_counter(int num_spice_models,
|
||||
t_spice_model* spice_model);
|
||||
|
||||
boolean is_pb_wired_lut(t_pb_graph_node* cur_pb_graph_node,
|
||||
t_pb_type* cur_pb_type,
|
||||
t_rr_node* pb_rr_graph);
|
||||
void set_spice_model_counter(int num_spice_models,
|
||||
t_spice_model* spice_model,
|
||||
int* spice_model_counter);
|
||||
|
||||
void get_logical_block_output_vpack_net_num(INP t_logical_block* cur_logical_block,
|
||||
OUTP int* num_lb_output_ports, OUTP int** num_lb_output_pins,
|
||||
OUTP int*** lb_output_vpack_net_num);
|
||||
|
||||
int get_lut_logical_block_index_with_output_vpack_net_num(int target_vpack_net_num);
|
||||
|
||||
void get_fpga_x2p_global_op_clock_ports(t_llist* head,
|
||||
int* num_clock_ports,
|
||||
t_spice_model_port*** clock_port);
|
||||
|
||||
void get_fpga_x2p_global_all_clock_ports(t_llist* head,
|
||||
int* num_clock_ports,
|
||||
t_spice_model_port*** clock_port);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue