Vortex 2.0 changes:
+ Microarchitecture optimizations + 64-bit support + Xilinx FPGA support + LLVM-16 support + Refactoring and quality control fixes
This commit is contained in:
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module VX_tb_divide();
|
||||
@@ -17,7 +30,7 @@ module VX_tb_divide();
|
||||
|
||||
wire [31:0] o_div[0:7], o_rem[0:7];
|
||||
|
||||
for (genvar i = 0; i < 8; i++) begin
|
||||
for (genvar i = 0; i < 8; ++i) begin
|
||||
VX_divide#(
|
||||
.WIDTHN(32),
|
||||
.WIDTHD(32),
|
||||
|
||||
6
hw/unit_tests/cache/Makefile
vendored
6
hw/unit_tests/cache/Makefile
vendored
@@ -1,4 +1,6 @@
|
||||
PARAMS += -DCACHE_SIZE=4096 -DCACHE_WORD_SIZE=4 -DCACHE_LINE_SIZE=16 -DCACHE_NUM_BANKS=4 -DCACHE_CREQ_SIZE=4 -DMRVQ_SIZE=16 -DDFPQ_SIZE=16 -DSNRQ_SIZE=16 -DCWBQ_SIZE=4 -DDWBQ_SIZE=4 -DFQQ_SIZE=4
|
||||
PARAMS += -DCACHE_SIZE=4096 -DCACHE_WORD_SIZE=4 -DCACHE_LINE_SIZE=16 -DCACHE_NUM_BANKS=4 -DMRVQ_SIZE=16 -DDFPQ_SIZE=16 -DSNRQ_SIZE=16 -DCWBQ_SIZE=4 -DDWBQ_SIZE=4 -DFQQ_SIZE=4
|
||||
|
||||
TOP = VX_cache
|
||||
|
||||
# control RTL debug tracing states
|
||||
DBG_TRACE_FLAGS = -DDBG_TRACE_CORE_PIPELINE \
|
||||
@@ -31,7 +33,7 @@ VF += -exe $(SRCS) $(INCLUDE)
|
||||
VF += $(PARAMS)
|
||||
|
||||
gen:
|
||||
verilator $(VF) -cc $(TOP).v -CFLAGS '$(CF)' --exe $(SRCS)
|
||||
verilator $(VF) -cc $(TOP).sv -CFLAGS '$(CF)' --exe $(SRCS)
|
||||
|
||||
build: gen
|
||||
(cd obj_dir && make -j -f V$(TOP).mk)
|
||||
|
||||
15
hw/unit_tests/cache/cachesim.cpp
vendored
15
hw/unit_tests/cache/cachesim.cpp
vendored
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "cachesim.h"
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
@@ -235,7 +248,7 @@ void CacheSim::eval_mem_bus() {
|
||||
if (cache_->mem_req_valid) {
|
||||
if (cache_->mem_req_rw) { //write = 1
|
||||
uint64_t byteen = cache_->mem_req_byteen;
|
||||
unsigned base_addr = (cache_->mem_req_addr * MEM_BLOCK_SIZE);
|
||||
uint64_t base_addr = (cache_->mem_req_addr * MEM_BLOCK_SIZE);
|
||||
uint8_t* data = (uint8_t*)(cache_->mem_req_data);
|
||||
for (int i = 0; i < MEM_BLOCK_SIZE; i++) {
|
||||
if ((byteen >> i) & 0x1) {
|
||||
|
||||
13
hw/unit_tests/cache/cachesim.h
vendored
13
hw/unit_tests/cache/cachesim.h
vendored
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VVX_cache.h"
|
||||
|
||||
13
hw/unit_tests/cache/ram.h
vendored
13
hw/unit_tests/cache/ram.h
vendored
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
13
hw/unit_tests/cache/testbench.cpp
vendored
13
hw/unit_tests/cache/testbench.cpp
vendored
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "cachesim.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
0
hw/unit_tests/cache2/Makefile
Normal file
0
hw/unit_tests/cache2/Makefile
Normal file
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "vl_simulator.h"
|
||||
#include "VVX_fifo_queue.h"
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
`timescale 1ns/1ns
|
||||
`include "VX_fifo_queue.v"
|
||||
|
||||
@@ -15,8 +28,8 @@ module testbench();
|
||||
wire empty;
|
||||
|
||||
VX_fifo_queue #(
|
||||
.DATAW(4),
|
||||
.SIZE(4)
|
||||
.DATAW (4),
|
||||
.DEPTH (4)
|
||||
) dut (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
65
hw/unit_tests/mem_streamer/mem_streamer/Makefile
Normal file
65
hw/unit_tests/mem_streamer/mem_streamer/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
#---------------------------------------------------------
|
||||
# Makefile to compile and test the memory stream unit
|
||||
#---------------------------------------------------------
|
||||
|
||||
TOP = VX_mem_scheduler
|
||||
PARAMS += -GNUM_REQS=4 -GADDRW=8 -GDATAW=8 -GTAGW=8 -GWORD_SIZE=1 -GQUEUE_SIZE=4
|
||||
|
||||
ifdef RSP_PARTIAL
|
||||
PARAMS += -GRSP_PARTIAL=$(RSP_PARTIAL)
|
||||
endif
|
||||
|
||||
ifdef DUPLICATE_ADDR
|
||||
PARAMS += -GDUPLICATE_ADDR=$(DUPLICATE_ADDR)
|
||||
endif
|
||||
|
||||
RTL_DIR = ../../../rtl
|
||||
DPI_DIR = ../../../dpi
|
||||
|
||||
RTL_INCLUDE = -I$(RTL_DIR) -I$(RTL_DIR)/libs -I$(DPI_DIR)
|
||||
|
||||
VERILATOR_ROOT = /opt/verilator
|
||||
VERILATOR ?= $(VERILATOR_ROOT)/bin/verilator
|
||||
|
||||
VL_FLAGS += --exe --cc $(TOP).sv --top-module $(TOP)
|
||||
VL_FLAGS += --language 1800-2009 --assert -Wall
|
||||
VL_FLAGS += -Wno-DECLFILENAME -Wno-REDEFMACRO
|
||||
VL_FLAGS += --x-initial unique --x-assign unique
|
||||
VL_FLAGS += --trace
|
||||
VL_FLAGS += $(RTL_INCLUDE)
|
||||
VL_FLAGS += $(PARAMS)
|
||||
|
||||
SRCS += memsim.cpp ram.cpp $(DPI_DIR)/util_dpi.cpp
|
||||
|
||||
CXXFLAGS += -std=c++11 -Wall -Wextra -Wfatal-errors -Wno-array-bounds -Wno-maybe-uninitialized
|
||||
CXXFLAGS += -I../../../../dpi -I../../../../
|
||||
|
||||
default: run
|
||||
|
||||
gen: $(SRCS)
|
||||
@echo
|
||||
@echo "### VERILATE ###"
|
||||
$(VERILATOR) $(VL_FLAGS) $^ -CFLAGS '$(CXXFLAGS)'
|
||||
|
||||
build: gen
|
||||
@echo
|
||||
@echo "### BUILD ###"
|
||||
$(MAKE) -C obj_dir -j 4 -f V$(TOP).mk
|
||||
|
||||
run: build
|
||||
@echo
|
||||
@echo "### RUN ###"
|
||||
obj_dir/V$(TOP)
|
||||
|
||||
waves: trace.vcd
|
||||
@echo
|
||||
@echo "### TRACE ###"
|
||||
gtkwave -o trace.vcd
|
||||
|
||||
clean:
|
||||
@echo
|
||||
@echo "### CLEAN ###"
|
||||
-rm -rf obj_dir *.vcd *.log
|
||||
|
||||
#---------------------------------------------------------
|
||||
|
||||
176
hw/unit_tests/mem_streamer/mem_streamer/memsim.cpp
Normal file
176
hw/unit_tests/mem_streamer/mem_streamer/memsim.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <random>
|
||||
#include "memsim.h"
|
||||
#include "ram.h"
|
||||
|
||||
static bool trace_enabled = false;
|
||||
static uint64_t trace_start_time = 0;
|
||||
static uint64_t trace_stop_time = -1ull;
|
||||
static uint64_t timestamp = 0;
|
||||
|
||||
double sc_time_stamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
bool sim_trace_enabled() {
|
||||
if (timestamp >= trace_start_time
|
||||
&& timestamp < trace_stop_time)
|
||||
return true;
|
||||
return trace_enabled;
|
||||
}
|
||||
|
||||
void sim_trace_enable (bool enable) {
|
||||
trace_enabled = enable;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
int generate_rand (int min, int max) {
|
||||
int range = max - min + 1;
|
||||
return rand() % range + min;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
int generate_rand_mask (int mask) {
|
||||
int result = 0;
|
||||
int m = mask;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int bit = m & 0b1;
|
||||
int rand_bit = generate_rand (0, bit);
|
||||
result |= (rand_bit << i);
|
||||
m = m >> 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
MemSim::MemSim() {
|
||||
msu_ = new VVX_mem_streamer();
|
||||
|
||||
// Enable tracing
|
||||
Verilated::traceEverOn(true);
|
||||
trace_ = new VerilatedVcdC;
|
||||
msu_->trace(trace_, 99);
|
||||
trace_->open("trace.vcd");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
MemSim::~MemSim() {
|
||||
trace_->close();
|
||||
delete msu_;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void MemSim::eval() {
|
||||
msu_->eval();
|
||||
trace_->dump(timestamp++);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void MemSim::step() {
|
||||
msu_->clk = 0;
|
||||
this->eval();
|
||||
|
||||
msu_->clk = 1;
|
||||
this->eval();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void MemSim::reset() {
|
||||
msu_->reset = 1;
|
||||
this->step();
|
||||
|
||||
msu_->reset = 0;
|
||||
this->step();
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void MemSim::attach_core() {
|
||||
if (msu_->req_ready) {
|
||||
msu_->req_valid = generate_rand(0, 1);
|
||||
msu_->req_rw = generate_rand(0, 1);
|
||||
msu_->req_mask = generate_rand(0b0001, 0b1111);
|
||||
msu_->req_byteen = 0b1;
|
||||
msu_->req_addr = generate_rand(0, 0x10000000);
|
||||
msu_->req_data = generate_rand(0x60000000, 0x80000000);
|
||||
msu_->req_tag = generate_rand(0x00, 0xFF);
|
||||
}
|
||||
msu_->rsp_ready = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void MemSim::attach_ram (RAM *ram) {
|
||||
|
||||
req_t req;
|
||||
req.valid = msu_->mem_req_valid;
|
||||
req.rw = msu_->mem_req_rw;
|
||||
req.byteen = msu_->mem_req_byteen;
|
||||
req.addr = msu_->mem_req_addr;
|
||||
req.data = msu_->mem_req_data;
|
||||
req.tag = msu_->mem_req_tag;
|
||||
msu_->mem_req_ready = ram->is_ready();
|
||||
|
||||
ram->insert_req(req);
|
||||
|
||||
rsp_t rsp;
|
||||
rsp = ram->schedule_rsp();
|
||||
|
||||
msu_->mem_rsp_valid = rsp.valid;
|
||||
msu_->mem_rsp_mask = rsp.mask;
|
||||
msu_->mem_rsp_data = rsp.data;
|
||||
msu_->mem_rsp_tag = rsp.tag;
|
||||
rsp.ready = msu_->mem_rsp_ready;
|
||||
std::cout<<"MEMSIM: mem_rsp_ready: "<<rsp.ready<<"\n";
|
||||
|
||||
ram->halt_rsp(rsp);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void MemSim::run(RAM *ram) {
|
||||
this->reset();
|
||||
|
||||
while (sc_time_stamp() < SIM_TIME) {
|
||||
this->step();
|
||||
std::cout<<"========================="<<"\n";
|
||||
std::cout<<"Cycle: "<<sc_time_stamp()<<"\n";
|
||||
this->attach_core();
|
||||
this->attach_ram(ram);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
int main (int argc, char** argv, char** env) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
MemSim memsim;
|
||||
RAM ram;
|
||||
|
||||
memsim.run(&ram);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
47
hw/unit_tests/mem_streamer/mem_streamer/memsim.h
Normal file
47
hw/unit_tests/mem_streamer/mem_streamer/memsim.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <verilated.h>
|
||||
#include <verilated_vcd_c.h>
|
||||
#include "VVX_mem_streamer.h"
|
||||
#include "VVX_mem_streamer__Syms.h"
|
||||
#include "ram.h"
|
||||
|
||||
#define SIM_TIME 5000
|
||||
|
||||
int generate_rand (int min, int max);
|
||||
int generate_rand_mask (int mask);
|
||||
|
||||
class MemSim {
|
||||
private:
|
||||
VVX_mem_streamer *msu_;
|
||||
VerilatedVcdC *trace_;
|
||||
|
||||
void eval();
|
||||
void step();
|
||||
void reset();
|
||||
|
||||
void attach_core();
|
||||
void attach_ram(RAM *ram);
|
||||
|
||||
public:
|
||||
MemSim();
|
||||
virtual ~MemSim();
|
||||
|
||||
void run(RAM *ram);
|
||||
};
|
||||
137
hw/unit_tests/mem_streamer/mem_streamer/ram.cpp
Normal file
137
hw/unit_tests/mem_streamer/mem_streamer/ram.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ram.h"
|
||||
#include "memsim.h"
|
||||
|
||||
RAM::RAM() {
|
||||
|
||||
ram_.clear();
|
||||
is_rsp_active_ = false;
|
||||
is_rsp_stall_ = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
bool RAM::check_duplicate_req(req_t req) {
|
||||
for(int i = 0; i < ram_.size(); i++) {
|
||||
if (ram_[i].addr == req.addr) {
|
||||
std::cout<<"RAM: Duplicate entry. Do not insert..."<<std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
int RAM::simulate_cycle_delay() {
|
||||
|
||||
std::cout<<"RAM: # entries: "<<ram_.size()<<std::endl;
|
||||
|
||||
int dequeue_index = -1;
|
||||
|
||||
for (int i = 0; i < ram_.size(); i++) {
|
||||
if (!is_rsp_stall_) {
|
||||
if (ram_[i].cycles_left > 0) {
|
||||
ram_[i].cycles_left -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout<<"RAM: # cycles left: "<<ram_[i].cycles_left<<std::endl;
|
||||
|
||||
if (ram_[i].cycles_left == 0) {
|
||||
dequeue_index = i;
|
||||
}
|
||||
}
|
||||
return dequeue_index;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
void RAM::insert_req(req_t req) {
|
||||
if ( !(this->check_duplicate_req(req)) && req.valid && !req.rw) {
|
||||
req_t r;
|
||||
r.valid = req.valid;
|
||||
r.rw = req.rw;
|
||||
r.byteen = req.byteen;
|
||||
r.addr = req.addr;
|
||||
r.data = req.data;
|
||||
r.tag = req.tag & 0b11;
|
||||
|
||||
// Store metadata
|
||||
r.cycles_left = MEM_LATENCY;
|
||||
|
||||
std::cout<<"RAM: Insert entry... "<<std::endl;
|
||||
std::cout<<"Write? : "<<req.rw<<std::endl;
|
||||
ram_.push_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
uint8_t RAM::is_ready() {
|
||||
// return generate_rand(0b1000, 0b1111);
|
||||
return 0b1111;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
rsp_t RAM::schedule_rsp() {
|
||||
rsp_t rsp;
|
||||
int dequeue_index = this->simulate_cycle_delay();
|
||||
|
||||
if (!is_rsp_active_) {
|
||||
if (dequeue_index != -1) {
|
||||
|
||||
std::cout<<"RAM: Scheduling response... "<<std::endl;
|
||||
|
||||
is_rsp_active_ = true;
|
||||
rsp.valid = 1;
|
||||
rsp.mask = generate_rand_mask(ram_[dequeue_index].valid);
|
||||
rsp.data = generate_rand(0x20000000, 0x30000000);
|
||||
rsp.tag = ram_[dequeue_index].tag;
|
||||
|
||||
std::cout<<std::hex;
|
||||
std::cout<<"RAM: Response mask: "<<+rsp.mask<<" | Required mask: "<<+ram_[dequeue_index].valid<<std::endl;
|
||||
|
||||
ram_[dequeue_index].rsp_sent_mask = rsp.mask;
|
||||
ram_[dequeue_index].valid = ram_[dequeue_index].valid & ~ram_[dequeue_index].rsp_sent_mask;
|
||||
|
||||
if (0 == ram_[dequeue_index].valid) {
|
||||
ram_.erase(ram_.begin() + dequeue_index);
|
||||
is_rsp_stall_ = false;
|
||||
std::cout<<"RAM: Clear entry... "<<std::endl;
|
||||
} else {
|
||||
is_rsp_stall_ = true;
|
||||
std::cout<<"RAM: Stall... "<<std::endl;
|
||||
}
|
||||
} else {
|
||||
rsp.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
return rsp;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// Schedule response for only one cycle
|
||||
void RAM::halt_rsp(rsp_t rsp) {
|
||||
if (is_rsp_active_ && rsp.valid && rsp.ready) {
|
||||
std::cout<<"RAM: Halt response..."<<std::endl;
|
||||
is_rsp_active_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
64
hw/unit_tests/mem_streamer/mem_streamer/ram.h
Normal file
64
hw/unit_tests/mem_streamer/mem_streamer/ram.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright © 2019-2023
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#define MEM_LATENCY 4
|
||||
|
||||
typedef struct {
|
||||
uint8_t valid;
|
||||
bool rw;
|
||||
uint8_t byteen;
|
||||
uint32_t addr;
|
||||
uint32_t data;
|
||||
uint8_t tag;
|
||||
uint8_t ready;
|
||||
|
||||
// Metadata
|
||||
uint8_t rsp_sent_mask;
|
||||
double cycles_left;
|
||||
} req_t;
|
||||
|
||||
typedef struct {
|
||||
bool valid;
|
||||
uint8_t mask;
|
||||
uint32_t data;
|
||||
uint8_t tag;
|
||||
bool ready;
|
||||
} rsp_t;
|
||||
|
||||
class RAM {
|
||||
|
||||
private:
|
||||
std::vector<req_t> ram_;
|
||||
|
||||
bool is_rsp_active_;
|
||||
bool is_rsp_stall_;
|
||||
|
||||
bool check_duplicate_req(req_t req);
|
||||
int simulate_cycle_delay();
|
||||
|
||||
public:
|
||||
RAM();
|
||||
|
||||
uint8_t is_ready();
|
||||
void insert_req(req_t req);
|
||||
rsp_t schedule_rsp();
|
||||
void halt_rsp(rsp_t rsp);
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
@@ -1,30 +0,0 @@
|
||||
TOP = VX_tex_sampler
|
||||
|
||||
PARAMS ?=
|
||||
|
||||
INCLUDE = -I../../../rtl/ -I../../../rtl/libs -I../../../rtl/tex_unit
|
||||
|
||||
SRCS = main.cpp
|
||||
|
||||
all: build
|
||||
|
||||
CF += -std=c++11 -fms-extensions -I../..
|
||||
VF += $(PARAMS)
|
||||
|
||||
VF += --language 1800-2009 --assert -Wall --trace
|
||||
VF += -Wno-DECLFILENAME
|
||||
VF += --x-initial unique
|
||||
VF += -exe $(SRCS) $(INCLUDE)
|
||||
VF += $(PARAMS)
|
||||
|
||||
gen:
|
||||
verilator $(VF) -cc $(TOP).v -CFLAGS '$(CF)' --exe $(SRCS)
|
||||
|
||||
build: gen
|
||||
(cd obj_dir && make -j -f V$(TOP).mk)
|
||||
|
||||
run: build
|
||||
(cd obj_dir && ./V$(TOP))
|
||||
|
||||
clean:
|
||||
rm -rf obj_dir
|
||||
@@ -1,215 +0,0 @@
|
||||
#include "vl_simulator.h"
|
||||
#include "VVX_tex_sampler.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#define MAX_TICKS 20
|
||||
#define MAX_UNIT_CYCLES 5
|
||||
#define NUM_THREADS
|
||||
|
||||
#define CHECK(x) \
|
||||
do { \
|
||||
if (x) \
|
||||
break; \
|
||||
std::cout << "FAILED: " << #x << std::endl; \
|
||||
std::abort(); \
|
||||
} while (false)
|
||||
|
||||
uint64_t ticks = 0;
|
||||
|
||||
// using Device = VVX_tex_sampler;
|
||||
|
||||
template <typename T>
|
||||
class testbench
|
||||
{
|
||||
private:
|
||||
vl_simulator<T> sim;
|
||||
std::map<int, struct Input> input_map;
|
||||
std::map<int, struct Output> output_map;
|
||||
|
||||
public:
|
||||
|
||||
struct UnitTest {
|
||||
bool use_reset;
|
||||
unsigned int num_cycles;
|
||||
bool use_cmodel;
|
||||
struct Output outputs[MAX_UNIT_CYCLES];
|
||||
struct Input inputs[MAX_UNIT_CYCLES];
|
||||
unsigned int num_output_check;
|
||||
unsigned int check_output_cycle[MAX_UNIT_CYCLES];
|
||||
}
|
||||
|
||||
struct Input {
|
||||
bool req_valid;
|
||||
unsigned int req_wid;
|
||||
unsigned int req_tmask;
|
||||
unsigned int req_PC;
|
||||
unsigned int req_rd;
|
||||
unsigned int req_wb;
|
||||
unsigned int req_filter;
|
||||
unsigned int req_format;
|
||||
unsigned int req_u[NUM_THREADS];
|
||||
unsigned int req_v[NUM_THREADS];
|
||||
unsigned int req_texels[NUM_THREADS][4];
|
||||
bool rsp_ready;
|
||||
}
|
||||
|
||||
struct Output {
|
||||
int output_cycle;
|
||||
// outputs
|
||||
bool req_ready;
|
||||
bool rsp_valid;
|
||||
unsigned int rsp_wid;
|
||||
unsigned int rsp_tmask;
|
||||
unsigned int rsp_PC;
|
||||
unsigned int rsp_rd;
|
||||
bool rsp_wb;
|
||||
unsigned int rsp_data[NUM_THREADS];
|
||||
}
|
||||
|
||||
testbench(/* args */){
|
||||
|
||||
}
|
||||
|
||||
~testbench(){
|
||||
}
|
||||
|
||||
void unittest_Cmodel(struct UnitTest * test){
|
||||
int cycles = test->num_cycles;
|
||||
int num_outputs = test->num_output_check;
|
||||
|
||||
// struct Input* inputs = new (struct Input)[cycles];
|
||||
struct Output* outputs = new (struct Output)[num_outputs];
|
||||
|
||||
// implement c model and assign outputs to struct
|
||||
|
||||
if (test->inputs[0]->req_filter == 0){
|
||||
for (int i = 0; i < NUM_THREADS; i++)
|
||||
outputs[0]->rsp_data[0] = test->inputs->req_texels[i][0];
|
||||
} else {
|
||||
// for (int i = 0; i < NUM_THREADS; i++){
|
||||
// uint32_t low[4], high[4];
|
||||
// for (int j = 0; j < 4; j++){
|
||||
// low[j] = test->inputs->req_texels[i][j] & 0x00ff00ff;
|
||||
// high[j] = (test->inputs->req_texels[i][j] >> 8) & 0x00ff00ff;
|
||||
// }
|
||||
|
||||
// }
|
||||
}
|
||||
outputs[0]->output_cycle = 1;
|
||||
test->num_cycles = 1;
|
||||
test->outputs = &outputs;
|
||||
|
||||
}
|
||||
|
||||
void generate_test_vectors(struct UnitTest * tests, int num_tests, bool is_pipe){
|
||||
// for all unit tests create output test vectors (w w/o c-model)
|
||||
int prev_test_cycle = 0;
|
||||
|
||||
for (int i = 0; i < num_tests; i++)
|
||||
{
|
||||
int op_counter = 0;
|
||||
int ip_counter = 0;
|
||||
|
||||
int test_cycle = 0;
|
||||
int last_ip_cycle = 0;
|
||||
|
||||
struct UnitTest curr_test = tests[i];
|
||||
|
||||
if (curr_test->use_cmodel){
|
||||
unittest_Cmodel(&curr_test);
|
||||
}
|
||||
|
||||
for (int j = 0; j < curr_test->num_cycles; j++)
|
||||
{
|
||||
if (curr_test->inputs[ip_counter]->input_cycle == test_cycle){
|
||||
input_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->inputs[j]));
|
||||
last_ip_cycle = prev_test_cycle + test_cycle;
|
||||
ip_counter++;
|
||||
}
|
||||
|
||||
if (curr_test->outputs[op_counter]->output_cycle == test_cycle){
|
||||
output_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->outputs[op_counter]));
|
||||
op_counter++;
|
||||
}
|
||||
|
||||
test_cycle++;
|
||||
}
|
||||
|
||||
if(!is_pipe){
|
||||
prev_test_cycle += (test_cycle - 1);
|
||||
}
|
||||
else{
|
||||
prev_test_cycle = last_ip_cycle + 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void run(){
|
||||
|
||||
ticks = sim.reset(0);
|
||||
int cycle = 0;
|
||||
|
||||
while (ticks < MAX_TICKS) {
|
||||
|
||||
auto input = input_map.find(cycle);
|
||||
auto output = output_map.find(cycle);
|
||||
|
||||
if (input != input_map.end()){
|
||||
sim->req_valid = input->req_valid;
|
||||
sim->req_wid = input->req_wid;
|
||||
sim->req_tmask = input->req_tmask;
|
||||
sim->req_PC = input->req_PC;
|
||||
sim->req_rd = input->req_rd;
|
||||
sim->req_wb = input->req_wb;
|
||||
sim->req_filter = input->req_filter;
|
||||
sim->req_format = input->req_format;
|
||||
// sim->req_u = input->req_u[NUM_THREADS];
|
||||
// sim->req_v = input->req_v[NUM_THREADS];
|
||||
vl_setw(sim->req_texels, input->req_texels)
|
||||
// sim->req_texels = input->req_texels[NUM_THREADS][4];
|
||||
sim->rsp_ready = input->rsp_ready;
|
||||
} else{
|
||||
std::cout << "Warning! No Input on Cycle " << cycle << std::endl;
|
||||
}
|
||||
|
||||
if(output != output_map.end()){
|
||||
CHECK(sim->req_ready == output->req_ready);
|
||||
CHECK(sim->rsp_valid == output->rsp_valid);
|
||||
CHECK(sim->rsp_wid == output->rsp_wid);
|
||||
CHECK(sim->rsp_tmask == output->rsp_tmask);
|
||||
CHECK(sim->rsp_PC == output->rsp_PC);
|
||||
CHECK(sim->rsp_rd == output->rsp_rd);
|
||||
CHECK(sim->rsp_wb == output->rsp_wb);
|
||||
CHECK(vl_cmpw(sim->rsp_data, output->rsp_data));
|
||||
}
|
||||
|
||||
cycle++;
|
||||
ticks = sim.step(ticks,2);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "PASSED!" << std::endl;
|
||||
std::cout << "Simulation time: " << std::dec << ticks/2 << " cycles" << std::endl;
|
||||
|
||||
};
|
||||
|
||||
|
||||
double sc_time_stamp() {
|
||||
return ticks;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Initialize Verilators variables
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
testbench<VVX_tex_sampler> sampler_testbench;
|
||||
|
||||
sampler_testbench.generate_test_vectors(tests, 1, 0);
|
||||
sampler_test_bench.run();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user