Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bsg_clk_gen_pearl testbench #3

Open
wants to merge 17 commits into
base: clk_gen_pearl
Choose a base branch
from
3 changes: 3 additions & 0 deletions bsg_clk_gen_pearl/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
basejump_stl/
bsg_cadenv/
*.pyc
35 changes: 35 additions & 0 deletions bsg_clk_gen_pearl/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
THIS_DIR :=$(realpath $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))

GIT_CLONE_STYLE :=ssh
#GIT_CLONE_STYLE :=https

ifeq ($(GIT_CLONE_STYLE),ssh)
GITHUB :[email protected]:

else ifeq ($(GIT_CLONE_STYLE),https)
GITHUB :=https://github.com/

endif

basejump_stl_dir :=$(THIS_DIR)/basejump_stl
basejump_stl_url :=$(GITHUB)bespoke-silicon-group/basejump_stl
basejump_stl_commit :=nonsynth_osc

bsg_cadenv_dir :=$(THIS_DIR)/bsg_cadenv
bsg_cadenv_url :=$(GITHUB)bespoke-silicon-group/bsg_cadenv
bsg_cadenv_commit :=master

all_repos = $(subst _url,.repo,$(filter %_url,$(.VARIABLES)))

all: $(all_repos)

%.repo:
-git clone $($*_url) $($*_dir)
-cd $($*_dir) ; git checkout $($*_commit)

clean: are_you_sure
rm -rf $(subst .repo,,$(all_repos))

DISABLE_SAFETY_PROMPT ?= false
are_you_sure:
@$(DISABLE_SAFETY_PROMPT) || (echo -n "Are you sure [Y/n]? " && read ans && ([ "$$ans" == "Y" ] || [ "$$ans" == "y" ]))
51 changes: 51 additions & 0 deletions bsg_clk_gen_pearl/tcl/filelist.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
### filelist.tcl

#-------------------------------------------------------------------------------
# Do NOT arbitrarily change the order of files. Some module and macro
# definitions may be needed by the subsequent files
#-------------------------------------------------------------------------------

set bsg_designs_target_dir $::env(BSG_DESIGNS_TARGET_DIR)
set basejump_stl_dir $::env(BASEJUMP_STL_DIR)

