1 |
2 |
dargor |
#!/usr/bin/env python
|
2 |
|
|
# -*- coding: utf-8 -*-
|
3 |
|
|
|
4 |
|
|
#
|
5 |
|
|
# Basic IPcore model
|
6 |
4 |
dargor |
# * TBM model
|
7 |
|
|
# * Code generation model
|
8 |
2 |
dargor |
#
|
9 |
|
|
# Author: Oscar Diaz
|
10 |
4 |
dargor |
# Version: 0.2
|
11 |
|
|
# Date: 14-03-2011
|
12 |
2 |
dargor |
|
13 |
|
|
#
|
14 |
|
|
# This code is free software; you can redistribute it and/or
|
15 |
|
|
# modify it under the terms of the GNU Lesser General Public
|
16 |
|
|
# License as published by the Free Software Foundation; either
|
17 |
|
|
# version 2.1 of the License, or (at your option) any later version.
|
18 |
|
|
#
|
19 |
|
|
# This code is distributed in the hope that it will be useful,
|
20 |
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
|
|
# Lesser General Public License for more details.
|
23 |
|
|
#
|
24 |
|
|
# You should have received a copy of the GNU Lesser General Public
|
25 |
|
|
# License along with this library; if not, write to the
|
26 |
|
|
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
27 |
|
|
# Boston, MA 02111-1307 USA
|
28 |
|
|
#
|
29 |
|
|
|
30 |
|
|
#
|
31 |
|
|
# Changelog:
|
32 |
|
|
#
|
33 |
|
|
# 03-03-2011 : (OD) initial release
|
34 |
4 |
dargor |
# 14-03-2011 : (OD) adding code generation model
|
35 |
2 |
dargor |
#
|
36 |
|
|
|
37 |
|
|
"""
|
38 |
4 |
dargor |
* Basic ipcore TBM model
|
39 |
|
|
* Ipcore code generation model
|
40 |
2 |
dargor |
"""
|
41 |
|
|
|
42 |
4 |
dargor |
from nocmodel.noc_tbm_base import *
|
43 |
|
|
from nocmodel.noc_codegen_base import *
|
44 |
|
|
from intercon_model import *
|
45 |
2 |
dargor |
|
46 |
|
|
# ---------------------------
|
47 |
4 |
dargor |
# Basic IPCore TBM model
|
48 |
2 |
dargor |
|
49 |
4 |
dargor |
class basic_ipcore_tbm(noc_tbm_base):
|
50 |
2 |
dargor |
"""
|
51 |
4 |
dargor |
TBM model of a NoC ipcore. Its based on sending and receiving packets
|
52 |
2 |
dargor |
to a custom-based MyHDL generators. This class does not define any
|
53 |
|
|
functionality.
|
54 |
|
|
|
55 |
|
|
Attributes:
|
56 |
|
|
* ipcore_ref: reference to ipcore base object
|
57 |
|
|
|
58 |
|
|
Notes:
|
59 |
|
|
* This model is completely behavioral.
|
60 |
|
|
* See code comments to better understanding.
|
61 |
|
|
"""
|
62 |
|
|
def __init__(self, ipcore_ref):
|
63 |
4 |
dargor |
noc_tbm_base.__init__(self)
|
64 |
2 |
dargor |
if isinstance(ipcore_ref, ipcore):
|
65 |
|
|
self.ipcore_ref = ipcore_ref
|
66 |
|
|
self.graph_ref = ipcore_ref.graph_ref
|
67 |
|
|
self.logname = "IPCore '%s'" % ipcore_ref.name
|
68 |
|
|
if ipcore_ref.name == "":
|
69 |
|
|
self.logname = "IPCore '%s'" % ipcore_ref.router_ref.name
|
70 |
|
|
else:
|
71 |
|
|
raise TypeError("This class needs a ipcore object as constructor argument.")
|
72 |
|
|
|
73 |
|
|
self.debug("constructor")
|
74 |
|
|
# generic parameters
|
75 |
4 |
dargor |
self.retrytimes = 3
|
76 |
|
|
self.retrydelay = 2
|
77 |
2 |
dargor |
|
78 |
|
|
# one-port support: get a reference to the related channel
|
79 |
|
|
self.localch = self.ipcore_ref.channel_ref
|
80 |
|
|
|
81 |
|
|
# get protocol reference
|
82 |
|
|
self.protocol_ref = self.ipcore_ref.get_protocol_ref()
|
83 |
|
|
|
84 |
|
|
# bidirectional port: the sender part will write data to the signal
|
85 |
|
|
# outgoing_packet. This class provides a generator thar call send()
|
86 |
|
|
# method when there is new data.
|
87 |
|
|
# for receiving data, recv() method will write
|
88 |
|
|
# to the signal incoming_packet, and the ipcore must provide a generator
|
89 |
|
|
# sensible to that signal. Use the method register_generator()
|
90 |
|
|
self.incoming_packet = myhdl.Signal(packet())
|
91 |
|
|
self.outgoing_packet = myhdl.Signal(packet())
|
92 |
|
|
|
93 |
|
|
@myhdl.instance
|
94 |
|
|
def outgoing_process():
|
95 |
|
|
while True:
|
96 |
|
|
yield self.outgoing_packet
|
97 |
4 |
dargor |
# multiple tries
|
98 |
|
|
for i in range(self.retrytimes):
|
99 |
|
|
retval = self.send(self.ipcore_ref, self.localch, self.outgoing_packet.val)
|
100 |
|
|
if retval == noc_tbm_errcodes.no_error:
|
101 |
|
|
break;
|
102 |
|
|
yield myhdl.delay(self.retrydelay)
|
103 |
2 |
dargor |
|
104 |
|
|
self.generators = [outgoing_process]
|
105 |
|
|
self.debugstate()
|
106 |
|
|
|
107 |
|
|
def register_generator(self, genfunction, **kwargs):
|
108 |
|
|
"""
|
109 |
|
|
Register a new generator for this ipcore.
|
110 |
|
|
|
111 |
|
|
Arguments:
|
112 |
|
|
* genfunction: function that returns a MyHDL generator
|
113 |
|
|
* kwargs: optional keyed arguments to pass to genfunction call
|
114 |
|
|
|
115 |
|
|
Notes:
|
116 |
|
|
* This method requires that genfunction has the following prototype:
|
117 |
4 |
dargor |
* my_function(din, dout, tbm_ref, <other_arguments>)
|
118 |
2 |
dargor |
* din is a MyHDL Signal of type packet, and is the input signal
|
119 |
|
|
to the ipcore. Use this signal to react to input events and
|
120 |
|
|
receive input packets.
|
121 |
|
|
* dout is a MyHDL Signal of type packet, and is the output
|
122 |
|
|
signal to the ipcore. Use this signal to send out packets to
|
123 |
|
|
local channel (and then insert into the NoC).
|
124 |
4 |
dargor |
* tbm_ref is a reference to an object with logging methods.
|
125 |
|
|
(e.g. tbm_ref.info("message") ).
|
126 |
2 |
dargor |
* <other_arguments> may be defined, this method use kwargs
|
127 |
|
|
argument to pass them.
|
128 |
|
|
"""
|
129 |
4 |
dargor |
makegen = genfunction(din=self.incoming_packet, dout=self.outgoing_packet, tbm_ref=self, **kwargs)
|
130 |
2 |
dargor |
self.debug("register_generator( %s ) generator is %s args %s" % (repr(genfunction), repr(makegen), repr(kwargs)))
|
131 |
|
|
self.generators.append(makegen)
|
132 |
|
|
|
133 |
|
|
# Transaction - related methods
|
134 |
|
|
def send(self, src, dest, packet, addattrs=None):
|
135 |
|
|
"""
|
136 |
|
|
Assumptions:
|
137 |
|
|
* Safely ignore src and dest arguments, because this method
|
138 |
|
|
is called only by this object generators, therefore it always send
|
139 |
|
|
packets to the ipcore related channel.
|
140 |
|
|
* In theory src should be self.ipcore_ref, and dest should be
|
141 |
|
|
self.localch . This may be checked for errors.
|
142 |
|
|
"""
|
143 |
|
|
self.debug("-> send( %s , %s , %s , %s )" % (repr(src), repr(dest), repr(packet), repr(addattrs)))
|
144 |
|
|
|
145 |
|
|
# call recv on the local channel object
|
146 |
4 |
dargor |
retval = self.localch.tbm.recv(self.ipcore_ref, self.localch, packet, addattrs)
|
147 |
2 |
dargor |
|
148 |
|
|
# something to do with the retval? Only report it.
|
149 |
|
|
self.debug("-> send returns code '%s'" % repr(retval))
|
150 |
|
|
return retval
|
151 |
|
|
|
152 |
|
|
def recv(self, src, dest, packet, addattrs=None):
|
153 |
|
|
"""
|
154 |
|
|
Assumptions:
|
155 |
|
|
* Safely ignore src and dest arguments, because this method
|
156 |
|
|
is called only by local channel object.
|
157 |
|
|
* In theory src should be self.localch, and dest should be
|
158 |
|
|
self.ipcore_ref . This may be checked for errors.
|
159 |
|
|
"""
|
160 |
|
|
self.debug("-> recv( %s , %s , %s , %s )" % (repr(src), repr(dest), repr(packet), repr(addattrs)))
|
161 |
|
|
|
162 |
|
|
# update signal
|
163 |
|
|
self.incoming_packet.next = packet
|
164 |
|
|
|
165 |
4 |
dargor |
self.debug("-> recv returns 'noc_tbm_errcodes.no_error'")
|
166 |
|
|
return noc_tbm_errcodes.no_error
|
167 |
|
|
|
168 |
|
|
# ---------------------------
|
169 |
|
|
# Ipcore code generation model
|
170 |
|
|
|
171 |
|
|
class basic_ipcore_codegen(noc_codegen_ext):
|
172 |
|
|
"""
|
173 |
|
|
Code generation extension for Ipcore objects.
|
174 |
|
|
"""
|
175 |
|
|
|
176 |
|
|
def __init__(self, codegen_ref):
|
177 |
|
|
noc_codegen_ext.__init__(self, codegen_ref)
|
178 |
|
|
#self.codegen_ref = codegen_ref
|
179 |
|
|
self.ipcore_ref = codegen_ref.nocobject_ref
|
180 |
|
|
if not isinstance(self.ipcore_ref, ipcore):
|
181 |
|
|
raise TypeError("Argument must be a 'noc_codegen_base' instance defined for a ipcore object.")
|
182 |
|
|
|
183 |
|
|
# ipcore model: This basic ipcore has some parameters put in the
|
184 |
|
|
# generics list, and only one port of type masterwb.
|
185 |
|
|
|
186 |
|
|
codegen_ref.modulename = "basic_ipcore"
|
187 |
|
|
|
188 |
|
|
# 1. convert some attributes to generics
|
189 |
|
|
codegen_ref.add_generic("name", self.ipcore_ref.name, "Ipcore Name")
|
190 |
|
|
codegen_ref.add_generic("address", self.ipcore_ref.router_ref.address, "Ipcore router Address")
|
191 |
|
|
|
192 |
|
|
# 2. check intercon on ipcore port
|
193 |
|
|
|
194 |
|
|
ch = self.ipcore_ref.channel_ref
|
195 |
|
|
icon = ch.ports[None]["intercon"]
|
196 |
|
|
if not isinstance(icon, masterwb_intercon):
|
197 |
|
|
raise UserWarning("Port Local on ipcore '%s' does not use intercon 'masterwb_intercon'." % self.ipcore_ref.name)
|
198 |
|
|
|
199 |
|
|
# 2. convert ipcore port to codegen port
|
200 |
|
|
codegen_ref.add_port("PortLocal", None, "Port Local", type=icon.intercon_type)
|
201 |
|
|
|
202 |
|
|
for signame, sigval in icon.signals.iteritems():
|
203 |
|
|
stmp = get_new_signal(
|
204 |
|
|
name=signame,
|
205 |
|
|
direction=sigval["direction"],
|
206 |
|
|
default_value=intbv(0)[sigval["width"]:],
|
207 |
|
|
description=sigval["description"])
|
208 |
|
|
codegen_ref.add_port("PortLocal", stmp)
|
209 |
|
|
|
210 |
|
|
# 3. Calculate a Hash with generics and ports info.
|
211 |
|
|
# WARNING: You must recalculate the hash when you change the model!
|
212 |
|
|
codegen_ref.model_hash()
|
213 |
|
|
|
214 |
|
|
# 4. Implementation comment
|
215 |
|
|
codegen_ref.implementation += "-- Add here implementation code for Ipcore %s" % self.ipcore_ref.name
|
216 |
|
|
|
217 |
|
|
def add_external_signal(self, name, direction, value, description="", **kwargs):
|
218 |
|
|
"""
|
219 |
|
|
Wrapper to noc_codegen_base.add_external_signal method, to support hash
|
220 |
|
|
updating.
|
221 |
|
|
"""
|
222 |
|
|
retval = self.codegen_ref.add_external_signal(name, direction, value, description, **kwargs)
|
223 |
|
|
self.codegen_ref.model_hash()
|
224 |
|
|
return retval
|