55 */
66
77#include < vta/driver.h>
8+ #include < thread>
89#include " ./pynq_driver.h"
910
1011
@@ -16,16 +17,16 @@ void VTAMemFree(void* buf) {
1617 cma_free (buf);
1718}
1819
19- uint32_t VTAGetMemPhysAddr (void * buf) {
20+ vta_phy_addr_t VTAGetMemPhysAddr (void * buf) {
2021 return cma_get_phy_addr (buf);
2122}
2223
23- void VTAFlushCache (void * buf, int size) {
24- xlnkFlushCache (buf, size);
24+ void VTAFlushCache (vta_phy_addr_t buf, int size) {
25+ xlnkFlushCache (reinterpret_cast < void *>( buf) , size);
2526}
2627
27- void VTAInvalidateCache (void * buf, int size) {
28- xlnkInvalidateCache (buf, size);
28+ void VTAInvalidateCache (vta_phy_addr_t buf, int size) {
29+ xlnkInvalidateCache (reinterpret_cast < void *>( buf) , size);
2930}
3031
3132void *VTAMapRegister (uint32_t addr, size_t length) {
@@ -57,33 +58,112 @@ uint32_t VTAReadMappedReg(void* base_addr, uint32_t offset) {
5758 return *((volatile uint32_t *) (reinterpret_cast <char *>(base_addr) + offset));
5859}
5960
61+ class VTADevice {
62+ public:
63+ VTADevice () {
64+ // VTA stage handles
65+ vta_fetch_handle_ = VTAMapRegister (VTA_FETCH_ADDR, VTA_RANGE);
66+ vta_load_handle_ = VTAMapRegister (VTA_LOAD_ADDR, VTA_RANGE);
67+ vta_compute_handle_ = VTAMapRegister (VTA_COMPUTE_ADDR, VTA_RANGE);
68+ vta_store_handle_ = VTAMapRegister (VTA_STORE_ADDR, VTA_RANGE);
69+ }
70+
71+ ~VTADevice () {
72+ // Close VTA stage handle
73+ VTAUnmapRegister (vta_fetch_handle_, VTA_RANGE);
74+ VTAUnmapRegister (vta_load_handle_, VTA_RANGE);
75+ VTAUnmapRegister (vta_compute_handle_, VTA_RANGE);
76+ VTAUnmapRegister (vta_store_handle_, VTA_RANGE);
77+ }
78+
79+ int Run (vta_phy_addr_t insn_phy_addr,
80+ uint32_t insn_count,
81+ uint32_t wait_cycles) {
82+ // NOTE: Register address map is derived from the auto-generated
83+ // driver files available under hardware/build/vivado/<design>/export/driver
84+ // FETCH @ 0x10 : Data signal of insn_count_V
85+ VTAWriteMappedReg (vta_fetch_handle_, 0x10 , insn_count);
86+ // FETCH @ 0x18 : Data signal of insns_V
87+ VTAWriteMappedReg (vta_fetch_handle_, 0x18 , insn_phy_addr);
88+ // LOAD @ 0x10 : Data signal of inputs_V
89+ VTAWriteMappedReg (vta_load_handle_, 0x10 , 0 );
90+ // LOAD @ 0x18 : Data signal of weight_V
91+ VTAWriteMappedReg (vta_load_handle_, 0x18 , 0 );
92+ // COMPUTE @ 0x20 : Data signal of uops_V
93+ VTAWriteMappedReg (vta_compute_handle_, 0x20 , 0 );
94+ // COMPUTE @ 0x28 : Data signal of biases_V
95+ VTAWriteMappedReg (vta_compute_handle_, 0x28 , 0 );
96+ // STORE @ 0x10 : Data signal of outputs_V
97+ VTAWriteMappedReg (vta_store_handle_, 0x10 , 0 );
98+
99+ // VTA start
100+ VTAWriteMappedReg (vta_fetch_handle_, 0x0 , VTA_START);
101+ VTAWriteMappedReg (vta_load_handle_, 0x0 , VTA_AUTORESTART);
102+ VTAWriteMappedReg (vta_compute_handle_, 0x0 , VTA_AUTORESTART);
103+ VTAWriteMappedReg (vta_store_handle_, 0x0 , VTA_AUTORESTART);
104+
105+ // Loop until the VTA is done
106+ unsigned t, flag = 0 ;
107+ for (t = 0 ; t < wait_cycles; ++t) {
108+ flag = VTAReadMappedReg (vta_compute_handle_, 0x18 );
109+ if (flag == VTA_DONE) break ;
110+ std::this_thread::yield ();
111+ }
112+ // Report error if timeout
113+ return t < wait_cycles ? 0 : 1 ;
114+ }
115+
116+ private:
117+ // VTA handles (register maps)
118+ void * vta_fetch_handle_{nullptr };
119+ void * vta_load_handle_{nullptr };
120+ void * vta_compute_handle_{nullptr };
121+ void * vta_store_handle_{nullptr };
122+ };
123+
124+ VTADeviceHandle VTADeviceAlloc () {
125+ return new VTADevice ();
126+ }
127+
128+ void VTADeviceFree (VTADeviceHandle handle) {
129+ delete static_cast <VTADevice*>(handle);
130+ }
131+
132+ int VTADeviceRun (VTADeviceHandle handle,
133+ vta_phy_addr_t insn_phy_addr,
134+ uint32_t insn_count,
135+ uint32_t wait_cycles) {
136+ return static_cast <VTADevice*>(handle)->Run (
137+ insn_phy_addr, insn_count, wait_cycles);
138+ }
139+
60140void VTAProgram (const char * bitstream) {
61- int elem;
62- FILE *src, *dst, *partial;
63- partial = fopen (VTA_PYNQ_BS_IS_PARTIAL, " w" );
64- if (partial == NULL ) {
65- printf (" Cannot open partial config file %s\n " , VTA_PYNQ_BS_IS_PARTIAL);
141+ int elem;
142+ FILE *src, *dst, *partial;
143+ partial = fopen (VTA_PYNQ_BS_IS_PARTIAL, " w" );
144+ if (partial == NULL ) {
145+ printf (" Cannot open partial config file %s\n " , VTA_PYNQ_BS_IS_PARTIAL);
66146 fclose (partial);
67147 exit (1 );
68- }
69- fputc (' 0' , partial);
70- fclose (partial);
71- src = fopen (bitstream, " rb" );
72- if (src == NULL ) {
73- printf (" Cannot open bitstream %s\n " , bitstream);
74- exit (1 );
75- }
76- dst = fopen (VTA_PYNQ_BS_XDEVCFG, " wb" );
77- if (dst == NULL ) {
78- printf (" Cannot open device file %s\n " , VTA_PYNQ_BS_XDEVCFG);
79- fclose (dst);
80- exit (1 );
81- }
82- elem = fgetc (src);
83- while (elem != EOF) {
84- fputc (elem, dst);
85- elem = fgetc (src);
86- }
87- fclose (src);
148+ }
149+ fputc (' 0' , partial);
150+ fclose (partial);
151+ src = fopen (bitstream, " rb" );
152+ if (src == NULL ) {
153+ printf (" Cannot open bitstream %s\n " , bitstream);
154+ exit (1 );
155+ }
156+ dst = fopen (VTA_PYNQ_BS_XDEVCFG, " wb" );
157+ if (dst == NULL ) {
158+ printf (" Cannot open device file %s\n " , VTA_PYNQ_BS_XDEVCFG);
88159 fclose (dst);
160+ exit (1 );
161+ }
162+ elem = fgetc (src);
163+ while (elem != EOF) {
164+ fputc (elem, dst);
165+ elem = fgetc (src);
166+ }
167+ fclose (src);
168+ fclose (dst);
89169}
0 commit comments