Skip to content
Snippets Groups Projects
Commit e93c1e93 authored by dam1n19's avatar dam1n19
Browse files

SOC1-163: Moved Stimgen file to project repo added request ctrl register module to wrapper repo

parent 7a5fe702
No related branches found
No related tags found
No related merge requests found
import csv, os, tabulate
from enum import Enum
soclabs_header = """;#-----------------------------------------------------------------------------
;# SoC Labs Basic Hashing Accelerator Wrapper Input Stimulus File
;# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
;#
;# Contributors
;#
;# David Mapstone (d.a.mapstone@soton.ac.uk)
;#
;# Copyright 2023, SoC Labs (www.soclabs.org)
;#-----------------------------------------------------------------------------"""
class TransactionType(Enum):
""" Enumerated Types for Transaction Types for ASCII Debug """
READ = 1
WRITE = 2
def __str__(self):
if (self == TransactionType.READ):
return "R"
elif (self == TransactionType.WRITE):
return "W"
class TransactionSize(Enum):
""" Enumerated Types for Transaction Types for ASCII Debug """
WORD = 1
HALFWORD = 2
def __str__(self):
if (self == TransactionSize.WORD):
return "word"
elif (self == TransactionSize.HALFWORD):
return "halfword"
class InputBlockStruct:
def __init__(self):
self.word_list = []
def word_append(self, word):
self.word_list.append(word)
class InputPacketStruct:
def __init__(self):
self.block_list = []
def block_append(self, block):
self.block_list.append(block)
class WordStruct:
def __init__(self, data, addr, trans, packet_num = 0, block_num = 0, size = TransactionSize.WORD):
self.data = data
self.addr = addr
self.trans = trans
self.packet_num = packet_num
self.block_num = block_num
self.size = size
def adp_output(out_file, word_list):
"""
This function takes a list of 32 bit words and addresses and formats
the data into .cmd format for the ADP module
testbench
"""
data = []
for word in word_list:
if (word.data > 0):
data.append(["a", "{0:#0{1}x}".format(word.addr,10)])
data.append([str(word.trans).lower(), "{0:#0{1}x}".format(word.data,10)])
table_str = tabulate.tabulate(data, tablefmt="plain")
with open(out_file, "w", encoding="UTF8", newline='') as f:
f.write("A\n")
f.write(table_str)
f.write("\n A")
f.write("\nX")
f.write("\n!")
def fri_output(out_file, word_list):
"""
This function takes a list of 32 bit words and addresses and formats
the data into .fri format to be fed into fml2conv.pl script to stimulate
testbench
"""
# Column Names
col_names = ["Transaction", "Address", "Data", "Size"]
data = []
for word in word_list:
if (word.data > 0):
data.append([str(word.trans), "{0:#0{1}x}".format(word.addr,10), "{0:#0{1}x}".format(word.data,10), str(word.size)])
table_str = tabulate.tabulate(data, headers=col_names, tablefmt="plain")
with open(out_file, "w", encoding="UTF8", newline='') as f:
f.write(soclabs_header + "\n;")
f.write(table_str)
f.write("\nQ") # Add End of Simulation Flag
def stimulus_generation(stim_file, ref_file, input_start_address, input_size, output_start_address, output_size):
"""
This function takes 32 bit input stimulus file from accelerator model,
calculates write addresses for each word and generates a .fri file which
can be used to stimulate an AHB testbench
"""
# Calculate End Address
input_end_address = input_start_address + input_size - 0x4
# print(f"End Address is {hex(end_address)}")
# Open Files
with open(stim_file, "r") as stim:
csvreader = csv.reader(stim, delimiter=",")
stim_list = list(csvreader)
with open(ref_file, "r") as ref:
csvreader = csv.reader(ref, delimiter=",")
ref_list = list(csvreader)
# Initialise Packet Lists
write_packet_list = []
read_packet_list = []
# Initialise Temporary Structures
temppacketstruct = InputPacketStruct()
tempblockstruct = InputBlockStruct()
# Put Write Data into Structs
for i in stim_list:
tempblockstruct.word_append(int(i[0],16))
# If Last Word in Block, Append to Packet and Reset Temporary block structure
if (int(i[1])):
temppacketstruct.block_append(tempblockstruct)
tempblockstruct = InputBlockStruct()
# If Last Block in Packet , Append Packet to Packet List and Reset Temp Packet
if (int(i[2])):
write_packet_list.append(temppacketstruct)
temppacketstruct = InputPacketStruct()
# Put Read Data into Structs
for i in ref_list:
tempblockstruct.word_append(int(i[0],16))
# If Last Word in Block, Append to Packet and Reset Temporary block structure
if (int(i[1])):
temppacketstruct.block_append(tempblockstruct)
tempblockstruct = InputBlockStruct()
# If Last Block in Packet , Append Packet to Packet List and Reset Temp Packet
if (int(i[2])):
read_packet_list.append(temppacketstruct)
temppacketstruct = InputPacketStruct()
# List of Ouptut Transactions
output_word_list = []
# Generate Address for Packet
for packet_num, write_packet in enumerate(write_packet_list):
# Calculate Number of Blocks in First Packet
num_blocks = len(write_packet.block_list)
# Each Write Block Can Contain 16 32-bit Words (512 bits) (0x4 * 16 = 0x40)
# - Work Out Required Size = (0x40 * NumBlocks)
# - Work Out Beginning Address = (end_address + 0x4) - Size
req_write_size = 0x40 * num_blocks
start_write_addr = input_start_address + input_size - req_write_size
# Each Read Block Contains 8 32-bit Words (256 bits) (0x4 * 8 = 0x20)
req_read_size = 0x20
start_read_addr = output_start_address + output_size - req_read_size
# print(f"Packet: {int(packet_num)} | Start Address: {hex(start_write_addr)}")
write_addr = start_write_addr
read_addr = start_read_addr
# Write out Packet containing multiple 512 bit Blocks to Input Port
for block_num, block in enumerate(write_packet.block_list):
for word in block.word_list:
word_data = WordStruct(word, write_addr, TransactionType.WRITE, packet_num, block_num)
output_word_list.append(word_data)
# Increment Address
write_addr += 0x4
# Set Read Packet
read_packet = read_packet_list[packet_num]
# Read Back 256 Bit Packet from Output Port
for block_num, block in enumerate(read_packet.block_list):
for word in block.word_list:
word_data = WordStruct(word, read_addr, TransactionType.READ, packet_num, 0)
output_word_list.append(word_data)
# Increment Address
read_addr += 0x4
# Generate ADP Command File with Write Transactions
adp_file = os.environ["PROJECT_DIR"] + "/system/stimulus/" + "adp_hash_stim.cmd"
adp_output(adp_file, output_word_list)
# Generate FRI File with Write Transactions
fri_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "ahb_input_hash_stim.fri"
fri_output(fri_file, output_word_list)
# Call fm2conv.pl script
m2d_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "ahb_input_hash_stim.m2d"
os.system(f"fm2conv.pl -busWidth=32 -infile={fri_file} -outfile={m2d_file}")
if __name__ == "__main__":
accelerator_input_address = 0x6001_0000
accelerator_input_size = 0x0000_0800
accelerator_output_address = 0x6001_0800
accelerator_output_size = 0x0000_0800
stim_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "input_block_32bit_stim.csv"
ref_file = os.environ["PROJECT_DIR"] + "/wrapper/stimulus/" + "output_hash_32bit_ref.csv"
stimulus_generation(stim_file, ref_file, accelerator_input_address, accelerator_input_size, accelerator_output_address, accelerator_output_size)
\ No newline at end of file
......@@ -13,21 +13,21 @@ module wrapper_ahb_packet_constructor #(
parameter ADDRWIDTH=11,
parameter PACKETWIDTH=512
)(
input logic hclk, // clock
input logic hresetn, // reset
// AHB Input Port
input logic hsels,
input logic [ADDRWIDTH-1:0] haddrs,
input logic [1:0] htranss,
input logic [2:0] hsizes,
input logic hwrites,
input logic hreadys,
input logic [31:0] hwdatas,
output logic hreadyouts,
output logic hresps,
output logic [31:0] hrdatas,
input logic hclk, // clock
input logic hresetn, // reset
// AHB Input Port
input logic hsels,
input logic [ADDRWIDTH-1:0] haddrs,
input logic [1:0] htranss,
input logic [2:0] hsizes,
input logic hwrites,
input logic hreadys,
input logic [31:0] hwdatas,
output logic hreadyouts,
output logic hresps,
output logic [31:0] hrdatas,
// Valid/Ready Output Port
output logic [PACKETWIDTH-1:0] packet_data,
......
//-----------------------------------------------------------------------------
// SoC Labs DMAC Request Controller
// - Adapted from ARM AHB-lite example slave interface module.
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2023, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Abstract : Looks for last word address of packet during address phase
// to de-assert accelerator ready signal.
//-----------------------------------------------------------------------------
module wrapper_dmac_req #(
parameter ADDRWIDTH=11,
parameter DATAWIDTH=32
)(
input logic hclk, // clock
input logic hresetn, // reset
// Request Channel 0
input logic data_req_active_0,
input logic data_req_en_0,
output logic data_req_0,
// Request Channel 1
input logic data_req_active_1,
input logic data_req_en_1,
output logic data_req_1,
// Request Channel 2
input logic data_req_active_2,
input logic data_req_en_2,
output logic data_req_2,
// Request Channel 3
input logic data_req_active_3,
input logic data_req_en_3,
output logic data_req_3,
// Request Channel 4
input logic data_req_active_4,
input logic data_req_en_4,
output logic data_req_4
);
assign data_req_0 = data_req_active_0 & data_req_en_0;
assign data_req_1 = data_req_active_1 & data_req_en_1;
assign data_req_2 = data_req_active_2 & data_req_en_2;
assign data_req_3 = data_req_active_3 & data_req_en_3;
assign data_req_4 = data_req_active_4 & data_req_en_4;
endmodule
\ No newline at end of file
//-----------------------------------------------------------------------------
// SoC Labs Interrupt and DMA Control Registers
// - Adapted from ARM AHB-lite example slave interface module.
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2023, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module wrapper_req_ctrl_reg #(
// parameter for address width
parameter ADDRWIDTH = 12,
parameter DATAWIDTH = 32
) (
input logic hclk, // clock
input logic hresetn, // reset
// Register interface
input logic [ADDRWIDTH-1:0] addr,
input logic read_en,
input logic write_en,
input logic [DATAWIDTH-1:0] wdata,
output logic [DATAWIDTH-1:0] rdata,
// Request Active from I/O constructors
input logic req_act_ch0,
input logic req_act_ch1,
input logic req_act_ch2,
input logic req_act_ch3,
input logic req_act_ch4,
// DMA Output Request Signals
output logic drq_ch0,
output logic drq_ch1,
output logic drq_ch2,
output logic drq_ch3,
output logic drq_ch4,
// Interrupt Output Request Signals
output logic irq_ch0,
output logic irq_ch1,
output logic irq_ch2,
output logic irq_ch3,
output logic irq_ch4,
output logic irq_merged
);
localparam REQ_ACT_REG_WIDTH = 5;
localparam REQ_ACT_BIT_MAX = (REQ_ACT_REG_WIDTH-1);
localparam DREQ_EN_REG_WIDTH = 5;
localparam DREQ_EN_BIT_MAX = (DREQ_EN_REG_WIDTH-1);
localparam ADDR_DREQ_EN = 'h000;
localparam ADDR_DREQ_EN_SET = 'h004;
localparam ADDR_DREQ_EN_CLR = 'h008;
localparam ADDR_REQ_ACT = 'h010;
localparam DREQ_EN_CH0_BIT = 0;
localparam DREQ_EN_CH1_BIT = 1;
localparam DREQ_EN_CH2_BIT = 2;
localparam DREQ_EN_CH3_BIT = 3;
localparam DREQ_EN_CH4_BIT = 4;
localparam DREQ_ACT_CH0_BIT = 0;
localparam DREQ_ACT_CH1_BIT = 1;
localparam DREQ_ACT_CH2_BIT = 2;
localparam DREQ_ACT_CH3_BIT = 3;
localparam DREQ_ACT_CH4_BIT = 4;
logic [DREQ_EN_BIT_MAX:0] drq_en;
logic [REQ_ACT_BIT_MAX:0] req_act;
// Register Declaration
assign req_act = {req_act_ch4,req_act_ch3,req_act_ch2,req_act_ch1,req_act_ch0};
// Write Logic
always_ff @(posedge hclk or negedge hresetn) begin
if (!hresetn) begin
drq_en <= {DREQ_EN_REG_WIDTH{1'b0}};
end else begin
if (write_en) begin
case (addr)
// Set appropriate DMAC Request Register
ADDR_DREQ_EN: drq_en <= wdata[DREQ_EN_BIT_MAX:0];
ADDR_DREQ_EN_SET: drq_en <= drq_en | wdata[DREQ_EN_BIT_MAX:0];
ADDR_DREQ_EN_CLR: drq_en <= drq_en & wdata[DREQ_EN_BIT_MAX:0];
default: ;
endcase
end
end
end
// Read Logic
always_comb begin
rdata = 32'h0bad0bad;
if (read_en) begin
case (addr)
ADDR_DREQ_EN: rdata = {{(32-DREQ_EN_REG_WIDTH){1'b0}}, drq_en[DREQ_EN_BIT_MAX:0]};
ADDR_REQ_ACT: rdata = {{(32-REQ_ACT_REG_WIDTH){1'b0}}, req_act[REQ_ACT_BIT_MAX:0]};
default: rdata = 32'h0bad0bad;
endcase
end
end
// DMA Request Output Assignment
assign drq_ch0 = req_act[0] & drq_en[0];
assign drq_ch1 = req_act[1] & drq_en[1];
assign drq_ch2 = req_act[2] & drq_en[2];
assign drq_ch3 = req_act[3] & drq_en[3];
assign drq_ch4 = req_act[4] & drq_en[4];
// Interrupt Request Output Assignment
assign irq_ch0 = req_act[0] & !drq_en[0];
assign irq_ch1 = req_act[1] & !drq_en[1];
assign irq_ch2 = req_act[2] & !drq_en[2];
assign irq_ch3 = req_act[3] & !drq_en[3];
assign irq_ch4 = req_act[4] & !drq_en[4];
assign irq_merged = irq_ch0 | irq_ch1 | irq_ch2 | irq_ch3 | irq_ch4;
endmodule
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment