10 from helpers
import trace
, l
, u
, n
11 from helpers
.io
import ErrorMessage
, WarningMessage
12 from helpers
.overlay
import UpdateSession
14 from Hurricane
import Breakpoint
, DataBase
, DbU
, Transformation
, Point
, Box
, \
16 from plugins
.alpha
.block
.matrix
import RegisterMatrix
17 from plugins
.alpha
.macro
.macro
import Macro
18 from plugins
.alpha
.block
.iospecs
import IoSpecs
19 from plugins
.alpha
.block
.block
import Block
20 from plugins
.alpha
.block
.configuration
import IoPin
, GaugeConf
21 from plugins
.alpha
.block
.spares
import Spares
22 from plugins
.alpha
.core2chip
.libresocio
import CoreToChip
23 from plugins
.alpha
.chip
.configuration
import ChipConf
24 from plugins
.alpha
.chip
.chip
import Chip
25 #from plugins.alpha.utils import rgetInstanceMatching
28 af
= CRL
.AllianceFramework
.get()
34 twoGrid
= DbU
.fromGrid( 2 )
41 def isiterable ( pyobj
):
42 if isinstance(pyobj
,collections
.Iterable
): return True
46 def doIoPowerCap ( flags
):
48 side
= flags
& IoPin
.SIDE_MASK
49 if flags
& IoPin
.A_BEGIN
:
50 ioPadPower
= [ (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
51 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
52 , (side
, None, 'ioground_{}'.format(powerCount
), 'vss' )
53 , (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
56 ioPadPower
= [ (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
57 , (side
, None, 'ioground_{}'.format(powerCount
), 'vss' )
58 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
59 , (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
65 def doIoPinVector ( ioSpec
, bits
):
67 if not isiterable(bits
): bits
= range(bits
)
69 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
70 , '(bits={})'.format(bits
)
76 , ioSpec
[2].format(bit
)
77 , ioSpec
[3].format(bit
)
78 , ioSpec
[4].format(bit
) ))
79 elif len(ioSpec
) == 6:
83 , ioSpec
[2].format(bit
)
84 , ioSpec
[3].format(bit
)
85 , ioSpec
[4].format(bit
)
86 , ioSpec
[5].format(bit
) ))
87 elif len(ioSpec
) == 7:
91 , ioSpec
[2].format(bit
)
92 , ioSpec
[3].format(bit
)
93 , ioSpec
[4].format(bit
)
94 , ioSpec
[5].format(bit
)
95 , ioSpec
[6].format(bit
) ))
97 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec
))
98 , '(ioSpec={})'.format(ioSpec
)
103 def rgetInstance ( cell
, path
):
105 Get the instance designated by path (recursively). The path argument can be
106 either a string of instance names separated by dots or directly a list of
109 if isinstance(path
,str):
110 path
= path
.split( '.' )
111 elif not isinstance(path
,list):
112 raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither a string or a list ({})"' \
114 instance
= cell
.getInstance( path
[0] )
116 raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \
117 .format(path
[0],cell
.getName()) )
120 return rgetInstance( instance
.getMasterCell(), path
[1:] )
123 def rsetAbutmentBox ( cell
, ab
):
124 for occurrence
in cell
.getNonTerminalNetlistInstanceOccurrences():
125 masterCell
= occurrence
.getEntity().getMasterCell()
126 masterCell
.setAbutmentBox( ab
)
129 def scriptMain (**kw
):
130 """The mandatory function to be called by Coriolis CGT/Unicorn."""
132 #helpers.setTraceLevel( 550 )
133 #Breakpoint.setStopLevel( 100 )
135 coreSizeX
= u(51*90.0)
136 coreSizeY
= u(56*90.0)
137 chipBorder
= u(2*214.0 + 8*13.0)
140 # this should work fine, tested on nsxlib
141 cwd
= os
.path
.split(os
.path
.abspath(__file__
))[0]
142 pinmuxFile
= '%s/non_generated/litex_pinpads.json' % cwd
143 # actual contents auto-generated and listed at:
144 # http://libre-soc.org/180nm_Oct2020/ls180/
145 ioSpecs
.loadFromPinmux( pinmuxFile
)
147 # XXX ioPadsSpec created but not used. saves time, saves errors. see
148 # wiki page for contents: http://libre-soc.org/180nm_Oct2020/ls180/
149 # if *not* using the auto-generated ioSpecs, ioPadsSpec should, really,
150 # be made exactly the same. which is more work.
152 # I/O pads, East side.
154 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_BEGIN
)
155 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' )
156 , (IoPin
.EAST
, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' )
157 , (IoPin
.EAST
, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' )
159 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_a_{}' , 'sdram_a({})' , 'sdram_a({})'), 13 )
160 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
161 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 )
162 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(0,2) )
163 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_END
)
164 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'sys_pll_testout_o', 'sys_pll_testout_o', 'sys_pll_testout_o' )
165 , (IoPin
.EAST|IoPin
.ANALOG
, None, 'sys_pll_vco_o' , 'sys_pll_vco_o' , 'sys_pll_vco_o' )
168 # I/O pads, North side.
169 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_BEGIN
)
170 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'jtag_tms' , 'jtag_tms' , 'jtag_tms' )
171 , (IoPin
.NORTH
, None, 'jtag_tdi' , 'jtag_tdi' , 'jtag_tdi' )
172 , (IoPin
.NORTH
, None, 'jtag_tdo' , 'jtag_tdo' , 'jtag_tdo' )
173 , (IoPin
.NORTH
, None, 'jtag_tck' , 'jtag_tck' , 'jtag_tck' )
175 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(2,19) )
176 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe({})', 'sdram_dq_o({})'), range(0,16) )
177 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 )
178 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'sys_clk' , 'sys_clk' , 'sys_clk' ) ]
179 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_END
)
181 # I/O pads, West side.
182 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_BEGIN
)
183 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'nc_{}', ' nc({})', 'nc({})'), range(19,36) )
184 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'eint_{}', 'eint_{}', 'eint_{}'), 3 )
185 ioPadsSpec
+= [ (IoPin
.WEST
, None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
186 , (IoPin
.WEST
, None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
187 , (IoPin
.WEST
, None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
188 , (IoPin
.WEST
, None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
190 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_END
)
192 # I/O pads, South side.
193 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_BEGIN
)
194 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,16) )
195 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i', 'i2c_sda_oe', 'i2c_sda_o' ) ]
196 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_scl' , 'i2c_scl' , 'i2c_scl' ) ]
197 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'uart_tx', 'uart_tx', 'uart_tx' )
198 , (IoPin
.SOUTH
, None, 'uart_rx', 'uart_rx', 'uart_rx' )
199 , (IoPin
.SOUTH
, None, 'sys_rst', 'sys_rst', 'sys_rst' )
201 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' )
202 , (IoPin
.SOUTH
, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' )
203 , (IoPin
.SOUTH
, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' )
205 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_END
)
208 cell
, editor
= plugins
.kwParseMain( **kw
)
209 cell
= af
.getCell( 'ls180', CRL
.Catalog
.State
.Logical
)
211 print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \
214 if editor
: editor
.setCell( cell
)
215 # use auto-generated (but from non_generated) io pads specs
216 # works fine with soclayout nsxlib, should work perfectly fine
218 ls180Conf
= ChipConf( cell
, ioPads
=ioSpecs
.ioPadsSpec
)
219 #ls180Conf = ChipConf( cell, ioPads=ioPadsSpec )
220 ls180Conf
.cfg
.etesian
.bloat
= 'Flexlib'
221 ls180Conf
.cfg
.etesian
.uniformDensity
= True
222 ls180Conf
.cfg
.etesian
.aspectRatio
= 1.0
223 ls180Conf
.cfg
.etesian
.spaceMargin
= 0.05
224 ls180Conf
.cfg
.anabatic
.searchHalo
= 3
225 ls180Conf
.cfg
.anabatic
.globalIterations
= 20
226 ls180Conf
.cfg
.anabatic
.topRoutingLayer
= 'METAL5'
227 ls180Conf
.cfg
.katana
.hTracksReservedLocal
= 11
228 ls180Conf
.cfg
.katana
.vTracksReservedLocal
= 8
229 ls180Conf
.cfg
.katana
.hTracksReservedMin
= 8
230 ls180Conf
.cfg
.katana
.vTracksReservedMin
= 6
231 ls180Conf
.cfg
.katana
.runRealignStage
= True
232 ls180Conf
.cfg
.katana
.trackFill
= 0
233 ls180Conf
.cfg
.block
.spareSide
= u(7*13)
234 ls180Conf
.cfg
.chip
.supplyRailWidth
= u(35)
235 ls180Conf
.cfg
.chip
.supplyRailPitch
= u(90)
236 ls180Conf
.editor
= editor
237 ls180Conf
.useSpares
= True
238 ls180Conf
.useClockTree
= True
239 ls180Conf
.useHFNS
= True
240 ls180Conf
.bColumns
= 2
242 ls180Conf
.chipConf
.name
= 'chip'
243 ls180Conf
.chipConf
.ioPadGauge
= 'LibreSOCIO'
244 ls180Conf
.coreSize
= (coreSizeX
, coreSizeY
)
245 ls180Conf
.chipSize
= (coreSizeX
+ chipBorder
+ u(5.0), coreSizeY
+ chipBorder
- u(0.04) )
246 ls180Conf
.chipLogos
= [ 'C4MLogo_norm'
247 , 'libresoc_logo_norm'
248 , 'sorbonne_logo_norm'
251 ls180Conf
.useHTree( 'core.pll_clk', Spares
.HEAVY_LEAF_LOAD
)
252 ls180Conf
.useHTree( 'jtag_tck_from_pad' )
254 tiPath
= 'test_issuer.ti.'
256 = [ ['test_issuer.ti.sram4k_0.spblock_512w64b8w', -2]
257 , ['test_issuer.ti.sram4k_1.spblock_512w64b8w', 2]
258 , ['test_issuer.ti.sram4k_2.spblock_512w64b8w', 2]
259 , ['test_issuer.ti.sram4k_3.spblock_512w64b8w', 2]
262 ls180ToChip
= CoreToChip( ls180Conf
)
263 ls180ToChip
.buildChip()
264 chipBuilder
= Chip( ls180Conf
)
265 chipBuilder
.doChipFloorplan()
267 with
UpdateSession():
268 sram
= DataBase
.getDB().getCell( 'spblock_512w64b8w' )
269 sramAb
= sram
.getAbutmentBox()
270 coreAb
= cell
.getAbutmentBox()
271 sliceHeight
= chipBuilder
.conf
.sliceHeight
272 sliceStep
= chipBuilder
.conf
.sliceStep
273 originX
= coreAb
.getXMin() + sramDatas
[0][1]*chipBuilder
.conf
.sliceStep
274 for i
in range(len(sramDatas
)):
275 chipBuilder
.placeMacro \
277 , Transformation( originX
278 , coreAb
.getYMax() - sramAb
.getHeight() - 2*sliceHeight
279 , Transformation
.Orientation
.ID
)
281 if i
+1 < len(sramDatas
):
282 originX
+= sramAb
.getWidth() + 2*sliceHeight
+ sramDatas
[i
+1][1]*sliceStep
283 pllTransf
= Transformation( coreAb
.getXMax() # -u(234.0)
284 , coreAb
.getYMax() - u(208.0)
285 , Transformation
.Orientation
.MX
)
286 print( 'pllTransf={}'.format(pllTransf
) )
287 chipBuilder
.placeMacro( 'test_issuer.wrappll.pll' , pllTransf
)
290 Breakpoint
.stop( 99, 'After core placement.' )
292 rvalue
= chipBuilder
.doPnR()
294 CRL
.Gds
.save( ls180Conf
.chip
)
295 except Exception as e
: