RoCC SW Wrappers now handled by generate_wrapper.py
This commit is contained in:
parent
841aab0053
commit
2f19dd036e
|
@ -75,7 +75,11 @@ sub generate_accel{
|
|||
system("perl run_chisel.pl ${PGM} ${FUNC} $prefix");
|
||||
}
|
||||
if ($tasks{'accel_sw'}){
|
||||
system("perl generate_wrapper.pl ${PGM} ${FUNC} $idx_addr $prefix");
|
||||
system("$RDIR/tools/centrifuge/scripts/generate_wrapper.py --fname ${FUNC} " .
|
||||
"--prefix $prefix " .
|
||||
"--base $idx_addr " .
|
||||
"--mode 'rocc' " .
|
||||
"--source $bm_path");
|
||||
}
|
||||
#system("make clean");
|
||||
#system("make CUSTOM_INST=1");
|
||||
|
@ -87,7 +91,6 @@ sub generate_accel{
|
|||
}
|
||||
|
||||
if ($tasks{'accel_sw'}){
|
||||
# system("perl generate_wrapper_tl.pl ${PGM} ${FUNC} $idx_addr $prefix");
|
||||
system("$RDIR/tools/centrifuge/scripts/generate_wrapper.py --fname ${FUNC} " .
|
||||
"--base $idx_addr " .
|
||||
"--prefix $prefix " .
|
||||
|
|
|
@ -1,337 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
use warnings;
|
||||
use strict;
|
||||
use Cwd;
|
||||
use File::Copy;
|
||||
use List::Util qw(first);
|
||||
|
||||
# Inputs: file_name, func_name, rocc_index, prefix(Optional)
|
||||
my $dir = getcwd;
|
||||
my $file_name = $ARGV[0];
|
||||
my $func_name = $ARGV[1];
|
||||
my $rocc_index= $ARGV[2];
|
||||
|
||||
my $prefix = undef;
|
||||
|
||||
my $num_args = $#ARGV + 1;
|
||||
if ($num_args > 3) {
|
||||
$prefix = $ARGV[3];
|
||||
}
|
||||
|
||||
my $rdir = $ENV{'RDIR'};
|
||||
#print $rdir;
|
||||
if ((not defined($rdir)) or $rdir eq '') {
|
||||
print("Please source sourceme-f1.sh!\n");
|
||||
exit();
|
||||
}
|
||||
my $wrapper_func_name = $func_name;
|
||||
my $wrapper_file= "accel_wrapper.c";
|
||||
my $wrapper_header= "accel_wrapper.h";
|
||||
if ($prefix) {
|
||||
$func_name = $prefix.$func_name;
|
||||
}
|
||||
|
||||
my $bm_inc_path = $rdir."/tools/centrifuge/scripts/sw_aux/sw_helper/";
|
||||
#############################PARSE Verilog##############################
|
||||
my $verilog_file = "$dir/../verilog/$func_name".".v";
|
||||
my $line = undef;
|
||||
my @verilog_input = ();
|
||||
my @verilog_input_size = ();
|
||||
my @verilog_output = ();
|
||||
my @verilog_output_size = ();
|
||||
|
||||
print "Parsing ".$verilog_file."\n";
|
||||
# parse the verilog file to get the info we need
|
||||
if(!open VERILOG, "$verilog_file"){
|
||||
print $!;
|
||||
} else {
|
||||
while(<VERILOG>){
|
||||
$line = $_;
|
||||
if($line =~ m/^\s*input\s+(.*)/){
|
||||
my $input = $1;
|
||||
#print "input:$input\n";
|
||||
if($input =~ m/\s*\[(.*):(.*)\]\s*(.*)\s*;/){
|
||||
my $end = $1;
|
||||
my $start = $2;
|
||||
my $input_name = $3;
|
||||
#print "here!"."$input_name\n";
|
||||
push (@verilog_input, $input_name);
|
||||
my $size = $end - $start + 1;
|
||||
push(@verilog_input_size, $size);
|
||||
}elsif ($input =~ m/\s*(.*)\s*;/){
|
||||
my $input_name = $1;
|
||||
#print "here!"."$input_name\n";
|
||||
push (@verilog_input, $input_name);
|
||||
push(@verilog_input_size, 1);
|
||||
}
|
||||
|
||||
}elsif($line =~ m/^\s*output\s+(.*)/){
|
||||
my $output = $1;
|
||||
#print "output:$output\n";
|
||||
if($output =~ m/\s*\[(.*):(.*)\]\s*(.*)\s*;/){
|
||||
my $end = $1;
|
||||
my $start = $2;
|
||||
my $output_name = $3;
|
||||
#print "here!"."$output_name\n";
|
||||
push(@verilog_output, $output_name);
|
||||
my $size = $end - $start + 1;
|
||||
push(@verilog_output_size, $size);
|
||||
}elsif ($output =~ m/\s*(.*)\s*;/){
|
||||
my $output_name = $1;
|
||||
#print "here!"."$output_name\n";
|
||||
push (@verilog_output, $output_name);
|
||||
push(@verilog_output_size, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
print("Inputs:");
|
||||
my $in_str = join ' ', @verilog_input;
|
||||
print $in_str."\n";
|
||||
print("Outputs:");
|
||||
my $out_str = join ' ', @verilog_output;
|
||||
print $out_str."\n";
|
||||
}
|
||||
|
||||
#creat scala folder
|
||||
my $scala_dir = "$dir/../scala";
|
||||
mkdir $scala_dir unless (-d $scala_dir);
|
||||
|
||||
##############################################################################################################################
|
||||
print "Generating BlackBox file ...\n";
|
||||
# should be under scala folder
|
||||
|
||||
my $blackbox1 = "
|
||||
package hls_test_c
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.util._
|
||||
import vivadoHLS._
|
||||
|
||||
class test_c() extends BlackBox() {
|
||||
";
|
||||
$blackbox1 =~ s/test_c/$func_name/g;
|
||||
|
||||
|
||||
my $i = undef;
|
||||
my $bb_body = "";
|
||||
|
||||
# now if the input name does not start with ap, we assume it is an arg
|
||||
my $ap_return = 0;
|
||||
my $ap_clk = 0;
|
||||
my $ap_rst = 0;
|
||||
my @verilog_input_scalar = ();
|
||||
my %verilog_input_pointer = ();
|
||||
my @verilog_input_pointer_arg = (); # An ordered list of args
|
||||
|
||||
my $arg_count = 0;
|
||||
my @sindices = ();
|
||||
my @pindices = ();
|
||||
|
||||
for( $i = 0; $i < @verilog_input; $i = $i + 1 ){
|
||||
my $input_name = $verilog_input[$i];
|
||||
my $input_size = $verilog_input_size[$i];
|
||||
|
||||
if ($input_name =~ m/ap_clk(.*)/){
|
||||
$ap_clk = 1;
|
||||
}
|
||||
|
||||
|
||||
elsif ($input_name =~ m/ap_rst(.*)/){
|
||||
$ap_rst = 1;
|
||||
}
|
||||
|
||||
# If the input is a ap_bus port, the signals should match the following format
|
||||
# There should be 3 different input signals
|
||||
elsif($input_name =~ m/(\S+)_req_full_n/ or $input_name =~ m/(\S+)_rsp_empty_n/ or $input_name =~ m/(\S+)_datain/){
|
||||
my $arg_name = $1;
|
||||
if ($input_name =~ m/(\S+)_datain/) {
|
||||
push(@pindices, $arg_count);
|
||||
$arg_count = $arg_count + 1;
|
||||
push(@verilog_input_pointer_arg, $arg_name);
|
||||
}
|
||||
if (defined $verilog_input_pointer{$arg_name}) {
|
||||
$verilog_input_pointer{$arg_name} += 1;
|
||||
} else {
|
||||
$verilog_input_pointer{$arg_name} = 1;
|
||||
}
|
||||
}
|
||||
elsif(!($input_name =~ m/ap_(,*)/)){
|
||||
push (@verilog_input_scalar, $input_name);
|
||||
push(@sindices, $arg_count);
|
||||
$arg_count = $arg_count + 1;
|
||||
}
|
||||
else{
|
||||
print("Not func args: $input_name\n");
|
||||
}
|
||||
}
|
||||
|
||||
#foreach my $arg (keys %verilog_input_pointer) {
|
||||
foreach my $arg (@verilog_input_pointer_arg) {
|
||||
print("pointer_arg: $arg\n");
|
||||
}
|
||||
my $hash_count = keys %verilog_input_pointer;
|
||||
print("hash_count: $hash_count\n");
|
||||
if(@verilog_input_scalar + $hash_count> 2){
|
||||
print "verilog_input_scalar: ";
|
||||
my $in_str = join ' ', @verilog_input_scalar;
|
||||
print $in_str."\n";
|
||||
die "Only accept function with no more than 2 arguments!\n";
|
||||
}
|
||||
|
||||
foreach my $arg (keys %verilog_input_pointer) {
|
||||
if ($verilog_input_pointer{$arg} ne 3) {
|
||||
die "The AP bus interfance did not generate expected number of inputs!\n";
|
||||
}
|
||||
}
|
||||
|
||||
for( $i = 0; $i < @verilog_output; $i = $i + 1 ){
|
||||
|
||||
my $output_name = $verilog_output[$i];
|
||||
my $output_size = $verilog_output_size[$i];
|
||||
|
||||
if ($output_name =~ m/ap_return(.*)/){
|
||||
$ap_return = 1;
|
||||
}
|
||||
|
||||
$bb_body = $bb_body."\tio.".$output_name.".setName(\"".$output_name."\")\n";
|
||||
}
|
||||
|
||||
if ($ap_clk eq 1){
|
||||
$bb_body = $bb_body."addClock(Driver\.implicitClock)\n".'renameClock("clk", "ap_clk")'."\n";
|
||||
}
|
||||
|
||||
if ($ap_rst eq 1){
|
||||
$bb_body = $bb_body.'renameReset("ap_rst")'."\n";
|
||||
}
|
||||
|
||||
my $bb_def = "class HLS$func_name"."Blackbox() extends Module {\n";
|
||||
|
||||
# Scalar IO Parameter
|
||||
my @sdata_widths = ();
|
||||
#my @sindices = ();
|
||||
#my $sidx = 0;
|
||||
foreach my $arg (@verilog_input_scalar) {
|
||||
my $sdata_idx = first { $verilog_input[$_] eq $arg} 0..$#verilog_input;
|
||||
my $sdata_width = $verilog_input_size[$sdata_idx];
|
||||
push(@sdata_widths, $sdata_width);
|
||||
#push(@sindices, $sidx);
|
||||
#$sidx += 1;
|
||||
}
|
||||
my $sindices_str = join ',',@sindices;
|
||||
my $sdata_widths_str = join ',',@sdata_widths;
|
||||
print "scalar data_widths: $sdata_widths_str\n";
|
||||
|
||||
$bb_def .= "\tval scalar_io_dataWidths = List($sdata_widths_str)\n";
|
||||
$bb_def .= "\tval scalar_io_argLoc = List($sindices_str) //Lists the argument number of the scalar_io\n";
|
||||
|
||||
# Pointer IO Parameter
|
||||
my @addr_widths = ();
|
||||
my @data_widths = ();
|
||||
#my @indices = ();
|
||||
my $idx = 0;
|
||||
foreach my $arg (sort keys %verilog_input_pointer) {
|
||||
my $addr_signal = $arg."_address";
|
||||
my $data_signal = $arg."_dataout";
|
||||
my $addr_idx = first { $verilog_output[$_] eq $addr_signal } 0..$#verilog_output;
|
||||
my $data_idx = first { $verilog_output[$_] eq $data_signal } 0..$#verilog_output;
|
||||
#my $addr_width = $verilog_output_size[$addr_idx];
|
||||
my $addr_width = "64";
|
||||
|
||||
my $data_width = $verilog_output_size[$data_idx];
|
||||
push(@addr_widths, $addr_width);
|
||||
push(@data_widths, $data_width);
|
||||
#push(@indices, $idx);
|
||||
$idx += 1;
|
||||
}
|
||||
#my $indices_str = join ',',@indices;
|
||||
my $pindices_str = join ',',@pindices;
|
||||
my $addr_widths_str = join ',',@addr_widths;
|
||||
print "addr_widths: $addr_widths_str\n";
|
||||
my $data_widths_str = join ',',@data_widths;
|
||||
print "data_widths: $data_widths_str\n";
|
||||
|
||||
|
||||
foreach my $arg (@verilog_input_pointer_arg) {
|
||||
print("pointer_arg: $arg\n");
|
||||
}
|
||||
|
||||
my $wrapper = '#include "'.$bm_inc_path.'rocc.h"'."\n";
|
||||
$wrapper .="#define ACCEL_WRAPPER\n";
|
||||
$wrapper .='#include "accel.h"'."\n";
|
||||
|
||||
my $return_type = "void ";
|
||||
if($ap_return){
|
||||
$return_type = "uint64_t ";
|
||||
}
|
||||
|
||||
my $total_args = @verilog_input_scalar + $hash_count;
|
||||
my $func_prototype = "$return_type $wrapper_func_name(";
|
||||
|
||||
my @args = ();
|
||||
foreach my $arg (@verilog_input_scalar) {
|
||||
push(@args, $arg);
|
||||
}
|
||||
foreach my $arg (@verilog_input_pointer_arg) {
|
||||
push(@args, $arg);
|
||||
}
|
||||
|
||||
my $arg_str = join ', ', @args;
|
||||
$i = 0;
|
||||
foreach my $arg (@args) {
|
||||
if ($i != 0){
|
||||
$func_prototype.=", "
|
||||
}
|
||||
$func_prototype .="uint64_t $arg";
|
||||
|
||||
$i=1;
|
||||
}
|
||||
$func_prototype .= ")";
|
||||
|
||||
$wrapper .= $func_prototype;
|
||||
if($ap_return){
|
||||
$wrapper .= "
|
||||
{
|
||||
uint64_t ret_val;\n";
|
||||
}
|
||||
|
||||
#$wrapper .= " ROCC_BARRIER();\n";
|
||||
$wrapper .="
|
||||
#define XCUSTOM_ACC ";
|
||||
$wrapper .= $rocc_index."\n";
|
||||
|
||||
if ($ap_return){
|
||||
if ($total_args == 0) {
|
||||
$wrapper.=" ROCC_INSTRUCTION_D(XCUSTOM_ACC, ret_val, 0);\n";
|
||||
} elsif ($total_args == 1) {
|
||||
$wrapper.=" ROCC_INSTRUCTION_DS(XCUSTOM_ACC, ret_val, $arg_str, 0);\n";
|
||||
} else {
|
||||
$wrapper.=" ROCC_INSTRUCTION_DSS(XCUSTOM_ACC, ret_val, $arg_str, 0);\n";
|
||||
}
|
||||
} else{
|
||||
if ($total_args == 0) {
|
||||
$wrapper.=" ROCC_INSTRUCTION(XCUSTOM_ACC, 0);\n";
|
||||
} elsif ($total_args == 1) {
|
||||
$wrapper.=" ROCC_INSTRUCTION_S(XCUSTOM_ACC, $arg_str, 0);\n";
|
||||
} else {
|
||||
$wrapper.=" ROCC_INSTRUCTION_SS(XCUSTOM_ACC, $arg_str, 0);\n";
|
||||
}
|
||||
}
|
||||
$wrapper .= " ROCC_BARRIER();\n";
|
||||
if($ap_return){
|
||||
$wrapper .= " return ret_val;\n";
|
||||
}
|
||||
$wrapper.="}";
|
||||
|
||||
open FILE, "> $wrapper_header";
|
||||
print FILE "#ifndef ACCEL_WRAPPER_H
|
||||
#define ACCEL_WRAPPER_H\n
|
||||
";
|
||||
print FILE "$func_prototype;\n";
|
||||
print FILE "#endif";
|
||||
close FILE;
|
||||
|
||||
open FILE, "> $wrapper_file";
|
||||
print FILE $wrapper;
|
||||
close FILE;
|
||||
|
|
@ -27,15 +27,77 @@ class MmioArg():
|
|||
else:
|
||||
raise RuntimeError("Unsupported variable size: " + str(self.size))
|
||||
|
||||
def generateHeader(signature):
|
||||
"""Given the signature of the accelerated function, return an appropriate
|
||||
header file. """
|
||||
|
||||
header = ("#ifndef ACCEL_WRAPPER_H\n"
|
||||
"#define ACCEL_WRAPPER_H\n")
|
||||
|
||||
header += '\n'
|
||||
header += signature + ";\n"
|
||||
header += "#endif"
|
||||
return header
|
||||
|
||||
def ident(n):
|
||||
return " "*n
|
||||
|
||||
def cleanRoccArg(body):
|
||||
"""Cleans up a RoccArg. Returns True if the argument was cleaned and can be
|
||||
used, returns False if the argument should be ignored."""
|
||||
|
||||
reIgnore = re.compile('ap_clk.*|ap_rst.*|\S+_req_full_n|\S+_rsp_empty_n')
|
||||
reBaseName = re.compile('ap_(\S+)|(\S+)_datain')
|
||||
|
||||
if reIgnore.match(body):
|
||||
return None
|
||||
|
||||
m = reBaseName.match(body)
|
||||
if not m:
|
||||
raise ValueError("Could not parse argument name: " + body)
|
||||
|
||||
return m.group(m.lastindex)
|
||||
|
||||
def parseVerilogRocc(vpath):
|
||||
"""Parse a centrifuge-generated verilog file to extract the information
|
||||
needed to generate a RoCC wrapper.
|
||||
|
||||
vpath: Path to main verilog function file
|
||||
|
||||
Returns: (inputs, retVal)
|
||||
inputs - list of argument names
|
||||
retVal - boolean indicating whether or not a return value is present
|
||||
"""
|
||||
|
||||
# Input/Output statements in the verilog. We assume only one module in the file.
|
||||
reInput = re.compile('^\s*input\s+\[.*:.*\]\s*(.*)')
|
||||
reReturnVal = re.compile('^\s*output\s+\[(.*):(.*)\]\s*ap_return;')
|
||||
|
||||
print("Parsing: ",vpath)
|
||||
inputs = []
|
||||
retVal = False
|
||||
with open(vpath, 'r') as vf:
|
||||
for line in vf.readlines():
|
||||
inMatch = reInput.match(line)
|
||||
if inMatch:
|
||||
argName = cleanRoccArg(inMatch.group(1))
|
||||
if argName:
|
||||
inputs.append(argName)
|
||||
else:
|
||||
if reReturnVal.match(line):
|
||||
retVal = True
|
||||
|
||||
return inputs, retVal
|
||||
|
||||
def parseVerilogTL(vpath):
|
||||
"""Parse a centrifuge-generated verilog file to extract the information
|
||||
needed to generate tilelink wrappers.
|
||||
|
||||
vpath: Path to the verilog file to parse (path-like object)
|
||||
vpath: Path to the verilog file containing control signal info (path-like object)
|
||||
|
||||
returns: (returnSize, Args)
|
||||
returnSize: The size of the return value in 32-bit words. Either 0, 1, or 2.
|
||||
Args: An ordered dictionary of mappings from argument name to base address
|
||||
retVal: MmioArg representing the return value (or None if no return).
|
||||
Args: List of MmioArg representing the arguments to the accelerated function
|
||||
"""
|
||||
with open(vpath, 'r') as vf:
|
||||
print("Parsing: ",vpath)
|
||||
|
@ -70,16 +132,74 @@ def parseVerilogTL(vpath):
|
|||
|
||||
return (retVal, list(args.values()))
|
||||
|
||||
def generateHeaderTL(signature):
|
||||
"""Given the signature of the accelerated function, return an appropriate
|
||||
header file. """
|
||||
def generateWrapperRocc(fname, roccIdx, inputs, retVal):
|
||||
"""Returns a Rocc C wrapper given a function.
|
||||
|
||||
header = ("#ifndef ACCEL_WRAPPER_H\n"
|
||||
"#define ACCEL_WRAPPER_H\n")
|
||||
fname - name of the function
|
||||
inputs - list of argument names
|
||||
retVal - boolean indicating whether or not a value is returned
|
||||
"""
|
||||
|
||||
header += signature + ";\n"
|
||||
header += "#endif"
|
||||
return header
|
||||
# current indentation level
|
||||
lvl = 0
|
||||
|
||||
cWrapper = ('#include "rocc.h"\n'
|
||||
'\n'
|
||||
'#define ACCEL_WRAPPER\n'
|
||||
'#include "accel.h"\n'
|
||||
'\n')
|
||||
|
||||
cWrapper += ident(lvl) + "#define XCUSTOM_ACC " + roccIdx + "\n"
|
||||
cWrapper += "\n"
|
||||
|
||||
signature = ""
|
||||
if retVal:
|
||||
retStr = "uint64_t"
|
||||
else:
|
||||
retStr = "void"
|
||||
|
||||
signature += retStr + " " + fname + "("
|
||||
argStrs = []
|
||||
for arg in inputs:
|
||||
argStrs.append("uint64_t " + arg)
|
||||
signature += ", ".join(argStrs)
|
||||
signature += ")"
|
||||
cWrapper += signature + "\n"
|
||||
cWrapper += "{\n"
|
||||
|
||||
lvl = 1
|
||||
if retVal:
|
||||
cWrapper += ident(lvl) + "uint64_t ret_val;\n"
|
||||
cWrapper += "\n"
|
||||
|
||||
if len(inputs) == 0:
|
||||
cWrapper += ident(lvl) + "ROCC_INSTRUCTION_D(XCUSTOM_ACC, ret_val, 0);\n"
|
||||
elif len(inputs) == 1:
|
||||
cWrapper += ident(lvl) + "ROCC_INSTRUCTION_DS(XCUSTOM_ACC, ret_val, " + inputs[0] + ", 0);\n"
|
||||
elif len(inputs) == 2:
|
||||
cWrapper += ident(lvl) + "ROCC_INSTRUCTION_DSS(XCUSTOM_ACC, ret_val, " + inputs[0] + ", " + inputs[1] + ", 0);\n"
|
||||
else:
|
||||
raise ValueError("Too many inputs. Rocc only supports up to 2 arguments, was passed " + len(inputs))
|
||||
|
||||
else:
|
||||
if len(inputs) == 0:
|
||||
cWrapper += ident(lvl) + "ROCC_INSTRUCTION(XCUSTOM_ACC, 0);\n"
|
||||
elif len(inputs) == 1:
|
||||
cWrapper += ident(lvl) + "ROCC_INSTRUCTION_S(XCUSTOM_ACC, " + inputs[0] + ", 0);\n"
|
||||
elif len(inputs) == 2:
|
||||
cWrapper += ident(lvl) + "ROCC_INSTRUCTION_SS(XCUSTOM_ACC, " + inputs[0] + ", 0);\n"
|
||||
else:
|
||||
raise ValueError("Too many inputs. Rocc only supports up to 2 arguments, was passed " + len(inputs))
|
||||
|
||||
cWrapper += ident(lvl) + "ROCC_BARRIER();\n"
|
||||
|
||||
cWrapper += '\n'
|
||||
if retVal:
|
||||
cWrapper += ident(lvl) + "return ret_val;\n"
|
||||
|
||||
cWrapper += "}"
|
||||
|
||||
return cWrapper, generateHeader(signature)
|
||||
|
||||
def generateWrapperTL(fname, baseAddr, retVal, args):
|
||||
"""Given a set of mmio address/varialble pairs, produce the C wrapper
|
||||
|
@ -92,9 +212,9 @@ def generateWrapperTL(fname, baseAddr, retVal, args):
|
|||
"""
|
||||
|
||||
cWrapper = ('#include "mmio.h"\n'
|
||||
'#define ACCEL_WRAPPER\n'
|
||||
'#include "accel.h"\n'
|
||||
'\n'
|
||||
'#define ACCEL_WRAPPER\n'
|
||||
'#define AP_DONE_MASK 0b10\n')
|
||||
|
||||
# MMIO Constants
|
||||
|
@ -125,7 +245,7 @@ def generateWrapperTL(fname, baseAddr, retVal, args):
|
|||
|
||||
# Pass Args to MMIO
|
||||
cWrapper += " //Disable Interrupts\n"
|
||||
cWrapper += " reg_write32(ACCEL_BASE + ACCEL_INT, 0x0)\n"
|
||||
cWrapper += " reg_write32(ACCEL_BASE + ACCEL_INT, 0x0);\n"
|
||||
for arg in args:
|
||||
cWrapper += " reg_write32(ACCEL_BASE + ACCEL_"+arg.name+"_0, (uint32_t) "+arg.name+");\n"
|
||||
if arg.size == 2:
|
||||
|
@ -143,6 +263,7 @@ def generateWrapperTL(fname, baseAddr, retVal, args):
|
|||
|
||||
# Handle returns (if any)
|
||||
if retVal is not None:
|
||||
cWrapper += "\n"
|
||||
cWrapper += " " + retVal.cType() + " ret_val = 0;\n"
|
||||
cWrapper += " ret_val = reg_read32(ACCEL_BASE + ACCEL_"+retVal.name+"_0);\n"
|
||||
if retVal.size == 2:
|
||||
|
@ -150,14 +271,14 @@ def generateWrapperTL(fname, baseAddr, retVal, args):
|
|||
|
||||
cWrapper += "}"
|
||||
|
||||
return cWrapper, generateHeaderTL(signature)
|
||||
return cWrapper, generateHeader(signature)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate software wrappers for a given centrifuge-generated function.")
|
||||
|
||||
parser.add_argument('-n', '--fname', required=True, help="Name of function to accelerate")
|
||||
parser.add_argument('-b', '--base', required=True, help="Base address of function (if tilelink)")
|
||||
parser.add_argument('-b', '--base', required=True, help="Base address of function (if tilelink), RoCC index (if rocc)")
|
||||
parser.add_argument('-p', '--prefix', default="", help="Optional prefix for function")
|
||||
parser.add_argument('-m', '--mode', required=True,
|
||||
help="Function integration mode (either 'tl' or 'rocc')")
|
||||
|
@ -171,11 +292,17 @@ if __name__ == '__main__':
|
|||
args.source / 'src' / 'main' / 'verilog' / (args.prefix + args.fname + "_control_s_axi.v"))
|
||||
|
||||
cWrapper, hWrapper = generateWrapperTL(args.fname, args.base, retVal, funcArgs)
|
||||
with open(args.source / 'src' / 'main' / 'c' / 'accel_wrapper.c', 'w') as cF:
|
||||
cF.write(cWrapper)
|
||||
|
||||
with open(args.source / 'src' / 'main' / 'c' / 'accel_wrapper.h', 'w') as hF:
|
||||
hF.write(hWrapper)
|
||||
|
||||
elif args.mode == 'rocc':
|
||||
inputs, retVal = parseVerilogRocc(
|
||||
args.source / 'src' / 'main' / 'verilog' / (args.prefix + args.fname + ".v"))
|
||||
cWrapper, hWrapper = generateWrapperRocc(args.fname, args.base, inputs, retVal)
|
||||
else:
|
||||
raise NotImplementedError("Mode '" + args.mode + "' not supported.")
|
||||
|
||||
|
||||
with open(args.source / 'src' / 'main' / 'c' / 'accel_wrapper.c', 'w') as cF:
|
||||
cF.write(cWrapper)
|
||||
|
||||
with open(args.source / 'src' / 'main' / 'c' / 'accel_wrapper.h', 'w') as hF:
|
||||
hF.write(hWrapper)
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ CFLAGS+=-mcmodel=medany -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall -DW
|
|||
LDFLAGS=-static -nostdlib -nostartfiles -lgcc
|
||||
|
||||
BM_LIB_DIR=${RDIR}/tools/centrifuge/scripts/sw_aux/bm_linker_scripts/
|
||||
BM_INC_DIR=${RDIR}/tools/centrifuge/scripts/sw_aux/sw_helper/
|
||||
|
||||
INCLUDES=-I${BM_LIB_DIR} -I${BM_INC_DIR}
|
||||
|
||||
BM_LIB_FLAG=-lriscvbm
|
||||
BM_LIB=$(BM_LIB_DIR)/libriscvbm.a
|
||||
|
||||
|
@ -41,23 +45,23 @@ all: $(addsuffix .bm.rv,$(TARGET)) bm_accel
|
|||
|
||||
dumps: $(addsuffix .dump,$(TARGET))
|
||||
|
||||
.s.o: $(SRC_S)
|
||||
$(CC) $(CFLAGS) -D__ASSEMBLY__=1 -c $< -o $@
|
||||
%.s.o: %.S
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -D__ASSEMBLY__=1 -c $< -o $@
|
||||
|
||||
.o: $(SRC)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
|
||||
|
||||
#%.rv: %.o crt.o syscalls.o $(BM_LIB_DIR)/bm_linker_scripts/link.ld
|
||||
# Use $info to debug
|
||||
#$(TARGET).rv: $(OBJ) $(BM_LIB) $(BM_LIB_DIR)/link.ld $(info $(OBJ))
|
||||
$(TARGET).bm.rv: Makefile $(OBJ) $(BM_LIB) $(BM_LIB_DIR)/link.ld
|
||||
$(CC) -T $(BM_LIB_DIR)/link.ld $(LDFLAGS) -I$(BM_LIB_DIR) -L$(BM_LIB_DIR) $(BM_LIB_FLAG) $(OBJ_BASE) -o $@
|
||||
$(CC) -T $(BM_LIB_DIR)/link.ld $(LDFLAGS) $(INCLUDES) -L$(BM_LIB_DIR) $(BM_LIB_FLAG) $(OBJ_BASE) -o $@
|
||||
|
||||
# Add new target
|
||||
bm_accel: $(addsuffix .bm_accel.rv,$(TARGET))
|
||||
|
||||
$(TARGET).bm_accel.rv: $(OBJ) $(BM_LIB) $(BM_LIB_DIR)/link.ld
|
||||
$(CC) -T $(BM_LIB_DIR)/link.ld $(LDFLAGS) -I$(BM_LIB_DIR) -L$(BM_LIB_DIR) $(BM_LIB_FLAG) $(OBJ_ACCEL) -o $@
|
||||
$(CC) -T $(BM_LIB_DIR)/link.ld $(LDFLAGS) $(INCLUDES) -L$(BM_LIB_DIR) $(BM_LIB_FLAG) $(OBJ_ACCEL) -o $@
|
||||
|
||||
%.dump: %.rv
|
||||
$(OBJDUMP) -D $< > $@
|
||||
|
|
Loading…
Reference in New Issue