Update VPR7 X2P with new engine

This commit is contained in:
tangxifan 2019-04-26 12:23:47 -06:00
parent e2e4a9287d
commit 46d44fa42a
248 changed files with 48213 additions and 53950 deletions

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,2 +0,0 @@
This technology file was obtained here:
http://ptm.asu.edu/modelcard/LP/22nm_LP.pm

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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},

View File

@ -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,

View File

@ -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:

View File

@ -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 {

View File

@ -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;

View File

@ -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,

View File

@ -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*/

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;

3
vpr7_x2p/vpr/SRC/ctags_vpr_src.sh Normal file → Executable file
View File

@ -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]

View File

@ -1,5 +0,0 @@
void vpr_fpga_spice_tool_suites(t_vpr_setup vpr_setup,
t_arch Arch);

View File

@ -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

View File

@ -1,3 +0,0 @@
void vpr_print_spice_netlists(t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -1,4 +0,0 @@
void vpr_dump_syn_verilog(t_vpr_setup vpr_setup,
t_arch Arch,
char* circuit_name);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -0,0 +1,5 @@
void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
t_arch Arch);

View File

@ -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

View File

@ -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) ;

View File

@ -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/";

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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