This commit is contained in:
Katherine Parry 2022-07-11 18:30:29 -07:00
commit ba339fc794
21 changed files with 357 additions and 335 deletions

View File

@ -7,34 +7,57 @@ sources=$(cmbase)/core_main.c $(cmbase)/core_list_join.c $(cmbase)/coremark.h \
$(cmbase)/core_matrix.c $(cmbase)/core_state.c $(cmbase)/core_util.c \ $(cmbase)/core_matrix.c $(cmbase)/core_state.c $(cmbase)/core_util.c \
$(PORT_DIR)/core_portme.h $(PORT_DIR)/core_portme.c $(PORT_DIR)/core_portme.mak \ $(PORT_DIR)/core_portme.h $(PORT_DIR)/core_portme.c $(PORT_DIR)/core_portme.mak \
$(PORT_DIR)/crt.S $(PORT_DIR)/encoding.h $(PORT_DIR)/util.h $(PORT_DIR)/syscalls.c $(PORT_DIR)/crt.S $(PORT_DIR)/encoding.h $(PORT_DIR)/util.h $(PORT_DIR)/syscalls.c
ABI = lp64 ABI := $(if $(findstring "64","$(XLEN)"),lp64,ilp32)
#$(if $(findstring 64, $(XLEN)), lp64, ilp32) ARCH := rv$(XLEN)im
PORT_CFLAGS = -g -march=$(XLEN)im -mabi=$(ABI) -static -mcmodel=medlow -mtune=sifive-3-series \ PORT_CFLAGS = -g -march=rv$(XLEN)im -mabi=$(ABI) -march=$(ARCH) -static -falign-functions=16 \
-O3 -falign-functions=16 -funroll-all-loops \ -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-3-series -O3 -funroll-all-loops -finline-functions -falign-jumps=4 \
-finline-functions -falign-jumps=4 \ -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 \
-funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta \
-nostdlib -nostartfiles -ffreestanding -mstrict-align \ -nostdlib -nostartfiles -ffreestanding -mstrict-align \
-DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \ -DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 -DPERFORMANCE_RUN=1 -DXLEN=$(XLEN)
-DPERFORMANCE_RUN=1
# flags that cause build errors mcmodel=medlow
# -static -mcmodel=medlow -mtune=sifive-7-series \
# -O3 -falign-functions=16 -funroll-all-loops -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET
# -finline-functions -falign-jumps=4 \
# -nostdlib -nostartfiles -ffreestanding -mstrict-align \
# -DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
# -DPERFORMANCE_RUN=1
# "-march=rv$(XLEN)im -mabi=$(ABI) -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "
all: $(work_dir)/coremark.bare.riscv.elf.memfile
run:
(cd ../../pipelined/regression && (time vsim -c -do "do wally-pipelined-batch.do rv$(XLEN)gc coremark" 2>&1 | tee $(work_dir)/coremark.sim.log))
cd ../../benchmarks/coremark/
$(work_dir)/coremark.bare.riscv.elf.memfile: $(work_dir)/coremark.bare.riscv $(work_dir)/coremark.bare.riscv.elf.memfile: $(work_dir)/coremark.bare.riscv
riscv64-unknown-elf-objdump -D $< > $<.elf.objdump riscv64-unknown-elf-objdump -D $< > $<.elf.objdump
riscv64-unknown-elf-elf2hex --bit-width $(XLEN) --input $< --output $@ riscv64-unknown-elf-elf2hex --bit-width $(XLEN) --input $< --output $@
extractFunctionRadix.sh $<.elf.objdump extractFunctionRadix.sh $<.elf.objdump
(cd ../../pipelined/regression && (vsim -c -do "do wally-pipelined-batch.do rv$(XLEN)gc coremark" 2>&1 | tee $(work_dir)/coremark.sim.log))
cd ../../benchmarks/coremark/
$(work_dir)/coremark.bare.riscv: $(sources) Makefile $(work_dir)/coremark.bare.riscv: $(sources) Makefile
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=/opt/riscv/riscv-gnu-toolchain XCFLAGS="-march=rv64imd -mabi=lp64d -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fno-toplevel-reorder --param=max-inline-insns-size=128 -fipa-pta"
# These flags were used by WD on CoreMark # These flags were used by WD on CoreMark
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="-march=rv64imd -mabi=lp64d -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta " make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="$(PORT_CFLAGS)"
make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="-march=rv$(XLEN)im -mabi=$(ABI) -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "
# -fno-toplevel-reorder --param=max-inline-insns-size=128 " # adding this bit caused a compiler error # -fno-toplevel-reorder --param=max-inline-insns-size=128 " # adding this bit caused a compiler error
mkdir -p $(work_dir) mkdir -p $(work_dir)
mv $(cmbase)/coremark.bare.riscv $(work_dir) mv $(cmbase)/coremark.bare.riscv $(work_dir)
.PHONY: clean .PHONY: clean
clean: clean:
rm -f $(work_dir)/* rm -f $(work_dir)/*
# # PORT_CFLAGS = -g -march=$(XLEN)im -mabi=$(ABI) -static -mcmodel=medlow -mtune=sifive-3-series \
# # -O3 -falign-functions=16 -funroll-all-loops \
# # -finline-functions -falign-jumps=4 \
# # -nostdlib -nostartfiles -ffreestanding -mstrict-align \
# # -DTOTAL_DATA_SIZE=2000 -DMAIN_HAS_NOARGC=1 \
# # -DPERFORMANCE_RUN=1
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="-march=rv$(XLEN)im -mabi=$(ABI) -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=/opt/riscv/riscv-gnu-toolchain XCFLAGS="-march=rv64imd -mabi=lp64d -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fno-toplevel-reorder --param=max-inline-insns-size=128 -fipa-pta"
# make -C $(cmbase) PORT_DIR=$(PORT_DIR) compile RISCV=$(RISCV)/riscv-gnu-toolchain XCFLAGS="-march=rv64imd -mabi=lp64d -mbranch-cost=1 -DSKIP_DEFAULT_MEMSET -mtune=sifive-7-series -Ofast -funroll-all-loops -fno-delete-null-pointer-checks -fno-rename-registers --param=loop-max-datarefs-for-datadeps=0 -funroll-all-loops --param=uninlined-function-insns=8 -fno-tree-vrp -fwrapv -fipa-pta "

View File

@ -196,10 +196,13 @@ void stop_time(void) {
CORE_TICKS get_time(void) { CORE_TICKS get_time(void) {
CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
unsigned long instructions = minstretDiff(); unsigned long instructions = minstretDiff();
ee_printf(" Called get_time\n"); long long cm100 = 1000000000 / elapsed; // coremark score * 100
long long cpi100 = elapsed*100/instructions; // CPI * 100
ee_printf(" WALLY CoreMark Results (from get_time)\n");
ee_printf(" Elapsed MTIME: %u\n", elapsed); ee_printf(" Elapsed MTIME: %u\n", elapsed);
ee_printf(" Elapsed MINSTRET: %lu\n", instructions); ee_printf(" Elapsed MINSTRET: %lu\n", instructions);
ee_printf(" CPI: %lu / %lu\n", elapsed, instructions); ee_printf(" COREMARK/MHz Score: 10,000,000 / %lu = %d.%02d \n", elapsed, cm100/100, cm100%100);
ee_printf(" CPI: %lu / %lu = %d.%02d\n", elapsed, instructions, cpi100/100, cpi100%100);
return elapsed; return elapsed;
} }
/* Function: time_in_secs /* Function: time_in_secs

View File

@ -66,6 +66,9 @@ typedef size_t CORE_TICKS;
#elif HAS_TIME_H #elif HAS_TIME_H
#include <time.h> #include <time.h>
typedef clock_t CORE_TICKS; typedef clock_t CORE_TICKS;
// #elif (XLEN==32)
// #include <sys/types.h>
// typedef ee_u32 CORE_TICKS;
#else #else
/* Configuration: size_t and clock_t /* Configuration: size_t and clock_t
Note these need to match the size of the clock output and the xLen the processor supports Note these need to match the size of the clock output and the xLen the processor supports
@ -105,11 +108,16 @@ typedef signed int ee_s32;
typedef double ee_f32; typedef double ee_f32;
typedef unsigned char ee_u8; typedef unsigned char ee_u8;
typedef unsigned int ee_u32; typedef unsigned int ee_u32;
#if (XLEN==64)
typedef unsigned long long ee_ptr_int; typedef unsigned long long ee_ptr_int;
#else
typedef ee_u32 ee_ptr_int;
#endif
typedef size_t ee_size_t; typedef size_t ee_size_t;
/* align an offset to point to a 32b value */ /* align an offset to point to a 32b value */
#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3)) #define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3))
/* Configuration: SEED_METHOD /* Configuration: SEED_METHOD
Defines method to get seed values that cannot be computed at compile time. Defines method to get seed values that cannot be computed at compile time.

View File

@ -33,13 +33,13 @@ CC = $(RISCVTOOLS)/bin/$(RISCVTYPE)-gcc
# Flag: CFLAGS # Flag: CFLAGS
# Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags" # Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
#PORT_CFLAGS = -O2 -static -std=gnu99 #PORT_CFLAGS = -O2 -static -std=gnu99
PORT_CFLAGS = -O2 -mcmodel=medany -static -fno-tree-loop-distribute-patterns -std=gnu99 -fno-common -nostartfiles -lm -lgcc -T $(PORT_DIR)/link.ld PORT_CFLAGS = -mcmodel=medany -fno-tree-loop-distribute-patterns -fno-common -lm -lgcc -T $(PORT_DIR)/link.ld
FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"
#Flag: LFLAGS_END #Flag: LFLAGS_END
# Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts). # Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
# Note: On certain platforms, the default clock_gettime implementation is supported but requires linking of librt. # Note: On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
LFLAGS_END += LFLAGS_END += -static-libgcc -lgcc
# Flag: PORT_SRCS # Flag: PORT_SRCS
# Port specific source files can be added here # Port specific source files can be added here
PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/syscalls.c $(PORT_DIR)/crt.S PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/syscalls.c $(PORT_DIR)/crt.S

View File

@ -105,6 +105,7 @@ module cacheway #(parameter NUMLINES=512, parameter LINELEN = 256, TAGLEN = 26,
// Data Array // Data Array
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// *** instantiate one larger RAM, not one per RAM. Expand byte mask
genvar words; genvar words;
for(words = 0; words < LINELEN/`XLEN; words++) begin: word for(words = 0; words < LINELEN/`XLEN; words++) begin: word
sram1p1rw #(.DEPTH(NUMLINES), .WIDTH(`XLEN)) CacheDataMem(.clk, .Adr(RAdr), sram1p1rw #(.DEPTH(NUMLINES), .WIDTH(`XLEN)) CacheDataMem(.clk, .Adr(RAdr),

View File

@ -53,6 +53,7 @@ module sram1p1rw #(parameter DEPTH=128, WIDTH=256) (
if (`USE_SRAM == 1) begin if (`USE_SRAM == 1) begin
// 64 x 128-bit SRAM // 64 x 128-bit SRAM
// check if the size is ok, complain if not***
logic [WIDTH-1:0] BitWriteMask; logic [WIDTH-1:0] BitWriteMask;
for (index=0; index < WIDTH; index++) for (index=0; index < WIDTH; index++)
assign BitWriteMask[index] = ByteMask[index/8]; assign BitWriteMask[index] = ByteMask[index/8];

View File

@ -93,11 +93,7 @@ module srt (
otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qm, Quot); otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qm, Quot);
<<<<<<< Updated upstream
expcalc expcalc(.XExp, .YExp, .calcExp);
=======
expcalc expcalc(.XExp, .YExp, .calcExp, .Sqrt); expcalc expcalc(.XExp, .YExp, .calcExp, .Sqrt);
>>>>>>> Stashed changes
signcalc signcalc(.XSign, .YSign, .calcSign); signcalc signcalc(.XSign, .YSign, .calcSign);
endmodule endmodule
@ -187,6 +183,26 @@ module qsel2 ( // *** eventually just change to 4 bits
assign #1 qm = magnitude & sign; assign #1 qm = magnitude & sign;
endmodule endmodule
////////////////////////////////////
// Adder Input Selection, Radix 2 //
////////////////////////////////////
module fsel2 (
input logic sp, sn,
input logic [`DIVLEN+3:0] C, S, SM,
output logic [`DIVLEN+3:0] F
);
logic [`DIVLEN+3:0] FP, FN;
// Generate for both positive and negative bits
assign FP = ~S & C;
assign FN = SM | (C & (~C << 2));
// Choose which adder input will be used
assign F = sp ? FP : (sn ? FN : (`DIVLEN+4){1'b0});
endmodule
/////////////////////////////////// ///////////////////////////////////
// On-The-Fly Converter, Radix 2 // // On-The-Fly Converter, Radix 2 //
/////////////////////////////////// ///////////////////////////////////
@ -234,6 +250,17 @@ module otfc2 #(parameter N=64) (
endmodule endmodule
///////////////////////////////
// Square Root OTFC, Radix 2 //
///////////////////////////////
module softc2(
input logic clk,
input logic Start,
input logic sp, sn,
output logic S,
);
endmodule
///////////// /////////////
// counter // // counter //
///////////// /////////////
@ -301,13 +328,6 @@ endmodule
// expcalc // // expcalc //
////////////// //////////////
module expcalc( module expcalc(
<<<<<<< Updated upstream
input logic [`NE-1:0] XExp, YExp,
output logic [`NE-1:0] calcExp
);
assign calcExp = XExp - YExp + (`NE)'(`BIAS);
=======
input logic [`NE-1:0] XExp, YExp, input logic [`NE-1:0] XExp, YExp,
input logic Sqrt, input logic Sqrt,
output logic [`NE-1:0] calcExp output logic [`NE-1:0] calcExp
@ -317,7 +337,6 @@ module expcalc(
assign SExp = {1'b0, SXExp[`NE-1:1]} + (`NE)'(`BIAS); assign SExp = {1'b0, SXExp[`NE-1:1]} + (`NE)'(`BIAS);
assign DExp = XExp - YExp + (`NE)'(`BIAS); assign DExp = XExp - YExp + (`NE)'(`BIAS);
assign calcExp = Sqrt ? SExp : DExp; assign calcExp = Sqrt ? SExp : DExp;
>>>>>>> Stashed changes
endmodule endmodule

View File

@ -62,11 +62,6 @@ module testbench;
// `define mema 255:192 // `define mema 255:192
// FLOAT TEST SIZES // FLOAT TEST SIZES
<<<<<<< Updated upstream
`define memr 63:0
`define memb 127:64
`define mema 191:128
=======
// `define memr 63:0 // `define memr 63:0
// `define memb 127:64 // `define memb 127:64
// `define mema 191:128 // `define mema 191:128
@ -75,7 +70,6 @@ module testbench;
`define memr 63:0 `define memr 63:0
`define mema 127:64 `define mema 127:64
`define memb 191:128 `define memb 191:128
>>>>>>> Stashed changes
// Test logicisters // Test logicisters
logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file
@ -86,13 +80,9 @@ module testbench;
logic rsign; logic rsign;
integer testnum, errors; integer testnum, errors;
<<<<<<< Updated upstream
assign Int = 1'b0;
=======
// Equip Int test or Sqrt test // Equip Int test or Sqrt test
assign Int = 1'b0; assign Int = 1'b0;
assign Sqrt = 1'b1; assign Sqrt = 1'b1;
>>>>>>> Stashed changes
// Divider // Divider
srt srt(.clk, .Start(req), srt srt(.clk, .Start(req),
@ -101,11 +91,7 @@ module testbench;
.XSign(asign), .YSign(bsign), .rsign, .XSign(asign), .YSign(bsign), .rsign,
.SrcXFrac(afrac), .SrcYFrac(bfrac), .SrcXFrac(afrac), .SrcYFrac(bfrac),
.SrcA(a), .SrcB(b), .Fmt(2'b00), .SrcA(a), .SrcB(b), .Fmt(2'b00),
<<<<<<< Updated upstream
.W64(1'b1), .Signed(1'b0), .Int, .Sqrt(1'b0),
=======
.W64(1'b1), .Signed(1'b0), .Int, .Sqrt, .W64(1'b1), .Signed(1'b0), .Int, .Sqrt,
>>>>>>> Stashed changes
.Quot, .Rem(), .Flags(), .done); .Quot, .Rem(), .Flags(), .done);
// Counter // Counter
@ -125,11 +111,7 @@ module testbench;
begin begin
testnum = 0; testnum = 0;
errors = 0; errors = 0;
<<<<<<< Updated upstream
$readmemh ("testvectors", Tests);
=======
$readmemh ("sqrttestvectors", Tests); $readmemh ("sqrttestvectors", Tests);
>>>>>>> Stashed changes
Vec = Tests[testnum]; Vec = Tests[testnum];
a = Vec[`mema]; a = Vec[`mema];
{asign, aExp, afrac} = a; {asign, aExp, afrac} = a;
@ -183,17 +165,10 @@ module testbench;
req <= #5 1; req <= #5 1;
diffp = correctr[51:0] - r; diffp = correctr[51:0] - r;
diffn = r - correctr[51:0]; diffn = r - correctr[51:0];
<<<<<<< Updated upstream
if (($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
begin
errors = errors + 1;
$display("result was %h, should be %h %h %h\n", rSqrt, correctr, diffn, diffp);
=======
if (rExp !== correctr[62:52]) // check if accurate to 1 ulp if (rExp !== correctr[62:52]) // check if accurate to 1 ulp
begin begin
errors = errors + 1; errors = errors + 1;
$display("result was %h, should be %h %h %h\n", r, correctr, diffn, diffp); $display("result was %h, should be %h %h %h\n", r, correctr, diffn, diffp);
>>>>>>> Stashed changes
$display("failed\n"); $display("failed\n");
$stop; $stop;
end end

View File

@ -123,6 +123,7 @@ logic [3:0] dummy;
"wally32priv": tests = wally32priv; "wally32priv": tests = wally32priv;
"wally32periph": tests = wally32periph; "wally32periph": tests = wally32periph;
"embench": tests = embench; "embench": tests = embench;
"coremark": tests = coremark;
endcase endcase
end end
if (tests.size() == 0) begin if (tests.size() == 0) begin

View File

@ -36,7 +36,7 @@ string tvpaths[] = '{
"../../tests/riscof/work/riscv-arch-test/", "../../tests/riscof/work/riscv-arch-test/",
"../../tests/wally-riscv-arch-test/work/", //"../../tests/riscof/work/wally-riscv-arch-test/", "../../tests/wally-riscv-arch-test/work/", //"../../tests/riscof/work/wally-riscv-arch-test/",
"../../tests/imperas-riscv-tests/work/", "../../tests/imperas-riscv-tests/work/",
"../../benchmarks/coremark/work/", //"../../benchmarks/coremark/work/", "../../benchmarks/coremark/work/",
"../../addins/embench-iot/" "../../addins/embench-iot/"
}; };

View File

@ -1,14 +1,15 @@
# #
# Makefile for synthesis # Makefile for synthesis
# Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022 # Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022
# Madeleine Masser-Frye (mmasserfrye@hmc.edu) 7/8/2022
NAME := synth NAME := synth
# defaults # defaults
export DESIGN ?= wallypipelinedcore export DESIGN ?= wallypipelinedcore
export FREQ ?= 3000 export FREQ ?= 3000
export CONFIG ?= rv32e export CONFIG ?= rv32e
# title to add a note in the synth's directory name
TITLE = TITLE =
# tsmc28, sky130, and sky90 presently supported # tsmc28, sky130, and sky90 presently supported
export TECH ?= sky90 export TECH ?= sky90
# MAXCORES allows parallel compilation, which is faster but less CPU-efficient # MAXCORES allows parallel compilation, which is faster but less CPU-efficient
@ -21,20 +22,14 @@ export DRIVE ?= FLOP
time := $(shell date +%F-%H-%M) time := $(shell date +%F-%H-%M)
hash := $(shell git rev-parse --short HEAD) hash := $(shell git rev-parse --short HEAD)
export OUTPUTDIR := newRuns/$(DESIGN)_$(CONFIG)_$(TECH)nm_$(FREQ)_MHz_$(time)_$(TITLE)_$(hash) export OUTPUTDIR := runs/$(DESIGN)_$(CONFIG)_$(TECH)nm_$(FREQ)_MHz_$(time)_$(TITLE)_$(hash)
export SAIFPOWER ?= 0 export SAIFPOWER ?= 0
CONFIGDIR ?= ${WALLY}/pipelined/config CONFIGDIR ?= ${WALLY}/pipelined/config
CONFIGFILES ?= $(shell find $(CONFIGDIR) -name rv*_*) CONFIGFILES ?= $(shell find $(CONFIGDIR) -name rv*_*)
CONFIGFILESTRIM = $(notdir $(CONFIGFILES)) CONFIGFILESTRIM = $(notdir $(CONFIGFILES))
# FREQS = 25 50 100 150 200 250 300 350 400 # FREQS = 25 50 100 150 200 250 300 350 400
k = 3 6 # k = 3 6
ifeq ($(TECH), sky130)
FREQS = 25 50 100 150 200 250 300 350 400
else ifeq ($(TECH), sky90)
FREQS = 500 550 600 650 700 750 800 850 900 950 1000
endif
print: print:
@echo $(FREQS) @echo $(FREQS)
@ -44,12 +39,7 @@ print:
default: default:
@echo " Basic synthesis procedure for Wally:" @echo " Basic synthesis procedure for Wally:"
@echo " Invoke with make synth" @echo " Invoke with make synth"
@echo "Use wallySynth.py to run a concurrent sweep "
test: rv%
echo "Running test on $<"
rv%.log: rv%
echo $<
DIRS32 = rv32e rv32gc rv32ic DIRS32 = rv32e rv32gc rv32ic
@ -62,21 +52,21 @@ DIRS = $(DIRS32) $(DIRS64)
# @$(foreach kval, $(k), sed -i 's/BPRED_SIZE.*/BPRED_SIZE $(kval)/g' $(CONFIGDIR)/rv64gc_bpred_$(kval)/wally-config.vh;) # @$(foreach kval, $(k), sed -i 's/BPRED_SIZE.*/BPRED_SIZE $(kval)/g' $(CONFIGDIR)/rv64gc_bpred_$(kval)/wally-config.vh;)
# @$(foreach kval, $(k), make synth DESIGN=wallypipelinedcore CONFIG=rv64gc_bpred_$(kval) TECH=sky90 FREQ=500 MAXCORES=4 --jobs;) # @$(foreach kval, $(k), make synth DESIGN=wallypipelinedcore CONFIG=rv64gc_bpred_$(kval) TECH=sky90 FREQ=500 MAXCORES=4 --jobs;)
copy: copy:
# remove old config files
rm -rf $(CONFIGDIR)/*_*
@$(foreach dir, $(DIRS), rm -rf $(CONFIGDIR)/$(dir)_orig;) @$(foreach dir, $(DIRS), rm -rf $(CONFIGDIR)/$(dir)_orig;)
@$(foreach dir, $(DIRS), cp -r $(CONFIGDIR)/$(dir) $(CONFIGDIR)/$(dir)_orig;) @$(foreach dir, $(DIRS), cp -r $(CONFIGDIR)/$(dir) $(CONFIGDIR)/$(dir)_orig;)
@$(foreach dir, $(DIRS), sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES 512/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) @$(foreach dir, $(DIRS), sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES 512/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;)
@$(foreach dir, $(DIRS), sed -i 's/NUMWAYS.*/NUMWAYS 1/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) @$(foreach dir, $(DIRS), sed -i 's/NUMWAYS.*/NUMWAYS 1/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;)
@$(foreach dir, $(DIRS), sed -i 's/BPRED_SIZE.*/BPRED_SIZE 5/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;) @$(foreach dir, $(DIRS), sed -i 's/BPRED_SIZE.*/BPRED_SIZE 4/g' $(CONFIGDIR)/$(dir)_orig/wally-config.vh;)
@$(foreach dir, $(DIRS32), sed -i "s/RAM_RANGE.*/RAM_RANGE 34\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;) @$(foreach dir, $(DIRS32), sed -i "s/RAM_RANGE.*/RAM_RANGE 34\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;)
@$(foreach dir, $(DIRS64), sed -i "s/RAM_RANGE.*/RAM_RANGE 56\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;) @$(foreach dir, $(DIRS64), sed -i "s/RAM_RANGE.*/RAM_RANGE 56\'h01FF/g" $(CONFIGDIR)/$(dir)_orig/wally-config.vh ;)
del:
rm -rf $(CONFIGDIR)/*_*
configs: $(DIRS) configs: $(DIRS)
$(DIRS): $(DIRS):
# turn off FPU # turn off FPU
rm -rf $(CONFIGDIR)/$@_FPUoff rm -rf $(CONFIGDIR)/$@_FPUoff
cp -r $(CONFIGDIR)/$@_orig $(CONFIGDIR)/$@_FPUoff cp -r $(CONFIGDIR)/$@_orig $(CONFIGDIR)/$@_FPUoff
@ -106,18 +96,10 @@ $(DIRS):
freqs: freqs:
@$(foreach freq, $(FREQS), make synth DESIGN=wallypipelinedcore CONFIG=rv32e FREQ=$(freq) MAXCORES=1;) @$(foreach freq, $(FREQS), make synth DESIGN=wallypipelinedcore CONFIG=rv32e FREQ=$(freq) MAXCORES=1;)
allsynth: $(CONFIGFILESTRIM)
$(CONFIGFILESTRIM):
make synth DESIGN=wallypipelinedcore CONFIG=$@ TECH=sky90 FREQ=3000 MAXCORES=1
synth: synth:
rm -f hdl/*
rm -rf WORK
@echo "DC Synthesis" @echo "DC Synthesis"
@mkdir -p hdl/
@mkdir -p $(OUTPUTDIR) @mkdir -p $(OUTPUTDIR)
@mkdir -p $(OUTPUTDIR)/hdl
@mkdir -p $(OUTPUTDIR)/reports @mkdir -p $(OUTPUTDIR)/reports
@mkdir -p $(OUTPUTDIR)/mapped @mkdir -p $(OUTPUTDIR)/mapped
@mkdir -p $(OUTPUTDIR)/unmapped @mkdir -p $(OUTPUTDIR)/unmapped
@ -125,11 +107,11 @@ ifeq ($(SAIFPOWER), 1)
cp -f ../pipelined/regression/power.saif . cp -f ../pipelined/regression/power.saif .
endif endif
dc_shell-xg-t -64bit -f scripts/$(NAME).tcl | tee $(OUTPUTDIR)/$(NAME).out dc_shell-xg-t -64bit -f scripts/$(NAME).tcl | tee $(OUTPUTDIR)/$(NAME).out
rm -rf $(OUTPUTDIR)/hdl
rm -rf $(OUTPUTDIR)/WORK
rm -rf $(OUTPUTDIR)/alib-52
clean: clean:
# fix should make del be here
rm -rf alib-52 WORK analyzed $(NAME).out
rm -f hdl/*
rm -f default.svf rm -f default.svf
rm -f command.log rm -f command.log
rm -f filenames*.log rm -f filenames*.log
@ -137,6 +119,5 @@ clean:
rm -f Synopsys_stack_trace_*.txt rm -f Synopsys_stack_trace_*.txt
rm -f crte_*.txt rm -f crte_*.txt
fresh: clean copy configs
@echo "synth directory cleaned and fresh config files written"

View File

@ -7,10 +7,10 @@ import subprocess
from matplotlib.cbook import flatten from matplotlib.cbook import flatten
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.lines as lines import matplotlib.lines as lines
from wallySynth import testFreq
import numpy as np import numpy as np
from ppa.ppaAnalyze import noOutliers from ppa.ppaAnalyze import noOutliers
from matplotlib import ticker from matplotlib import ticker
import argparse
def synthsintocsv(): def synthsintocsv():
@ -74,14 +74,13 @@ def synthsfromcsv(filename):
allSynths[i] = Synth(*allSynths[i]) allSynths[i] = Synth(*allSynths[i])
return allSynths return allSynths
def freqPlot(tech, width, config): def freqPlot(tech, width, config):
''' plots delay, area for syntheses with specified tech, module, width ''' plots delay, area for syntheses with specified tech, module, width
''' '''
freqsL, delaysL, areasL = ([[], []] for i in range(3)) freqsL, delaysL, areasL = ([[], []] for i in range(3))
for oneSynth in allSynths: for oneSynth in allSynths:
if (width == oneSynth.width) & (config == oneSynth.config) & (tech == oneSynth.tech) & (oneSynth.special == ''): if (width == oneSynth.width) & (config == oneSynth.config) & (tech == oneSynth.tech) & ('' == oneSynth.special):
ind = (1000/oneSynth.delay < oneSynth.freq) # when delay is within target clock period ind = (1000/oneSynth.delay < oneSynth.freq) # when delay is within target clock period
freqsL[ind] += [oneSynth.freq] freqsL[ind] += [oneSynth.freq]
delaysL[ind] += [oneSynth.delay] delaysL[ind] += [oneSynth.delay]
@ -124,74 +123,93 @@ def freqPlot(tech, width, config):
addFO4axis(fig, ax1, tech) addFO4axis(fig, ax1, tech)
plt.savefig('./plots/wally/freqSweep_' + tech + '_' + width + config + '.png') plt.savefig('./plots/wally/freqSweep_' + tech + '_' + width + config + '.png')
# plt.show()
def areaDelay(tech, delays, areas, labels, fig, ax, norm=False):
def areaDelay(tech, fig=None, ax=None, freq=None, width=None, config=None, norm=False):
delays, areas, labels = ([] for i in range(3))
for oneSynth in allSynths:
if (width==None) or (width == oneSynth.width):
if (tech == oneSynth.tech) & (freq == oneSynth.freq):
if (config == None) & (oneSynth.special == 'FPUoff'): #fix
delays += [oneSynth.delay]
areas += [oneSynth.area]
labels += [oneSynth.width + oneSynth.config]
elif (config != None) & (oneSynth.config == config):
delays += [oneSynth.delay]
areas += [oneSynth.area]
labels += [oneSynth.special]
if width == None:
width = ''
if (fig == None) or (ax == None):
fig, (ax) = plt.subplots(1, 1)
ax.ticklabel_format(useOffset=False, style='plain')
plt.subplots_adjust(left=0.18) plt.subplots_adjust(left=0.18)
if norm: fo4 = techdict[tech].fo4
delays = [d/techdict[tech][0] for d in delays] add32area = techdict[tech].add32area
areas = [a/techdict[tech][1] for a in areas] marker = techdict[tech].shape
color = techdict[tech].color
plt.scatter(delays, areas) if norm:
delays = [d/fo4 for d in delays]
areas = [a/add32area for a in areas]
plt.scatter(delays, areas, marker=marker, color=color)
plt.xlabel('Cycle time (ns)') plt.xlabel('Cycle time (ns)')
plt.ylabel('Area (sq microns)') plt.ylabel('Area (sq microns)')
ytop = ax.get_ylim()[1] ytop = ax.get_ylim()[1]
plt.ylim(ymin=0, ymax=1.1*ytop) plt.ylim(ymin=0, ymax=1.1*ytop)
titleStr = tech + ' ' + width
saveStr = tech + '_' + width
if config:
titleStr += config
saveStr = saveStr + config + '_versions_'
if (config == None):
saveStr = saveStr + '_origConfigs_'
saveStr += str(freq)
titleStr = titleStr
plt.title(titleStr)
ax.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}')) ax.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
for i in range(len(labels)): for i in range(len(labels)):
plt.annotate(labels[i], (delays[i], areas[i]), textcoords="offset points", xytext=(0,10), ha='center') plt.annotate(labels[i], (delays[i], areas[i]), textcoords="offset points", xytext=(0,10), ha='center')
# addFO4axis(fig, ax1, tech) return fig
plt.savefig('./plots/wally/areaDelay_' + saveStr + '.png') def plotFeatures(tech, width, config):
delays, areas, labels = ([] for i in range(3))
freq = techdict[tech].targfreq
for oneSynth in allSynths:
if (tech == oneSynth.tech) & (freq == oneSynth.freq):
if (oneSynth.config == config) & (width == oneSynth.width):
delays += [oneSynth.delay]
areas += [oneSynth.area]
labels += [oneSynth.special]
fig, (ax) = plt.subplots(1, 1)
fig = areaDelay(tech, delays, areas, labels, fig, ax)
titlestr = tech+'_'+width+config
plt.title(titlestr)
plt.savefig('./plots/wally/features_'+titlestr+'.png')
def plotConfigs(tech, special=''):
delays, areas, labels = ([] for i in range(3))
freq = techdict[tech].targfreq
for oneSynth in allSynths:
if (tech == oneSynth.tech) & (freq == oneSynth.freq) & (oneSynth.special == special):
delays += [oneSynth.delay]
areas += [oneSynth.area]
labels += [oneSynth.width + oneSynth.config]
fig, (ax) = plt.subplots(1, 1)
fig = areaDelay(tech, delays, areas, labels, fig, ax)
titleStr = tech+'_'+special
plt.title(titleStr)
plt.savefig('./plots/wally/configs_' + titleStr + '.png')
def normAreaDelay(special=''):
fig, (ax) = plt.subplots(1, 1)
fullLeg = []
for tech in list(techdict.keys()):
delays, areas, labels = ([] for i in range(3))
spec = techdict[tech]
freq = spec.targfreq
for oneSynth in allSynths:
if (tech == oneSynth.tech) & (freq == oneSynth.freq) & (oneSynth.special == special):
delays += [oneSynth.delay]
areas += [oneSynth.area]
labels += [oneSynth.width + oneSynth.config]
areaDelay(tech, delays, areas, labels, fig, ax, norm=True)
fullLeg += [lines.Line2D([0], [0], markerfacecolor=spec.color, label=tech, marker=spec.shape, markersize=10, color='w')]
def normAreaDelay():
fig2, (ax) = plt.subplots(1, 1)
areaDelay('sky90', fig=fig2, ax=ax, freq=testFreq[0], norm=True)
areaDelay('tsmc28', fig=fig2, ax=ax, freq=testFreq[1], norm=True)
ax.set_title('Normalized Area & Cycle Time by Configuration') ax.set_title('Normalized Area & Cycle Time by Configuration')
ax.set_xlabel('Cycle Time (FO4)') ax.set_xlabel('Cycle Time (FO4)')
ax.set_ylabel('Area (add32)') ax.set_ylabel('Area (add32)')
fullLeg = [lines.Line2D([0], [0], color='royalblue', label='tsmc28')]
fullLeg += [lines.Line2D([0], [0], color='orange', label='sky90')]
ax.legend(handles = fullLeg, loc='upper left') ax.legend(handles = fullLeg, loc='upper left')
plt.savefig('./plots/wally/normAreaDelay.png') plt.savefig('./plots/wally/normAreaDelay.png')
def addFO4axis(fig, ax, tech): def addFO4axis(fig, ax, tech):
fo4 = techdict[tech][0] fo4 = techdict[tech].fo4
ax3 = fig.add_axes((0.125,0.14,0.775,0.0)) ax3 = fig.add_axes((0.125,0.14,0.775,0.0))
ax3.yaxis.set_visible(False) # hide the yaxis ax3.yaxis.set_visible(False) # hide the yaxis
@ -215,15 +233,22 @@ def addFO4axis(fig, ax, tech):
if __name__ == '__main__': if __name__ == '__main__':
techdict = {'sky90': [43.2e-3, 1440.600027], 'tsmc28': [12.2e-3, 209.286002]} parser = argparse.ArgumentParser()
parser.add_argument("-s", "--skyfreq", type=int, default=3000, help = "Target frequency used for sky90 syntheses")
parser.add_argument("-t", "--tsmcfreq", type=int, default=10000, help = "Target frequency used for tsmc28 syntheses")
args = parser.parse_args()
# synthsintocsv() TechSpec = namedtuple("TechSpec", "color shape targfreq fo4 add32area add32lpower add32denergy")
techdict = {}
techdict['sky90'] = TechSpec('green', 'o', args.skyfreq, 43.2e-3, 1440.600027, 714.057, 0.658023)
techdict['tsmc28'] = TechSpec('blue', 's', args.tsmcfreq, 12.2e-3, 209.286002, 1060.0, .081533)
synthsintocsv()
synthsfromcsv('Summary.csv') synthsfromcsv('Summary.csv')
freqPlot('tsmc28', 'rv32', 'e') freqPlot('tsmc28', 'rv32', 'e')
freqPlot('sky90', 'rv32', 'e') freqPlot('sky90', 'rv32', 'e')
areaDelay('tsmc28', freq=testFreq[1], width= 'rv64', config='gc') plotFeatures('sky90', 'rv64', 'gc')
areaDelay('sky90', freq=testFreq[0], width='rv64', config='gc') plotFeatures('tsmc28', 'rv64', 'gc')
areaDelay('tsmc28', freq=testFreq[1]) plotConfigs('sky90', special='orig')
areaDelay('sky90', freq=testFreq[0]) plotConfigs('tsmc28', special='orig')
normAreaDelay(special='orig')
# normAreaDelay()

32
synthDC/ppa/README Normal file
View File

@ -0,0 +1,32 @@
Wally PPA Study
July 8, 2022
Madeleine Masser-Frye
mmasserfrye@hmc.edu
___________________
Apologies for issues in this folder, code was written originally for individual use and documentation was compiled in haste. Please feel free to contact the author with questions.
-------------------
ppaSynth.py
Run to synthesize datapath modules from src/ppa.
To run a specific combination of widths, modules, techs, and freqs,
modify those lists and use allCombos() to generate synthsToRun (comment out freqSweep).
To run a sweep of frequencies around the best delay found in existing syntheses (according to bestSynths.csv), modify the parameters and use freqSweep to generate synthsToRun.
To remove synths to be run that already exist in /runs from synthsToRun, use filterRedundant().
Syntheses run in parallel but you may encounter issues doing more than a dozen or so at once.
-------------------
ppaAnalyze.py
Run to plot results of PPA syntheses. See docstrings for individual function info.
-------------------
bestSynths.csv
Results of the synthesis for each combination of module, width, and tech with the best achievable delay. Generated by csvOfBest() in ppaAnalyze.py
-------------------
ppaFitting.csv & ppaEquations.csv
Representations of the regression fit for each module and metric. Generated in ppaAnalyze.py by makeCoefTable() and makeEqTable().
-------------------
ppaData.csv
Results from all synthesis runs. Generated by synthsintocsv() and used by synthsfromcsv in ppaAnalyze.py.

View File

@ -8,9 +8,11 @@ import re
from matplotlib.cbook import flatten from matplotlib.cbook import flatten
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.lines as lines import matplotlib.lines as lines
import matplotlib as mpl
import numpy as np import numpy as np
from collections import namedtuple from collections import namedtuple
import sklearn.metrics as skm import sklearn.metrics as skm
import os
def synthsfromcsv(filename): def synthsfromcsv(filename):
Synth = namedtuple("Synth", "module tech width freq delay area lpower denergy") Synth = namedtuple("Synth", "module tech width freq delay area lpower denergy")
@ -518,7 +520,7 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
if no freq specified, uses the synthesis with best achievable delay for each width if no freq specified, uses the synthesis with best achievable delay for each width
overlays data from both techs overlays data from both techs
''' '''
plt.rcParams["figure.figsize"] = (7,3.46) with mpl.rc_context({"figure.figsize": (7,3.46)}):
fig, axs = plt.subplots(2, 2) fig, axs = plt.subplots(2, 2)
arr = [['delay', 'area'], ['lpower', 'denergy']] arr = [['delay', 'area'], ['lpower', 'denergy']]
@ -555,6 +557,8 @@ def plotPPA(mod, freq=None, norm=True, aleOpt=False):
# plt.show() # plt.show()
def makeLineLegend(): def makeLineLegend():
''' generates legend to accompany normalized plots
'''
plt.rcParams["figure.figsize"] = (5.5,0.3) plt.rcParams["figure.figsize"] = (5.5,0.3)
fig = plt.figure() fig = plt.figure()
fullLeg = [lines.Line2D([0], [0], color='black', label='fastest', linestyle='-')] fullLeg = [lines.Line2D([0], [0], color='black', label='fastest', linestyle='-')]
@ -619,6 +623,8 @@ def muxPlot(fits='clsgn', norm=True):
plt.savefig('./plots/mux.png') plt.savefig('./plots/mux.png')
def stdDevError(): def stdDevError():
''' calculates std deviation and error for paper-writing purposes
'''
for var in ['delay', 'area', 'lpower', 'denergy']: for var in ['delay', 'area', 'lpower', 'denergy']:
errlist = [] errlist = []
for module in modules: for module in modules:
@ -668,6 +674,30 @@ def stdDevError():
print(var, ' ', avgErr, ' ', stdv) print(var, ' ', avgErr, ' ', stdv)
def makePlotDirectory():
''' creates plots directory in same level as this script to store plots in
'''
current_directory = os.getcwd()
final_directory = os.path.join(current_directory, 'plots')
if not os.path.exists(final_directory):
os.makedirs(final_directory)
os.chdir(final_directory)
for folder in ['freqBuckshot', 'normalized', 'unnormalized']:
new_directory = os.path.join(final_directory, folder)
if not os.path.exists(new_directory):
os.makedirs(new_directory)
os.chdir(new_directory)
if 'freq' in folder:
for tech in ['sky90', 'tsmc28']:
for mod in modules:
tech_directory = os.path.join(new_directory, tech)
mod_directory = os.path.join(tech_directory, mod)
if not os.path.exists(mod_directory):
os.makedirs(mod_directory)
os.chdir('..')
os.chdir(current_directory)
if __name__ == '__main__': if __name__ == '__main__':
############################## ##############################
@ -686,26 +716,22 @@ if __name__ == '__main__':
############################## ##############################
# cleanup() # run to remove garbage synth runs # cleanup() # run to remove garbage synth runs
# synthsintocsv() # slow, run only when new synth runs to add to csv synthsintocsv() # slow, run only when new synth runs to add to csv
allSynths = synthsfromcsv('ppaData.csv') # your csv here! allSynths = synthsfromcsv('ppaData.csv') # your csv here!
bestSynths = csvOfBest('bestSynths.csv') bestSynths = csvOfBest('bestSynths.csv')
makePlotDirectory()
# ### function examples # ### other functions
# squareAreaDelay('sky90', 'add', 32)
# oneMetricPlot('mult', 'lpower')
# freqPlot('sky90', 'mux4', 16)
# plotBestAreas('add')
# makeCoefTable() # makeCoefTable()
# makeEqTable() # makeEqTable()
# makeLineLegend()
# muxPlot() # muxPlot()
# stdDevError() # stdDevError()
for mod in modules: for mod in modules:
plotPPA(mod, norm=False)
plotPPA(mod, aleOpt=True)
for w in widths: for w in widths:
freqPlot('sky90', mod, w) freqPlot('sky90', mod, w)
freqPlot('tsmc28', mod, w) freqPlot('tsmc28', mod, w)
plotPPA(mod, norm=False)
plotPPA(mod, aleOpt=True)
plt.close('all') plt.close('all')

View File

@ -10,47 +10,64 @@ def runCommand(module, width, tech, freq):
command = "make synth DESIGN=ppa_{}_{} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq) command = "make synth DESIGN=ppa_{}_{} TECH={} DRIVE=INV FREQ={} MAXOPT=1 MAXCORES=1".format(module, width, tech, freq)
subprocess.Popen(command, shell=True) subprocess.Popen(command, shell=True)
def deleteRedundant(LoT): def deleteRedundant(synthsToRun):
'''removes any previous runs for the current synthesis specifications''' '''removes any previous runs for the current synthesis specifications'''
synthStr = "rm -rf runs/ppa_{}_{}_rv32e_{}nm_{}_*" synthStr = "rm -rf runs/ppa_{}_{}_rv32e_{}nm_{}_*"
for synth in LoT: for synth in synthsToRun:
bashCommand = synthStr.format(*synth) bashCommand = synthStr.format(*synth)
outputCPL = subprocess.check_output(['bash','-c', bashCommand]) outputCPL = subprocess.check_output(['bash','-c', bashCommand])
if __name__ == '__main__': def freqSweep(module, width, tech):
LoT = []
synthsToRun = [] synthsToRun = []
##### Run specific syntheses
# widths = [8]
# modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
# techs = ['sky90']
# freqs = [5000]
# for w in widths:
# for module in modules:
# for tech in techs:
# for freq in freqs:
# LoT += [[module, str(w), tech, str(freq)]]
##### Run a sweep based on best delay found in existing syntheses
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8] arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
allSynths = synthsfromcsv('bestSynths.csv') allSynths = synthsfromcsv('bestSynths.csv')
for synth in allSynths: for synth in allSynths:
if (synth.module == module) & (synth.tech == tech) & (synth.width == width):
f = 1000/synth.delay f = 1000/synth.delay
for freq in [round(f+f*x/100) for x in arr]: for freq in [round(f+f*x/100) for x in arr]:
LoT += [[synth.module, str(synth.width), synth.tech, str(freq)]] synthsToRun += [[synth.module, str(synth.width), synth.tech, str(freq)]]
return synthsToRun
##### Only do syntheses for which a run doesn't already exist def filterRedundant(synthsToRun):
bashCommand = "find . -path '*runs/ppa*rv32e*' -prune" bashCommand = "find . -path '*runs/ppa*rv32e*' -prune"
output = subprocess.check_output(['bash','-c', bashCommand]) output = subprocess.check_output(['bash','-c', bashCommand])
specReg = re.compile('[a-zA-Z0-9]+') specReg = re.compile('[a-zA-Z0-9]+')
allSynths = output.decode("utf-8").split('\n')[:-1] allSynths = output.decode("utf-8").split('\n')[:-1]
allSynths = [specReg.findall(oneSynth)[2:7] for oneSynth in allSynths] allSynths = [specReg.findall(oneSynth)[2:7] for oneSynth in allSynths]
allSynths = [oneSynth[0:2] + [oneSynth[3][:-2]] + [oneSynth[4]] for oneSynth in allSynths] allSynths = [oneSynth[0:2] + [oneSynth[3][:-2]] + [oneSynth[4]] for oneSynth in allSynths]
for synth in LoT: output = []
for synth in synthsToRun:
if (synth not in allSynths): if (synth not in allSynths):
synthsToRun += [synth] output += [synth]
return output
def allCombos(widths, modules, techs, freqs):
synthsToRun = []
for w in widths:
for module in modules:
for tech in techs:
for freq in freqs:
synthsToRun += [[module, str(w), tech, str(freq)]]
return synthsToRun
if __name__ == '__main__':
##### Run specific syntheses
widths = [8, 16, 32, 64, 128]
modules = ['mult', 'add', 'shiftleft', 'flop', 'comparator', 'priorityencoder', 'add', 'csa', 'mux2', 'mux4', 'mux8']
techs = ['sky90', 'tsmc28']
freqs = [5000]
synthsToRun = allCombos(widths, modules, techs, freqs)
##### Run a sweep based on best delay found in existing syntheses
module = 'add'
width = 32
tech = 'sky90'
synthsToRun = freqSweep(module, width, tech)
##### Only do syntheses for which a run doesn't already exist
synthsToRun = filterRedundant(synthsToRun)
pool = Pool(processes=25) pool = Pool(processes=25)
pool.starmap(runCommand, synthsToRun) pool.starmap(print, synthsToRun)

View File

@ -1,29 +0,0 @@
#!/usr/bin/bash
# Madeleine Masser-Frye mmasserfrye@hmc.edu July 2022
helpFunction()
{ echo ""
echo "Usage: $0 "
echo -e "\t--configs Synthesizes wally with configurations 32e, 32ic, 64ic, 32gc, and 64gc"
echo -e "\t--freqs NUM Synthesizes rv32e with target frequencies at NUM MHz and +/- 2, 4, 6, 8 %"
echo -e "\t--features Synthesizes rv64gc versions FPUoff, noMulDiv, noPriv, PMP0, PMP16"
exit 1 # Exit script after printing help
}
VALID_ARGS=$(getopt -o cft: --long configs,features,freqs: -- "$@")
eval set -- "$VALID_ARGS"
unset VALID_ARGS
if [[ $1 == "--" ]];
then helpFunction
elif [[ $1 == "--freqs" ]] && [[ ! $2 =~ ^[[:digit:]]+$ ]]
then echo "Argument must be an integer, target frequnecy is in MHz"
else
make clean
make del
make copy
make configs
./wallySynth.py $1 $2
./extractSummary.py
fi

View File

@ -1,64 +0,0 @@
#!/usr/bin/python3
# Shreya Sanghai (ssanghai@hmc.edu) 2/28/2022
import glob
import re
import csv
import linecache
import os
# field_names = [ 'Name', 'Critical Path Length', 'Cell Area', 'Synth Time']
# data = []
# for name in glob.glob("/home/ssanghai/riscv-wally/synthDC/runs/*/reports/wallypipelinedcore_qor.rep"):
# f = open(name, 'r')
# # trimName = re.search("runs\/(.*?)\/reports", name).group(1)
# trimName = re.search("wallypipelinedcore_(.*?)_sky9",name).group(1)
# for line in f:
# if "Critical Path Length" in line:
# pathLen = re.search("Length: *(.*?)\\n", line).group(1)
# if "Cell Area" in line:
# area = re.search("Area: *(.*?)\\n", line).group(1)
# if "Overall Compile Time" in line:
# time = re.search("Time: *(.*?)\\n", line).group(1)
# data += [{'Name' : trimName, 'Critical Path Length': pathLen, 'Cell Area' : area, 'Synth Time' :time}]
def main():
data = []
curr_dir = os.path.dirname(os.path.abspath(__file__))
output_file = os.path.join(curr_dir,"..","Summary.csv")
runs_dir = os.path.join(curr_dir,"..","runs/*/reports/wallypipelinedcore_qor.rep")
# cruns_dir = "/home/ssanghai/Desktop/cleanRun/*/reports/wallypipelinedcore_qor.rep"
search_strings = [
"Critical Path Length:", "Cell Area:", "Overall Compile Time:",
"Critical Path Clk Period:", "Critical Path Slack:"
]
for name in glob.glob(runs_dir):
f = open(name, 'r')
trimName = re.search("wallypipelinedcore_(.*?)_sky",name).group(1)
output = {'Name':trimName}
num_lines = len(f.readlines())
curr_line_index = 0
while curr_line_index < num_lines:
line = linecache.getline(name, curr_line_index)
for search_string in search_strings:
if search_string in line:
val = getVal(name,search_string,line,curr_line_index)
output[search_string] = val
curr_line_index +=1
data += [output]
with open(output_file, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=['Name'] + search_strings)
writer.writeheader()
writer.writerows(data)
def getVal(filename, search_string, line, line_index):
data = re.search(f"{search_string} *(.*?)\\n", line).group(1)
if data == '': #sometimes data is stored in two line
data = linecache.getline(filename, line_index+1).strip()
return data
if __name__=="__main__":
main()

View File

@ -1,9 +0,0 @@
#!/usr/bin/bash
# rm -r runs/*
make clean
make del
make copy
make configs
make allsynth
scripts/extractSummary.py
make del

View File

@ -1,7 +0,0 @@
#!/usr/bin/bash
# rm -r runs/*
make clean
make del
make freqs TECH=$1
scripts/extractSummary.py
make del

View File

@ -26,11 +26,11 @@ set saifpower $::env(SAIFPOWER)
set maxopt $::env(MAXOPT) set maxopt $::env(MAXOPT)
set drive $::env(DRIVE) set drive $::env(DRIVE)
eval file copy -force ${cfg} {hdl/} eval file copy -force ${cfg} {$outputDir/hdl/}
eval file copy -force ${cfg} $outputDir eval file copy -force ${cfg} $outputDir
eval file copy -force [glob ${hdl_src}/../config/shared/*.vh] {hdl/} eval file copy -force [glob ${hdl_src}/../config/shared/*.vh] {$outputDir/hdl/}
eval file copy -force [glob ${hdl_src}/*/*.sv] {hdl/} eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/}
eval file copy -force [glob ${hdl_src}/*/flop/*.sv] {hdl/} eval file copy -force [glob ${hdl_src}/*/flop/*.sv] {$outputDir/hdl/}
# Only for FMA class project; comment out when done # Only for FMA class project; comment out when done
# eval file copy -force [glob ${hdl_src}/fma/fma16.v] {hdl/} # eval file copy -force [glob ${hdl_src}/fma/fma16.v] {hdl/}
@ -41,7 +41,7 @@ if { $saifpower == 1 } {
} }
# Verilog files # Verilog files
set my_verilog_files [glob hdl/*] set my_verilog_files [glob $outputDir/hdl/*]
# Set toplevel # Set toplevel
set my_toplevel $::env(DESIGN) set my_toplevel $::env(DESIGN)
@ -56,7 +56,8 @@ set vhdlout_show_unconnected_pins "true"
# Due to parameterized Verilog must use analyze/elaborate and not # Due to parameterized Verilog must use analyze/elaborate and not
# read_verilog/vhdl (change to pull in Verilog and/or VHDL) # read_verilog/vhdl (change to pull in Verilog and/or VHDL)
# #
define_design_lib WORK -path ./WORK set alib_library_analysis_path ./$outputDir
define_design_lib WORK -path ./$outputDir/WORK
analyze -f sverilog -lib WORK $my_verilog_files analyze -f sverilog -lib WORK $my_verilog_files
elaborate $my_toplevel -lib WORK elaborate $my_toplevel -lib WORK

View File

@ -3,44 +3,62 @@
import subprocess import subprocess
from multiprocessing import Pool from multiprocessing import Pool
import time import argparse
import sys
def runSynth(config, tech, freq): def runSynth(config, tech, freq, maxopt):
global pool global pool
command = "make synth DESIGN=wallypipelinedcore CONFIG={} TECH={} DRIVE=FLOP FREQ={} MAXOPT=1 MAXCORES=1".format(config, tech, freq) command = "make synth DESIGN=wallypipelinedcore CONFIG={} TECH={} DRIVE=FLOP FREQ={} MAXOPT={} MAXCORES=1".format(config, tech, freq, maxopt)
pool.map(mask, [command]) pool.map(mask, [command])
def mask(command): def mask(command):
subprocess.Popen(command, shell=True) subprocess.Popen(command, shell=True)
testFreq = [3000, 10000] def freshStart():
out = subprocess.check_output(['bash','-c', 'make fresh'])
for x in out.decode("utf-8").split('\n')[:-1]:
print(x)
return
if __name__ == '__main__': if __name__ == '__main__':
i = 0
techs = ['sky90', 'tsmc28'] techs = ['sky90', 'tsmc28']
synthsToRun = [] allConfigs = ['rv32gc', 'rv32ic', 'rv64gc', 'rv64ic', 'rv32e', 'rv32i', 'rv64i']
tech = techs[i] freqVaryPct = [-20, -12, -8, -6, -4, -2, 0, 2, 4, 6, 8, 12, 20]
freq = testFreq[i]
arr = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
pool = Pool() pool = Pool()
staggerPeriod = 60 #seconds
typeToRun = sys.argv[1] parser = argparse.ArgumentParser()
if 'configs' in typeToRun: parser.add_argument("-s", "--freqsweep", type=int, help = "Synthesize wally with target frequencies at given MHz and +/- 2, 4, 6, 8 %%")
parser.add_argument("-c", "--configsweep", action='store_true', help = "Synthesize wally with configurations 32e, 32ic, 64ic, 32gc, and 64gc")
parser.add_argument("-f", "--featuresweep", action='store_true', help = "Synthesize wally with features turned off progressively to visualize critical path")
parser.add_argument("-v", "--version", choices=allConfigs, help = "Configuration of wally")
parser.add_argument("-t", "--targetfreq", type=int, help = "Target frequncy")
parser.add_argument("-e", "--tech", choices=techs, help = "Technology")
parser.add_argument("-o", "--maxopt", action='store_true', help = "Turn on MAXOPT")
args = parser.parse_args()
freq = args.targetfreq if args.targetfreq else 3000
tech = args.tech if args.tech else 'sky90'
maxopt = int(args.maxopt)
if args.freqsweep:
sc = args.freqsweep
config = args.version if args.version else 'rv32e'
freshStart()
for freq in [round(sc+sc*x/100) for x in freqVaryPct]: # rv32e freq sweep
runSynth(config, tech, freq, maxopt)
if args.configsweep:
freshStart()
for config in ['rv32gc', 'rv32ic', 'rv64gc', 'rv64ic', 'rv32e']: # configs for config in ['rv32gc', 'rv32ic', 'rv64gc', 'rv64ic', 'rv32e']: # configs
config = config + '_orig' # until memory integrated config = config + '_orig' # until memory integrated
runSynth(config, tech, freq) runSynth(config, tech, freq, maxopt)
time.sleep(staggerPeriod) if args.featuresweep:
elif 'features' in typeToRun: freshStart()
v = args.version if args.version else 'rv64gc'
for mod in ['FPUoff', 'noMulDiv', 'noPriv', 'PMP0', 'PMP16']: # rv64gc path variations for mod in ['FPUoff', 'noMulDiv', 'noPriv', 'PMP0', 'PMP16']: # rv64gc path variations
config = 'rv64gc_' + mod config = v + '_' + mod
runSynth(config, tech, freq) runSynth(config, tech, freq, maxopt)
time.sleep(staggerPeriod)
elif 'freqs' in typeToRun:
sc = int(sys.argv[2])
config = 'rv32e'
for freq in [round(sc+sc*x/100) for x in arr]: # rv32e freq sweep
runSynth(config, tech, freq)