diff --git a/flow/stimgen.py b/flow/stimgen.py deleted file mode 100644 index 578df0b9f8bd9b49230656bfdd0a031311194790..0000000000000000000000000000000000000000 --- a/flow/stimgen.py +++ /dev/null @@ -1,210 +0,0 @@ -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 diff --git a/hdl/src/wrapper_ahb_packet_constructor.sv b/hdl/src/wrapper_ahb_packet_constructor.sv index 47546ac47491696915abb4660701471e950c5d9a..e6f877a2ffe20c336ea5a93d72f5fcf7953a3139 100644 --- a/hdl/src/wrapper_ahb_packet_constructor.sv +++ b/hdl/src/wrapper_ahb_packet_constructor.sv @@ -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, diff --git a/hdl/src/wrapper_dmac_req.sv b/hdl/src/wrapper_dmac_req.sv new file mode 100644 index 0000000000000000000000000000000000000000..ee9be3953dc86c407dbc7b3a51bff4dc71838414 --- /dev/null +++ b/hdl/src/wrapper_dmac_req.sv @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// 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 diff --git a/hdl/src/wrapper_req_ctrl_reg.sv b/hdl/src/wrapper_req_ctrl_reg.sv new file mode 100644 index 0000000000000000000000000000000000000000..6e8ce367cade6463b0f2e4673d24acf1e7e900e3 --- /dev/null +++ b/hdl/src/wrapper_req_ctrl_reg.sv @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------- +// 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