-
Notifications
You must be signed in to change notification settings - Fork 17
Python API
See Code Generation section for usage guidelines.
Sample of a basic interface spec in Python:
from cog_acctempl import *
dut = DUT("cycle_detection")
inps = [TypedRead("Node","inp",buf_size_in_cl = 2, max_burst_count = 1)]
outs = [TypedWrite("CycleExistInfo","out")]
dut.add_rds(inps)
dut.add_wrs(outs)
dut.add_ut( UserType("Node",[UnsignedLongLongField("next_offset"), UnsignedLongLongField("val")]) )
dut.add_ut( UserType("CycleExistInfo",[UnsignedIntField("info")]) )
DUT
is a class used to define a design. Below are its methods:
DUT(nm)
constructor that takes a name of the design. Generated files will have this name as prefix.
-
nm
- String - given name of the design
add_rd(v)
adds a memory read port to the design
-
v
- [TypedRead|SingleRead] - read port
add_wr(v)
adds a memory write port to the design
-
v
- TypedWrite - write port
add_rds(l)
adds a list of memory read ports to the design
-
l
- List of [TypedRead|SingleRead] - list of read ports
add_wrs(l)
adds a list of memory write ports to the design
-
l
- List of TypedWrite - list of write ports
add_ut(v)
adds a user type to the design
-
v
- UserType - user type
get_ut(ty)
returns a user type given a type name
-
ty
- String - type name
add_extra_config_field(v)
adds extra fields to the config struct in addition to automatically created used for memory ports
-
v
- [ArrayField|BitReducedField|UserTypeField|{Unsigned,Signed}{LongLong,Int,Short,Char}Field] - field
add_extra_config_fields(l)
adds a list of extra fields to the config struct in addition to automatically created fields used for memory ports
-
l
- List of [ArrayField|BitReducedField|UserTypeField|{Unsigned,Signed}{LongLong,Int,Short,Char}Field]
TypedRead defines a burst read port bundle and a corresponding AccIn load-unit(C++ reference guide). It can be used for both streaming and random accesses. The responses will arrive in the same order as requests were sent.
TypedRead (ty, nm, buf_size_in_cl = "128", max_burst_count = "1<<24", buf_size_in_burst_reqs = None)
-
ty
- String - payload type (one of User Interface Type) -
nm
- String - prefix of the bundle (actual port names will get special suffixes) -
buf_size_in_cl
- String - number of parallel outstanding cacheline-worth requests in flight supported (user type objects will be packed into cachelines for streaming requests and each user type request will initiate a cacheline-worth request for random requests) -
max_burst_count
- String - maximum number of requested per one request in user type (e.g. may be 1 for random accesses or very large value for streaming accesses) -
buf_size_in_burst_reqs
- String - maximum number of parallel user requests in flight (should be not assigned for random acceses, but can be 1 for streaming applications when you request a large chunk of data but only once)
SingleRead represents a random access read port and a corresponding AccIn load-unit (C++ reference guide). It should be used for random read requests only. The responses may come out of order. The unit may have better performance than the TypedRead
port for this memory access pattern.
SingleRead(ty, tag_ty, nm, buf_size = "128")
-
ty
- String - payload type (one of User Interface Type) -
tag_ty
- String - tag type that is the type of a tag that will be send along with each request and will arrive with a corresponding response. It is used to match a response to a request. -
nm
- String - prefix of the bundle (actual port names will get special suffixes) -
buf_size
- String - number of outstanding request in user types (usually large 64-128)
TypedWrite represents a streaming write port and a corresponding store-unit (C++ reference guide)
TypedWrite(ty, nm)
-
ty
- String - payload type (one of User Interface Type) -
nm
- String - prefix of the bundle (actual port names will get special suffixes)
usertypes
is an associative map and it captures information about user C-structs that are used as payloads for the memory interfaces. The key to the map is the alias name of a struct (often real struct name). The value is the UserType object.
UserType(ty, fields)
-
ty
- String - struct name -
fields
- List of [ArrayField|BitReducedField|UserTypeField|{Unsigned,Signed}{LongLong,Int,Short,Char}Field] - fields of the struct
ArrayField(ty, count)
Used to have a C array of elements in the struct
-
ty
- [UserTypeField|{Unsigned,Signed}{LongLong,Int,Short,Char}Field] - array element type -
count
- Int - size of the array
BitReducedField(ty, bitwidth)
Used to represent bit fields of C-structs (e.g. int data : 5)
-
ty
- [{Unsigned,Signed}{LongLong,Int,Short,Char}Field] - type -
bitwidth
- Int - bitwidth (must be less or equal than the parent type can hold)
UnsignedLongLongField(nm)
Represents 'unsigned long long' C type
-
nm
- String - name of the field of C type unsigned long long
SignedLongLongField(nm)
Represents 'long long' C type
-
nm
- String - name of the field of C type long long
UnsignedIntField(nm)
Represents 'unsigned int' C type
-
nm
- String - name of the field of C type unsigned int
SignedIntField(nm)
Represents 'int' C type
-
nm
- String - name of the field of C type int
UnsignedShortField(nm)
Represents 'unsigned short' C type
-
nm
- String - name of the field of C type unsigned short
SignedShortField(nm)
Represents 'short' C type
-
nm
- String - name of the field of C type short
UnsignedCharField(nm)
Represents 'unsigned char' C type
-
nm
- String - name of the field of C type unsigned char
SignedCharField(nm)
Represents 'char' C type
-
nm
- String - name of the field of C type char
UserTypeField(nm, ty)
Represents a user type. Can be used to create an array of structs or to include a struct in another struct
-
nm
- String - name of the field -
ty
- String - name of the struct
Sample of more advanced interface specs in Python:
...
dut.module.add_cthreads( [CThread("inp_fetcher",writes_to_done=True),
CThread("inp_addr_gen"),
CThread("out_addr_gen")])
dut.get_cthread( "inp_fetcher").add_ports( [RdRespPort("inp"),
WrDataPort("out")])
dut.get_cthread( "inp_addr_gen").add_ports( [RdReqPort("inp")])
dut.get_cthread( "out_addr_gen").add_ports( [WrReqPort("out")])
if __name__ == "__main__":
dut.dump_dot( dut.nm + ".dot")
Here are more member variable and methods on the DUT
class:
add_cthread(v)
, add_cthreads(vs)
, get_cthreads(nm)
add a get cthreads
add_storage_fifo(v)
, add_storage_fifos(vs)
add a storage (internal) fifo to the module
dump_dot(fn)
writes a dot formatted file describing the interconnect structure of the modules and threads.
-
fn
- String - filename
This class defines an internal FIFO
StorageFIFO(ty, capacity, nm)
-
capacity
- Int - number of storage locations -
nm
- String - name of the storage fifo
Here are several classes for expressing ports. Only the constructor is needed.
Port( channel)
is the superclass of the following six. For all, channel
is a String
refering to the name of the channel
RdReqPort( channel)
the request port of a read (input) channel
RdRespPort( channel)
the response port of a read (input) channel
WrReqPort( channel)
the request port of a write (output) channel
WrDataPort( channel)
the data port of a write (output) channel
EnqueuePort( channel)
the enqueue (put) side of a storage fifo
DequeuePort( channel)
the dequeue (get) side of a storage fifo
The channel interconnection structure is specified using this classs.
CThread( nm, ports=None, writes_to_done=False)
-
nm
- String - naming the thread -
ports
is a list of Port objects used in this thread -
writes_to_done
- Bool - specifies whether this thread is (uniquely) responsible for signaling completion
Instead of assigning the ports in the constructor, you can alternatively use the methods add_port( p)
and add_ports( ps)
to attach ports to threads where p
is a single Port object and ps
is a list of Port objects.
We can also group the threads into internal modules (currently one-level) to allow easier experimentation with backend-flows.
To the DUT
class we have
add_module(v)
, add_modules(vs)
, get_module(nm)
add and get modules
The class Module
contains these member methods:
add_cthread(v)
, add_cthreads(vs)
, get_cthreads(nm)
add and get cthreads
add_storage_fifo(v)
, add_storage_fifos(vs)
add a storage (internal) fifo to the module
The follow specification produces the hierarchy shown in the diagram.
...
dut.add_modules( [Module("frontend")])
dut.get_module("frontend").add_cthreads( [CThread("inp_fetcher",writes_to_done=True),
CThread("inp_addr_gen")])
dut.module.add_cthreads( [CThread("out_addr_gen")])
dut.get_cthread( "inp_fetcher").add_ports( [RdRespPort("inp"),
WrDataPort("out")])
dut.get_cthread( "inp_addr_gen").add_ports( [RdReqPort("inp")])
dut.get_cthread( "out_addr_gen").add_ports( [WrReqPort("out")])
...
The two threads inp_addr_gen
and inp_fetcher
were encapsulated in the internal module named frontend
. All necessary SystemC boilerplate is generated automatically.