1 |
4 |
dargor |
#!/usr/bin/env python
|
2 |
|
|
# -*- coding: utf-8 -*-
|
3 |
|
|
|
4 |
|
|
#
|
5 |
|
|
# Basic NoC Code generation model
|
6 |
|
|
# * VHDL code support
|
7 |
|
|
#
|
8 |
|
|
# Author: Oscar Diaz
|
9 |
|
|
# Version: 0.2
|
10 |
|
|
# Date: 14-03-2011
|
11 |
|
|
|
12 |
|
|
#
|
13 |
|
|
# This code is free software; you can redistribute it and/or
|
14 |
|
|
# modify it under the terms of the GNU Lesser General Public
|
15 |
|
|
# License as published by the Free Software Foundation; either
|
16 |
|
|
# version 2.1 of the License, or (at your option) any later version.
|
17 |
|
|
#
|
18 |
|
|
# This code is distributed in the hope that it will be useful,
|
19 |
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20 |
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
21 |
|
|
# Lesser General Public License for more details.
|
22 |
|
|
#
|
23 |
|
|
# You should have received a copy of the GNU Lesser General Public
|
24 |
|
|
# License along with this library; if not, write to the
|
25 |
|
|
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
26 |
|
|
# Boston, MA 02111-1307 USA
|
27 |
|
|
#
|
28 |
|
|
|
29 |
|
|
#
|
30 |
|
|
# Changelog:
|
31 |
|
|
#
|
32 |
|
|
# 14-03-2011 : (OD) initial release
|
33 |
|
|
#
|
34 |
|
|
|
35 |
|
|
"""
|
36 |
|
|
* Basic NoC VHDL code generation model
|
37 |
|
|
"""
|
38 |
|
|
|
39 |
|
|
from nocmodel import *
|
40 |
|
|
from nocmodel.noc_codegen_base import *
|
41 |
|
|
from nocmodel.noc_codegen_vhdl import *
|
42 |
|
|
from intercon_model import *
|
43 |
|
|
|
44 |
|
|
from myhdl import intbv
|
45 |
|
|
|
46 |
|
|
class basic_noc_arch_vhdl(noc_codegen_ext):
|
47 |
|
|
"""
|
48 |
|
|
Code generation extension for NoC objects in VHDL.
|
49 |
|
|
|
50 |
|
|
This extension object generates the architecture needed to connect all
|
51 |
|
|
objects into a top VHDL file.
|
52 |
|
|
"""
|
53 |
|
|
def __init__(self, codegen_ref):
|
54 |
|
|
noc_codegen_ext.__init__(self, codegen_ref)
|
55 |
|
|
self.noc_ref = codegen_ref.nocobject_ref
|
56 |
|
|
if not isinstance(self.noc_ref, noc):
|
57 |
|
|
raise TypeError("Argument must be a 'noc_codegen_base' instance defined for a NoC object.")
|
58 |
|
|
|
59 |
|
|
codegen_ref.modulename = self.noc_ref.name
|
60 |
|
|
|
61 |
|
|
# NoC model: must generate all needed components and join them together
|
62 |
|
|
# in this top module.
|
63 |
|
|
|
64 |
|
|
# 1. convert some attributes to generics
|
65 |
|
|
codegen_ref.add_generic("name", self.noc_ref.name, "NoC Name")
|
66 |
|
|
|
67 |
|
|
# 2. define a basic port signals:
|
68 |
|
|
codegen_ref.add_external_signal("rst_i", "in", intbv(0)[1:], "System reset in")
|
69 |
|
|
codegen_ref.add_external_signal("clk_i", "in", intbv(0)[1:], "System clock in")
|
70 |
|
|
|
71 |
|
|
# 2. keep a list of needed components
|
72 |
|
|
hash_list = {}
|
73 |
|
|
|
74 |
|
|
# 2. search for defined external_ports in codegen objects
|
75 |
|
|
for obj in self.noc_ref.all_list(True):
|
76 |
|
|
for sig in obj.codegen.external_signals:
|
77 |
|
|
# make a copy of the signal dict, adding a reference to the
|
78 |
|
|
# nocobject which belongs
|
79 |
|
|
csig = sig.copy()
|
80 |
|
|
csig["back_ref"] = obj
|
81 |
|
|
codegen_ref.external_signals.append(csig)
|
82 |
|
|
|
83 |
|
|
# 3. Build implementation string
|
84 |
|
|
codegen_ref.implementation += "-- Implementation for '%s' name '%s' generated by '%s'\n" % (repr(self.noc_ref), self.noc_ref.name, repr(self))
|
85 |
|
|
# 3.1 add components
|
86 |
|
|
# TODO: check the components name
|
87 |
|
|
for obj in self.noc_ref.all_list():
|
88 |
|
|
# add only for routers and ipcores (WARNING)
|
89 |
|
|
if isinstance(obj, (router, ipcore)):
|
90 |
|
|
if obj.codegen.interface_hash == "":
|
91 |
|
|
# update hash
|
92 |
|
|
obj.codegen.model_hash()
|
93 |
|
|
# check if the component is already declared
|
94 |
|
|
if hash(obj.codegen.interface_hash) in hash_list:
|
95 |
|
|
# already declared component
|
96 |
|
|
hash_list[hash(obj.codegen.interface_hash)]["instance_list"].append(obj)
|
97 |
|
|
else:
|
98 |
|
|
# new component
|
99 |
|
|
codegen_ref.implementation += "\n-- Component for '%s' name '%s'\n" % (repr(obj), obj.name)
|
100 |
|
|
codegen_ref.implementation += obj.codegen.generate_component()
|
101 |
|
|
hash_list[hash(obj.codegen.interface_hash)] = {
|
102 |
|
|
"str_hash": obj.codegen.interface_hash,
|
103 |
|
|
"component_name": obj.codegen.modulename,
|
104 |
|
|
"instance_list": [obj]
|
105 |
|
|
}
|
106 |
|
|
|
107 |
|
|
# 3.2 intermediate signals
|
108 |
|
|
codegen_ref.implementation += "\n-- Intermediate signals\n\n"
|
109 |
|
|
# signals here has the format: "sig_<obj.name>_<signal_name>"
|
110 |
|
|
for obj in self.noc_ref.all_list():
|
111 |
|
|
# add only for routers and ipcores (WARNING)
|
112 |
|
|
if isinstance(obj, (router, ipcore)):
|
113 |
|
|
for s in obj.codegen.generate_port_declaration(None, True):
|
114 |
|
|
if s[0:2] != "--":
|
115 |
|
|
# note that port declaration will put "in" or "out". Filter it
|
116 |
|
|
sf = s.replace(": in", ":").replace(": out", ":")
|
117 |
|
|
codegen_ref.implementation += "signal sig_%s_%s;\n" % (obj.name, sf)
|
118 |
|
|
else:
|
119 |
|
|
codegen_ref.implementation += "-- Object %s : %s\n" % (obj.name, s[2:])
|
120 |
|
|
|
121 |
|
|
codegen_ref.implementation += "begin\n"
|
122 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- component instantiation\n\n")
|
123 |
|
|
|
124 |
|
|
# 3.3 instances and port mapping
|
125 |
|
|
# hash_list has the declared components and its related objects
|
126 |
|
|
for hcomp in hash_list.itervalues():
|
127 |
|
|
for obj in hcomp["instance_list"]:
|
128 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Instance for '%s' name '%s'\n" % (repr(obj), obj.name))
|
129 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("i_%s : %s" % (obj.name, hcomp["component_name"]))
|
130 |
|
|
# generic map
|
131 |
|
|
if len(obj.codegen.generics) > 0:
|
132 |
|
|
codegen_ref.implementation += " generic map (\n"
|
133 |
|
|
strl = []
|
134 |
|
|
for g in obj.codegen.generics:
|
135 |
|
|
strl.append("%s => %s" % (g["name"], convert_value(g["default_value"], g["type"])))
|
136 |
|
|
codegen_ref.implementation += ",\n".join(codegen_ref.add_tab(strl, 2))
|
137 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("\n)")
|
138 |
|
|
# port map
|
139 |
|
|
if (len(obj.codegen.ports) + len(obj.codegen.external_signals)) > 0:
|
140 |
|
|
codegen_ref.implementation += " port map (\n"
|
141 |
|
|
strl = []
|
142 |
|
|
for p in obj.codegen.ports:
|
143 |
|
|
# search for each signal in a port
|
144 |
|
|
for sig in p["signal_list"]:
|
145 |
|
|
# format: <portname>_<signame> => sig_<obj.name>_<portname>_<signal_name>
|
146 |
|
|
strl.append("%s_%s => sig_%s_%s_%s" % (p["name"], sig["name"], obj.name, p["name"], sig["name"]))
|
147 |
|
|
# and then in external_signals
|
148 |
|
|
for sig in obj.codegen.external_signals:
|
149 |
|
|
# format: <signame> => <obj.name>_<signal_name>
|
150 |
|
|
strl.append("%s => %s_%s" % (sig["name"], obj.name, sig["name"]))
|
151 |
|
|
codegen_ref.implementation += ",\n".join(codegen_ref.add_tab(strl, 2))
|
152 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("\n)")
|
153 |
|
|
codegen_ref.implementation += ";\n\n"
|
154 |
|
|
|
155 |
|
|
# 3.4 signal connections
|
156 |
|
|
# connect routers first
|
157 |
|
|
for obj in self.noc_ref.router_list():
|
158 |
|
|
# go through all ports and check its use
|
159 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Signal mapping for '%s' name '%s'\n" % (repr(obj), obj.name))
|
160 |
|
|
for p in obj.codegen.ports:
|
161 |
|
|
if p["type"] == "dualwb":
|
162 |
|
|
if p["nocport"] is None:
|
163 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- port '%s' unused\n" % p["name"])
|
164 |
|
|
# Unused port. Go through all signals and put input
|
165 |
|
|
# values tied to 0
|
166 |
|
|
for sig in p["signal_list"]:
|
167 |
|
|
if sig["direction"] == "in":
|
168 |
|
|
# format: sig_<obj.name>_<portname>_<signal_name>
|
169 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("sig_%s_%s_%s <= %s;\n" % (obj.name, p["name"], sig["name"], convert_value(sig["default_value"], sig["type"])))
|
170 |
|
|
else:
|
171 |
|
|
# connected with a port. Assign only input signals.
|
172 |
|
|
peerobj = obj.ports[p["nocport"]]["peer"]
|
173 |
|
|
# search for peer object codegen ports
|
174 |
|
|
peerpname = None
|
175 |
|
|
for peerp in peerobj.codegen.ports:
|
176 |
|
|
if peerp["nocport"] is not None:
|
177 |
|
|
findobj = peerobj.ports[peerp["nocport"]]["peer"]
|
178 |
|
|
if findobj == obj:
|
179 |
|
|
peerpname = peerp["name"]
|
180 |
|
|
break
|
181 |
|
|
if peerpname is None:
|
182 |
|
|
raise ValueError("Connected object '%s'->'%s': port not found" % (obj.name, peerobj.name))
|
183 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- port '%s' connected to object '%s' port '%s'\n" % (p["name"], peerobj.name, peerpname))
|
184 |
|
|
for sig in p["signal_list"]:
|
185 |
|
|
if sig["direction"] == "in":
|
186 |
|
|
peersig = obj.ports[p["nocport"]]["channel"].ports[obj.address]["intercon"].get_complement_signal(sig["name"])
|
187 |
|
|
if peersig is not None:
|
188 |
|
|
# format: sig_<obj.name>_<portname>_<signal_name>
|
189 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("sig_%s_%s_%s <= sig_%s_%s_%s;\n" % (obj.name, p["name"], sig["name"], peerobj.name, peerpname, peersig))
|
190 |
|
|
else:
|
191 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Special signal sig_%s_%s_%s not assigned yet.\n" % (obj.name, p["name"], sig["name"]))
|
192 |
|
|
|
193 |
|
|
# then ipcores
|
194 |
|
|
for obj in self.noc_ref.ipcore_list():
|
195 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Signal mapping for '%s' name '%s'\n" % (repr(obj), obj.name))
|
196 |
|
|
# connect signals from and to ipcore
|
197 |
|
|
# get local and remote intercon
|
198 |
|
|
obj_icon = obj.ports[obj.get_address()]["channel"].ports[None]["intercon"]
|
199 |
|
|
dest_icon = obj.ports[obj.get_address()]["channel"].ports[obj.get_address()]["intercon"]
|
200 |
|
|
obj_port = obj.codegen.ports[0]
|
201 |
|
|
dest_port = None
|
202 |
|
|
for p in obj.router_ref.codegen.ports:
|
203 |
|
|
if p["type"] == dest_icon.intercon_type:
|
204 |
|
|
dest_port = p
|
205 |
|
|
if dest_port is None:
|
206 |
|
|
raise ValueError("Router object '%s': local port not found" % obj.router_ref.name)
|
207 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- port '%s' connected to object '%s' port '%s'\n" % (p["name"], obj.router_ref.name, dest_port["name"]))
|
208 |
|
|
# first ipcore <= router
|
209 |
|
|
for sig in obj_port["signal_list"]:
|
210 |
|
|
if sig["direction"] == "in":
|
211 |
|
|
peersig = obj_icon.get_complement_signal(sig["name"])
|
212 |
|
|
if peersig is not None:
|
213 |
|
|
# format: sig_<obj.name>_<portname>_<signal_name>
|
214 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("sig_%s_%s_%s <= sig_%s_%s_%s;\n" % (obj.name, obj_port["name"], sig["name"], obj.router_ref.name, dest_port["name"], peersig))
|
215 |
|
|
else:
|
216 |
|
|
# special port (TODO!)
|
217 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Special signal sig_%s_%s_%s not assigned yet.\n" % (obj.name, obj_port["name"], sig["name"]))
|
218 |
|
|
# then router <= ipcore
|
219 |
|
|
for sig in dest_port["signal_list"]:
|
220 |
|
|
if sig["direction"] == "in":
|
221 |
|
|
peersig = dest_icon.get_complement_signal(sig["name"])
|
222 |
|
|
if peersig is not None:
|
223 |
|
|
# format: sig_<obj.name>_<portname>_<signal_name>
|
224 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("sig_%s_%s_%s <= sig_%s_%s_%s;\n" % (obj.router_ref.name, dest_port["name"], sig["name"], obj.name, obj_port["name"], peersig))
|
225 |
|
|
else:
|
226 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Special signal sig_%s_%s_%s not assigned yet.\n" % (obj.router_ref.name, dest_port["name"], sig["name"]))
|
227 |
|
|
|
228 |
|
|
codegen_ref.implementation += codegen_ref.add_tab("-- Implementation code for Noc --")
|
229 |
|
|
|