Skip to content

Commit

Permalink
Merge pull request #8 from ReconfigureIO/temp/tutorial3-examples
Browse files Browse the repository at this point in the history
Temp/tutorial3 examples
  • Loading branch information
Rosie Yohannan authored Nov 1, 2017
2 parents ea352cd + edcae34 commit 3c501df
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 0 deletions.
48 changes: 48 additions & 0 deletions template/cmd/test/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"os"
"xcl"
)

func main() {
// Allocate a 'world' for interacting with kernels
world := xcl.NewWorld()
defer world.Release()

// Import the kernel.
// Right now these two identifiers are hard coded as an output from the build process
krnl := world.Import("kernel_test").GetKernel("reconfigure_io_sdaccel_builder_stub_0_1")
defer krnl.Release()

// Allocate a space in the shared memory to store the data you're sending to the FPGA and space
// for the results from the FPGA
inputBuff := world.Malloc(xcl.ReadOnly, <size here>)
defer inputBuff.Free()

outputBuff := world.Malloc(xcl.WriteOnly, <size here>)
defer outputBuff.Free()

// Create/get data and pass arguments to the kernel as required. These could be small pieces of data,
// pointers to memory, data lengths so the Kernel knows what to expect. This all depends on your project.
// Usually, you will send data via shared memory, so you will need to write it to the space you allocated
// above before passing the pointer to the kernel
// We have passed three arguments here, you can pass more as neccessary

// First argument
krnl.SetArg(0, <first>)
// Second argument
krnl.SetArg(1, <second>)
// Third argument
krnl.SetMemoryArg(2, <third>)

// Run the kernel with the supplied arguments. This is the same for all projects.
// The arguments ``(1, 1, 1)`` relate to x, y, z co-ordinates and correspond to our current
// underlying technology.
krnl.Run(1, 1, 1)

// Display/use the results returned from the FPGA as required!

...

}
33 changes: 33 additions & 0 deletions template/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
// Import the entire framework (including bundled verilog)
_ "sdaccel"

// Use the new AXI protocol package
aximemory "axi/memory"
axiprotocol "axi/protocol"
)

func Top(
// Specify inputs and outputs to the kernel. Tell the kernel where to find data in shared memory, what data type
// to expect or pass single integers directly to the kernel by sending them to the FPGA's control register

...

// Set up channels for interacting with the shared memory
memReadAddr chan<- axiprotocol.Addr,
memReadData <-chan axiprotocol.ReadData,

memWriteAddr chan<- axiprotocol.Addr,
memWriteData chan<- axiprotocol.WriteData,
memWriteResp <-chan axiprotocol.WriteResp) {

// Do whatever needs doing with the data from the host

...

// Write the result to the location in shared memory as requested by the host
aximemory.WriteUInt32(
memWriteAddr, memWriteData, memWriteResp, true, <results_pointer>, <results_data>)
}
68 changes: 68 additions & 0 deletions tutorial3_examples/multiply-array/cmd/test-multiply-array/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"encoding/binary"
"xcl"
"fmt"
)

func main() {
// Allocate a 'world' for interacting with kernels
world := xcl.NewWorld()
defer world.Release()

// Import the kernel.
// Right now these two identifiers are hard coded as an output from the build process
krnl := world.Import("kernel_test").GetKernel("reconfigure_io_sdaccel_builder_stub_0_1")
defer krnl.Release()

// Create/get data and pass arguments to the kernel as required. These could be small pieces of data,
// pointers to memory, data lengths so the Kernel knows what to expect. This all depends on your project.
// We have passed three arguments here, you can pass more as neccessary

// make an array to send to the kernel for processing
input := make([]uint32, 10)

// seed it with incrementing values
for i, _ := range input {
input[i] = uint32(i)
}

// Create space in shared memory for our array input
buff := world.Malloc(xcl.ReadOnly, uint(binary.Size(input)))
defer buff.Free()

// Create a variable to hold the output from the FPGA
var output [10]uint32

// Create space in the shared memory for the output from the FPGA
outputBuff := world.Malloc(xcl.ReadWrite, uint(binary.Size(output)))
defer outputBuff.Free()

// write our input to the shared memory at the location we specified previously
binary.Write(buff.Writer(), binary.LittleEndian, &input)

// zero out output space
binary.Write(outputBuff.Writer(), binary.LittleEndian, &output)

// Send the location of the input array as the first argument
krnl.SetMemoryArg(0, buff)
// Send the location the FPGA should put the result as the second argument
krnl.SetMemoryArg(1, outputBuff)
// Send the length of the input array, so the kernel knows what to expect, as the third argument
krnl.SetArg(2, uint32(len(input)))

// Run the kernel with the supplied arguments. This is the same for all projects.
// The arguments ``(1, 1, 1)`` relate to x, y, z co-ordinates and correspond to our current
// underlying technology.
krnl.Run(1, 1, 1)

// Display/use the results returned from the FPGA as required!

binary.Read(outputBuff.Reader(), binary.LittleEndian, &output);

for _, val := range output {
print(val)
}

}
48 changes: 48 additions & 0 deletions tutorial3_examples/multiply-array/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
// Import the entire framework (including bundled verilog)
_ "sdaccel"

