adjust chip/core size to try to fit ls180 core/pads
[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 if pad[-1] == '-':
111 en_sig = 'io_in'
112 if pad[-1] == '+':
113 en_sig = 'io_out'
114 padspec = [padside, None, padname, pad[1], pad[2], en_sig]
115
116 # format here is:
117 # ['padname', 'something', 'to core', 'from core', 'en', 'direction']
118 elif len(pad) == 6:
119 print("6-long io", pad)
120 padspec = [padside, None, padname] + pad[1:5]
121
122 # format here is power/gnd (io)vss/vdd
123 elif len(pad) == 2:
124 print("2-long io", pad)
125 padspec = [padside, None] + pad
126 else:
127 print("? long io", pad)
128 assert False
129 print ("padspec", padspec)
130 ioPadsSpec.append(tuple(padspec))
131
132 return ioPadsSpec
133
134 ioPadsSpec = generate_spec()
135
136
137 def scriptMain (**kw):
138 """The mandatory function to be called by Coriolis CGT/Unicorn."""
139 global af
140 rvalue = True
141 try:
142 helpers.setTraceLevel(550)
143 usePadsPosition = True
144 buildChip = True
145 cell, editor = plugins.kwParseMain(**kw)
146 cell = af.getCell('ls180', CRL.Catalog.State.Logical)
147 if cell is None:
148 print(ErrorMessage(2, 'doDesign.scriptMain(): Unable to load '
149 'cell "{}".'.format('ls180')))
150 sys.exit(1)
151 if editor: editor.setCell(cell)
152 ls180Conf = ChipConf(cell, ioPads=ioPadsSpec)
153 ls180Conf.cfg.etesian.bloat = 'nsxlib'
154 ls180Conf.cfg.etesian.uniformDensity = True
155 ls180Conf.cfg.etesian.aspectRatio = 1.0
156 ls180Conf.cfg.etesian.spaceMargin = 0.05
157 ls180Conf.cfg.block.spareSide = l(700)
158 ls180Conf.cfg.chip.padCoreSide = 'North'
159 ls180Conf.editor = editor
160 ls180Conf.useSpares = True
161 ls180Conf.useClockTree = True
162 ls180Conf.bColumns = 2
163 ls180Conf.bRows = 2
164 ls180Conf.chipConf.name = 'chip'
165 ls180Conf.chipConf.ioPadGauge = 'niolib'
166 ls180Conf.coreSize = (l(15000), l(15000))
167 ls180Conf.chipSize = (l(19000), l(19000))
168 ls180ToChip = CoreToChip(ls180Conf)
169 ls180ToChip.buildChip()
170 chipBuilder = Chip(ls180Conf)
171 rvalue = chipBuilder.doPnR()
172 chipBuilder.save()
173 except Exception, e:
174 helpers.io.catch(e)
175 rvalue = False
176 sys.stdout.flush()
177 sys.stderr.flush()
178 return rvalue