increase chip size by 100, make chipSize closer to ring
[soclayout.git] / experiments9 / doDesign.py
1 from __future__ import print_function
2
3 import os
4 import json
5 from pprint import pprint
6 import sys
7 import traceback
8 import CRL
9 import helpers
10 from helpers.io import ErrorMessage
11 from helpers.io import WarningMessage
12 from helpers import trace
13 from helpers import l, u, n
14 import plugins
15 from Hurricane import DbU
16 if True: # change this to False to get errors to "go away" so that
17 # print / debug statements in generation of spec can be seen
18 # without the hard dependence of having to run via "cgt"
19 from plugins.alpha.block.configuration import IoPin
20 from plugins.alpha.block.block import Block
21 from plugins.alpha.block.configuration import GaugeConf
22 from plugins.alpha.core2chip.niolib import CoreToChip
23 from plugins.alpha.chip.configuration import ChipConf
24 from plugins.alpha.chip.chip import Chip
25
26
27 af = CRL.AllianceFramework.get()
28
29 # converts unicode strings to utf-8 because coriolis2 python code is expecting
30 # str not unicode
31 def _byteify(data, ignore_dicts = False):
32 # if this is a unicode string, return its string representation
33 if isinstance(data, unicode):
34 return data.encode('utf-8')
35 # if this is a list of values, return list of byteified values
36 if isinstance(data, list):
37 return [ _byteify(item, ignore_dicts=True) for item in data ]
38 # if this is a dictionary, return dictionary of byteified keys and values
39 # but only if we haven't already byteified it
40 if isinstance(data, dict) and not ignore_dicts:
41 return dict((_byteify(key, ignore_dicts=True),
42 _byteify(value, ignore_dicts=True))
43 for key, value in data.iteritems())
44 # if it's anything else, return it in its original form
45 return data
46
47 # load JSON-formatted pad info from pinmux
48 pth = os.path.abspath(__file__)
49 pth = os.path.split(pth)[0]
50 print ("path", pth)
51 with open("%s/ls180/litex_pinpads.json" % pth) as f:
52 txt = f.read()
53 chip = json.loads(txt, object_hook=_byteify)
54 chip = _byteify(chip, ignore_dicts=True)
55 print (chip)
56
57 chip.update({ 'pads.ioPadGauge' : 'niolib',
58 # core option (big, time-consuming)
59 #'core.size' : (l(28000), l(28000)),
60 #'chip.size' : (l(30200), l(30200)),
61 # no-core option (test_issuer but no actual core)
62 'core.size' : (l(13000), l(13000)),
63 'chip.size' : (l(14400), l(14400)),
64 'pads.useCoreSize': True,
65 'chip.clockTree' : True,
66 })
67
68 # this function is the equivalent of statically-declared io pad specs.
69 # it is not ok to have io declared manually, duplicated in (literally) 5
70 # different places, too many mistakes can be made and changes are a
71 # nightmare.
72 #
73 # therefore the pinmux code takes responsibility for declaring the pinouts,
74 # generates a JSON file which is read (above) and *creates* the list from
75 # that auto-generated file. the core, litex peripheral code, *and* the C4M
76 # JTAG Boundary Scan code do *EXACTLY* the same thing and in this way they
77 # all "match".
78 #
79 # here we do some weirdness to convert from the ioring.py pads list format over
80 # to the new niolib format.
81
82 def generate_spec():
83 # convert old ioring format to ioPadsSpec
84 ioPadsSpec = []
85 sd = {'pads.east': IoPin.EAST,
86 'pads.west': IoPin.WEST,
87 'pads.south': IoPin.SOUTH,
88 'pads.north': IoPin.NORTH,
89 }
90 # create lookup dict for resolving pads.instances "side" (NSEW)
91 sides = {}
92 for side in ['pads.east', 'pads.west', 'pads.south', 'pads.north']:
93 io_pin_spec = sd[side]
94 #if side not in sides:
95 # sides[side] = {}
96 for pinname in chip[side]:
97 sides[pinname] = io_pin_spec
98
99 # now go through pads.instances
100 pprint (sides)
101 for pad in chip['pads.instances']:
102 padname = pad[0]
103 padside = sides[padname]
104 print ("padside", padname, padside)
105
106 # format here is ['padname', 'to core', 'from core', 'direction']
107 # where direction is "+" for out, "-" for in, "*" for bi-directionaly
108 if len(pad) == 4:
109 print("4-long io", pad)
110 padspec = [padside, None, padname, pad[1], pad[2]]
111
112 # format here is:
113 # ['padname', 'something', 'to core', 'from core', 'en', 'direction']
114 elif len(pad) == 6:
115 print("6-long io", pad)
116 padspec = [padside, None, padname] + pad[1:5]
117
118 # format here is power/gnd (io)vss/vdd
119 elif len(pad) == 2:
120 print("2-long io", pad)
121 padspec = [padside, None] + pad
122 else:
123 print("? long io", pad)
124 assert False
125 print ("padspec", padspec)
126 ioPadsSpec.append(tuple(padspec))
127
128 return ioPadsSpec
129
130 ioPadsSpec = generate_spec()
131
132
133 def scriptMain (**kw):
134 """The mandatory function to be called by Coriolis CGT/Unicorn."""
135 global af
136 rvalue = True
137 sz = 25100 # core size
138 try:
139 helpers.setTraceLevel(550)
140 usePadsPosition = True
141 buildChip = True
142 cell, editor = plugins.kwParseMain(**kw)
143 cell = af.getCell('ls180', CRL.Catalog.State.Logical)
144 if cell is None:
145 print(ErrorMessage(2, 'doDesign.scriptMain(): Unable to load '
146 'cell "{}".'.format('ls180')))
147 sys.exit(1)
148 if editor: editor.setCell(cell)
149 ls180Conf = ChipConf(cell, ioPads=ioPadsSpec)
150 ls180Conf.cfg.etesian.bloat = 'nsxlib'
151 ls180Conf.cfg.etesian.uniformDensity = True
152 ls180Conf.cfg.etesian.aspectRatio = 1.0
153 ls180Conf.cfg.etesian.spaceMargin = 0.05
154 ls180Conf.cfg.block.spareSide = l(700)
155 ls180Conf.cfg.chip.padCoreSide = 'North'
156 ls180Conf.editor = editor
157 ls180Conf.useSpares = True
158 ls180Conf.useClockTree = True
159 ls180Conf.bColumns = 2
160 ls180Conf.bRows = 2
161 ls180Conf.chipConf.name = 'chip'
162 ls180Conf.chipConf.ioPadGauge = 'niolib'
163 ls180Conf.coreSize = (l(sz), l(sz))
164 ls180Conf.chipSize = (l(sz+3430), l(sz+3430))
165 ls180ToChip = CoreToChip(ls180Conf)
166 ls180ToChip.buildChip()
167 chipBuilder = Chip(ls180Conf)
168 rvalue = chipBuilder.doPnR()
169 chipBuilder.save()
170 except Exception, e:
171 helpers.io.catch(e)
172 rvalue = False
173 sys.stdout.flush()
174 sys.stderr.flush()
175 return rvalue