set SVERILOG_INCLUDE_PATHS [join "
$basejump_stl_dir/bsg_clk_gen
$basejump_stl_dir/bsg_misc
$basejump_stl_dir/bsg_tag
"]

set SVERILOG_PACKAGE_FILES [join "
$basejump_stl_dir/bsg_tag/bsg_tag_pkg.v
$bsg_designs_target_dir/bsg_clk_gen_pearl_pkg.v
"]

set SVERILOG_SOURCE_FILES [join "
$SVERILOG_PACKAGE_FILES
$basejump_stl_dir/bsg_async/bsg_launch_sync_sync.v
$basejump_stl_dir/bsg_async/bsg_sync_sync.v
$basejump_stl_dir/bsg_clk_gen/bsg_clk_gen.v
$basejump_stl_dir/bsg_clk_gen/bsg_clk_gen_osc.v
$basejump_stl_dir/bsg_misc/bsg_buf.v
$basejump_stl_dir/bsg_misc/bsg_counter_clock_downsample.v
$basejump_stl_dir/bsg_misc/bsg_dff.v
$basejump_stl_dir/bsg_misc/bsg_dff_en.v
$basejump_stl_dir/bsg_misc/bsg_dff_reset_en.v
$basejump_stl_dir/bsg_misc/bsg_dff_async_reset.v
$basejump_stl_dir/bsg_misc/bsg_mux.v
$basejump_stl_dir/bsg_misc/bsg_mux2_gatestack.v
$basejump_stl_dir/bsg_misc/bsg_muxi2_gatestack.v
$basejump_stl_dir/bsg_misc/bsg_nand.v
$basejump_stl_dir/bsg_misc/bsg_nor3.v
$basejump_stl_dir/bsg_misc/bsg_reduce.v
$basejump_stl_dir/bsg_misc/bsg_strobe.v
$basejump_stl_dir/bsg_misc/bsg_xnor.v
$basejump_stl_dir/bsg_misc/bsg_counter_clear_up.v
$basejump_stl_dir/bsg_tag/bsg_tag_master_decentralized.v
$basejump_stl_dir/bsg_tag/bsg_tag_client.v
$basejump_stl_dir/bsg_tag/bsg_tag_client_unsync.v
$bsg_designs_target_dir/bsg_clk_gen_pearl_lfsr_div30.v
$bsg_designs_target_dir/bsg_clk_gen_pearl_monitor_clk_buf.v
$bsg_designs_target_dir/bsg_clk_gen_pearl_monitor.v
$bsg_designs_target_dir/bsg_clk_gen_pearl.v
"]

7 changes: 7 additions & 0 deletions bsg_clk_gen_pearl/tcl/parameters.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
set TOPLEVEL_PARAMETERS [join "
toplevel_tag_els_p=6
toplevel_tag_max_payload_width_p=7
toplevel_tag_node_id_offset_p=0
toplevel_ds_width_p=6
toplevel_num_adgs_p=1
"]
18 changes: 18 additions & 0 deletions bsg_clk_gen_pearl/testing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Bsg_clk_gen_pearl Testbench User Guide

## Run RTL Simulation
```
cd bsg_clk_gen_pearl/testing/rtl
make
```
## Run RTL OSC Sweep
```
cd bsg_clk_gen_pearl/testing/clk_gen_sweep/rtl
make
```
## Use Testbench on ASIC
1. Update `bsg_clk_gen_pearl/tcl/filelist.tcl` and `bsg_clk_gen_pearl/tcl/parameters.tcl` accordingly
2. Create a new version of `bsg_clk_gen_pearl/testing/v/bsg_clk_gen_pearl_pcb.v`, in which the DUT ASIC should be attached to the testbench
*Note that the watch_clk bind pin should be up-to-date
3. Update `bsg_clk_gen_pearl/testing/tcl/filelist.tcl` accordingly
4. Update the following variables in `bsg_clk_gen_pearl/testing/rtl/Makefile`: `BSG_TOP_SIM_MODULE`, `BSG_CHIP_INSTANCE_PATH`, `BSG_OSC_BASE_DELAY` and `BSG_OSC_GRANULARITY`
2 changes: 2 additions & 0 deletions bsg_clk_gen_pearl/testing/clk_gen_sweep/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
results/
runs/
75 changes: 75 additions & 0 deletions bsg_clk_gen_pearl/testing/clk_gen_sweep/py/output_csv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

import sys, os, glob, re

#import matplotlib
#import matplotlib.pyplot as plt

data = {}

if len(sys.argv) == 2:
logpath = sys.argv[1]
filelist = glob.glob(os.path.join(logpath, '*.log'))
filelist.sort()
for file in filelist:
corner = os.path.basename(file).replace('.log', '')
print(corner+',', end='')
data[corner] = {"pos": [], "neg": []}
f = open(file, "r")
lines = f.readlines()
pos_list = []
neg_list = []
pos_line_num = 0
neg_line_num = 0
for line in lines:
pos_pattern = re.compile(".*POSEDGE.*[0-9]+\s+ps")
neg_pattern = re.compile(".*NEGEDGE.*[0-9]+\s+ps")
if neg_pattern.match(line):
line_num = int(line.split(':')[0])
# remove previous number if two lines are close to each other
# usually caused by smooth transition of osc
if line_num <= neg_line_num + 2:
neg_list.pop(-1)
neg_list.append(line.split()[-2])
neg_line_num = line_num
if pos_pattern.match(line):
line_num = int(line.split(':')[0])
if line_num <= pos_line_num + 2:
pos_list.pop(-1)
pos_list.append(line.split()[-2])
pos_line_num = line_num
# Print results
print('NEG,', end='')
for num in neg_list:
print(num+',', end='')
data[corner]["pos"].append(int(num))
print('\n,POS,', end='')
for num in pos_list:
print(num+',', end='')
data[corner]["neg"].append(int(num))
print('')

# for k,v in data.items():
# data[k]['per'] = []
# for p,n in zip(v['pos'], v['neg']):
# data[k]['per'].append(p + n)
# data[k]['duty'] = []
# for p,n in zip(v['pos'], v['per']):
# data[k]['duty'].append(p / n)
#
# fig = plt.figure()
# ax1 = fig.add_subplot(211)
# ax2 = fig.add_subplot(212)
# x_labels = [i for i in range(32)]
# ax1.title.set_text("DUTY CYCLE")
# for k,v in data.items():
# ax1.plot(x_labels, v['duty'], label=k)
# ax2.title.set_text("PERIOD")
# for k,v in data.items():
# ax2.plot(x_labels, v['per'], label=k)
# fig.savefig("graph.png")
# #plt.show()

else:
print("USAGE:")
command = "python output_csv.py {logpath}"
print(command)
40 changes: 40 additions & 0 deletions bsg_clk_gen_pearl/testing/clk_gen_sweep/rtl/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.DEFAULT_GOAL=run

export BSG_DESIGNS_DIR := $(abspath ../../../../)
export BSG_DESIGNS_TARGET_DIR := $(abspath ../../../)

CLK_GEN_SWEEP_RUN_DIR := $(abspath ./)
CLK_GEN_SWEEP_DIR := $(CLK_GEN_SWEEP_RUN_DIR)/../
SIMULATION_DIR := $(BSG_DESIGNS_TARGET_DIR)/testing/rtl

SWEEP_RUNS_DIR := $(CLK_GEN_SWEEP_RUN_DIR)/runs
SWEEP_RESULTS_DIR := $(CLK_GEN_SWEEP_RUN_DIR)/results

OUTPUT_CSV_PY := $(CLK_GEN_SWEEP_DIR)/py/output_csv.py
RESULT_CSV := $(SWEEP_RESULTS_DIR)/result.csv
PYTHON := python3

RUNS := run-rtl

run: $(RUNS)
$(PYTHON) $(OUTPUT_CSV_PY) $(SWEEP_RESULTS_DIR) > $(RESULT_CSV)

run-%: $(SWEEP_RUNS_DIR) $(SWEEP_RESULTS_DIR)
mkdir $(SWEEP_RUNS_DIR)/$*
cd $(SWEEP_RUNS_DIR)/$* \
&& ln -s $(SIMULATION_DIR)/* . \
&& make run \
&& make summarize_details > $(SWEEP_RESULTS_DIR)/$*.log

csv:
$(PYTHON) $(OUTPUT_CSV_PY) $(SWEEP_RESULTS_DIR) > $(RESULT_CSV)

$(SWEEP_RUNS_DIR):
mkdir -p $@

$(SWEEP_RESULTS_DIR):
mkdir -p $@

clean:
rm -rf $(SWEEP_RUNS_DIR)
rm -rf $(SWEEP_RESULTS_DIR)
89 changes: 89 additions & 0 deletions bsg_clk_gen_pearl/testing/py/bsg_tag_boot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import sys
import os

sys.path.append(os.environ.get("BSG_DESIGNS_TARGET_DIR")+"/testing/py")
from bsg_tag_trace_gen import *

# Client ID Mapping
# ===================
# 0 = async_reset
# 1 = osc
# 2 = osc trigger
# 3 = ds
# 4 = sel
# 5 = monitor_reset

if len(sys.argv) != 6:
print("USAGE:")
command = "python bsg_tag_boot.py {num_clients_p} {max_payload_width_p} {offset_p} {ds_width_p} {num_adgs_p}"
print(command)
sys.exit("Error: tag trace generation failed")

num_masters_p = 1
num_clients_p = int(sys.argv[1])
max_payload_width_p = int(sys.argv[2])
offset_p = int(sys.argv[3])
ds_width_p = int(sys.argv[4])
num_adgs_p = int(sys.argv[5])

osc_width_p = 2+2+num_adgs_p # fdt+cdt+adg
osc_max_val_p = pow(2, osc_width_p)-1
ds_tag_width_p = ds_width_p+1
ds_tag_max_val_p = pow(2, ds_tag_width_p)-1

# instantiate tag trace gen
tg = TagTraceGen(num_masters_p, num_clients_p, max_payload_width_p)

# reset all bsg_tag master
tg.send(masters=0, client_id=offset_p+0, data_not_reset=0, length=0, data=0)
tg.wait(32)

# reset each bsg_tag client
tg.send(masters=0, client_id=offset_p+0, data_not_reset=0, length=1, data=0b1) # async_reset
tg.send(masters=0, client_id=offset_p+1, data_not_reset=0, length=osc_width_p, data=osc_max_val_p) # osc
tg.send(masters=0, client_id=offset_p+2, data_not_reset=0, length=1, data=0b1) # osc trigger
tg.send(masters=0, client_id=offset_p+3, data_not_reset=0, length=ds_tag_width_p, data=ds_tag_max_val_p) # ds
tg.send(masters=0, client_id=offset_p+4, data_not_reset=0, length=2, data=0b11) # sel
tg.send(masters=0, client_id=offset_p+5, data_not_reset=0, length=1, data=0b1) # monitor_reset

# select zero output clk
tg.send(masters=0, client_id=offset_p+4, data_not_reset=1, length=2, data=0b11)

# reset oscillator and trigger flops
tg.send(masters=0, client_id=offset_p+0, data_not_reset=1, length=1, data=0b1)

# init trigger to low, init oscillator to zero
# OSC INIT VALUE MUST BE ZERO TO AVOID X IN SIMULATION
tg.send(masters=0, client_id=offset_p+2, data_not_reset=1, length=1, data=0b0)
tg.send(masters=0, client_id=offset_p+1, data_not_reset=1, length=osc_width_p, data=0)

# take oscillator and trigger flops out of reset
tg.send(masters=0, client_id=offset_p+0, data_not_reset=1, length=1, data=0b0)

# trigger oscillator value
tg.send(masters=0, client_id=offset_p+2, data_not_reset=1, length=1, data=0b1)
tg.send(masters=0, client_id=offset_p+2, data_not_reset=1, length=1, data=0b0)

# reset ds, then set ds value
tg.send(masters=0, client_id=offset_p+3, data_not_reset=1, length=ds_tag_width_p, data=1)
tg.send(masters=0, client_id=offset_p+3, data_not_reset=1, length=ds_tag_width_p, data=0)

# select ds output clk
tg.send(masters=0, client_id=offset_p+4, data_not_reset=1, length=2, data=0b01)

# sweep oscillator values
for tap in range(osc_max_val_p+1):
# set osc value
tg.send(masters=0, client_id=offset_p+1, data_not_reset=1, length=osc_width_p, data=tap)
# trigger osc value
tg.send(masters=0, client_id=offset_p+2, data_not_reset=1, length=1, data=0b1)
tg.send(masters=0, client_id=offset_p+2, data_not_reset=1, length=1, data=0b0)
# reset monitor
tg.send(masters=0, client_id=offset_p+5, data_not_reset=1, length=1, data=0b1)
tg.send(masters=0, client_id=offset_p+5, data_not_reset=1, length=1, data=0b0)
# wait
tg.wait(64)

# all done
tg.done()

61 changes: 61 additions & 0 deletions bsg_clk_gen_pearl/testing/py/bsg_tag_trace_gen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#
# bsg_tag_trace_gen.py
#

import math

SEND_OP = 0b0001
DONE_OP = 0b0011
COUNT_INIT_OP = 0b0110
COUNT_WAIT_OP = 0b0101

class TagTraceGen:

# Constructor
def __init__(self, num_masters_p, num_clients_p, max_payload_width_p):
self.num_masters_p = num_masters_p
self.num_clients_p = num_clients_p
self.max_payload_width_p = max_payload_width_p
self.client_id_width_lp = self.safe_clog2(num_clients_p)
self.length_width_lp = self.safe_clog2(max_payload_width_p+1)

# BSG_SAFE_CLOG2(x)
def safe_clog2(self, x):
if x == 1:
return 1
else:
return int(math.ceil(math.log(x,2)))

# Get binary string
def get_bin_str(self, val, width):
return format(val, "0" + str(width) + "b")

# Print trace.
def get_trace(self, opcode, masters, client_id, data_not_reset, length, data):
trace = self.get_bin_str(opcode, 4) + "_"
trace += self.get_bin_str(masters, self.num_masters_p) + "_"
trace += self.get_bin_str(client_id, self.client_id_width_lp) + "_"
trace += self.get_bin_str(data_not_reset, 1) + "_"
trace += self.get_bin_str(length, self.length_width_lp) + "_"
trace += self.get_bin_str(data, self.max_payload_width_p)
return trace

# Send trace
def send(self, masters, client_id, data_not_reset, length, data):
print(self.get_trace(SEND_OP, masters, client_id, data_not_reset, length, data))

# Wait cycles.
def wait(self, cycles):
count_width = self.num_masters_p + self.client_id_width_lp + 1 + self.length_width_lp + self.max_payload_width_p
trace = self.get_bin_str(COUNT_INIT_OP, 4) + "_"
trace += self.get_bin_str(cycles, count_width)
print(trace)
trace = self.get_bin_str(COUNT_WAIT_OP, 4) + "_"
trace += self.get_bin_str(0, count_width)
print(trace)

# done
def done(self):
trace = self.get_trace(DONE_OP, 0,0,0,0,0)
print(trace)

Loading