// Use the new AXI protocol package
aximemory "axi/memory"
axiprotocol "axi/protocol"
)

func Top(
// Specify inputs and outputs to the kernel. Tell the kernel where to find data in shared memory, what data type
// to expect or pass single integers directly to the kernel by sending them to the FPGA's control register

inputData uintptr,
outputData uintptr,
length uint32,

// Set up channels for interacting with the shared memory
memReadAddr chan<- axiprotocol.Addr,
memReadData <-chan axiprotocol.ReadData,

memWriteAddr chan<- axiprotocol.Addr,
memWriteData chan<- axiprotocol.WriteData,
memWriteResp <-chan axiprotocol.WriteResp) {

// Do whatever needs doing with the data from the host

// Read all the input data into a channel
inputChan := make(chan uint32)
go aximemory.ReadBurstUInt32(
memReadAddr, memReadData, true, inputData, length, inputChan)

// Create a channel for the result of the calculation
transformedChan := make(chan uint32)
// multiply each element of the input channel by 2 and send to the channel we just made to hold the result
go func(){
// no need to stop here, which will save us some clocks checking
for {
transformedChan <- (<-inputChan) * 2
}
}()

// Write transformed results back to memory
aximemory.WriteBurstUInt32(
memWriteAddr, memWriteData, memWriteResp, true, outputData, length, transformedChan)
}
44 changes: 44 additions & 0 deletions tutorial3_examples/multiply1/cmd/test-multiply1/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"encoding/binary"
"xcl"
"fmt"
)

func main() {
// Allocate a 'world' for interacting with kernels
world := xcl.NewWorld()
defer world.Release()

// Import the kernel.
// Right now these two identifiers are hard coded as an output from the build process
krnl := world.Import("kernel_test").GetKernel("reconfigure_io_sdaccel_builder_stub_0_1")
defer krnl.Release()

// Allocate a space in the shared memory to store the results from the FPGA
// The output is a uint32, so we need 4 bytes to store it
buff := world.Malloc(xcl.WriteOnly, 4)
defer buff.Free()

// Pass the arguments to the kernel. These could be small pieces of data, pointers to
// memory, data lengths so the Kernel knows what to expect. This all depends on your project.

// First argument
krnl.SetArg(0, 1)
// Second argument
krnl.SetMemoryArg(1, buff)

// Run the kernel with the supplied arguments. This is the same for all projects.
// The arguments ``(1, 1, 1)`` relate to x, y, z co-ordinates and correspond to our current
// underlying technology.
krnl.Run(1, 1, 1)

// Display/use the results returned from the FPGA as required!
var output uint32
binary.Read(buff.Reader(), binary.LittleEndian, &output);

// Print the value we got from the FPGA
fmt.Printf("%d\n", output)

}
38 changes: 38 additions & 0 deletions tutorial3_examples/multiply1/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
// Import the entire framework (including bundled verilog)
_ "sdaccel"

// Use the new AXI protocol package
aximemory "axi/memory"
axiprotocol "axi/protocol"
)

func Top(
// Specify inputs and outputs to the kernel. Tell the kernel where to find data in shared memory, what data type
// to expect or pass single integers directly to the kernel by sending them to the FPGA's control register

a uint32,
addr uintptr,

// Set up channels for interacting with the shared memory
memReadAddr chan<- axiprotocol.Addr,
memReadData <-chan axiprotocol.ReadData,

memWriteAddr chan<- axiprotocol.Addr,
memWriteData chan<- axiprotocol.WriteData,
memWriteResp <-chan axiprotocol.WriteResp) {

// Since we're not reading anything from memory, disable those reads
go axiprotocol.ReadDisable(memReadAddr, memReadData)

// Do whatever needs doing with the data from the host

// Multiply incoming data by 2
val := a * 2

// Write the result to the location in shared memory as requested by the host
aximemory.WriteUInt32(
memWriteAddr, memWriteData, memWriteResp, true, addr, uint32(val))
}

0 comments on commit 3c501df

Please sign in to comment.