Remove barstools tests

This commit is contained in:
Jerry Zhao
2024-04-19 11:07:01 -07:00
parent 33a1fe3f7b
commit ac11f6dbd1
24 changed files with 0 additions and 8399 deletions

View File

@@ -1,231 +0,0 @@
module ExampleTopModuleWithBB_PadFrame(
output clock_Int,
output reset_Int,
output [14:0] io_a_Int,
output [14:0] io_b_Int,
output [13:0] io_c_Int,
input [15:0] io_x_Int,
input [15:0] io_y_Int,
input [15:0] io_z_Int,
input [4:0] io_v_0_Int,
input [4:0] io_v_1_Int,
input [4:0] io_v_2_Int,
input clock_Ext,
input reset_Ext,
input [14:0] io_a_Ext,
input [14:0] io_b_Ext,
input [13:0] io_c_Ext,
output [15:0] io_x_Ext,
output [15:0] io_y_Ext,
output [15:0] io_z_Ext,
inout [2:0] io_analog1_Ext,
inout [2:0] io_analog2_Ext,
output [4:0] io_v_0_Ext,
output [4:0] io_v_1_Ext,
output [4:0] io_v_2_Ext
);
wire pad_digital_from_tristate_foundry_vertical_input_array_reset_in;
wire pad_digital_from_tristate_foundry_vertical_input_array_reset_out;
wire [14:0] pad_digital_from_tristate_foundry_horizontal_input_array_io_a_in;
wire [14:0] pad_digital_from_tristate_foundry_horizontal_input_array_io_a_out;
wire [14:0] pad_digital_from_tristate_foundry_horizontal_input_array_io_b_in;
wire [14:0] pad_digital_from_tristate_foundry_horizontal_input_array_io_b_out;
wire [13:0] pad_digital_from_tristate_foundry_horizontal_input_array_io_c_in;
wire [13:0] pad_digital_from_tristate_foundry_horizontal_input_array_io_c_out;
wire [15:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_x_in;
wire [15:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_x_out;
wire [15:0] pad_digital_from_tristate_foundry_vertical_output_array_io_z_in;
wire [15:0] pad_digital_from_tristate_foundry_vertical_output_array_io_z_out;
wire [4:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0_in;
wire [4:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0_out;
wire [4:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1_in;
wire [4:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1_out;
wire [4:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2_in;
wire [4:0] pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2_out;
pad_digital_from_tristate_foundry_vertical_input_array #(.WIDTH(1)) pad_digital_from_tristate_foundry_vertical_input_array_reset (
.in(pad_digital_from_tristate_foundry_vertical_input_array_reset_in),
.out(pad_digital_from_tristate_foundry_vertical_input_array_reset_out)
);
pad_digital_from_tristate_foundry_horizontal_input_array #(.WIDTH(15)) pad_digital_from_tristate_foundry_horizontal_input_array_io_a (
.in(pad_digital_from_tristate_foundry_horizontal_input_array_io_a_in),
.out(pad_digital_from_tristate_foundry_horizontal_input_array_io_a_out)
);
pad_digital_from_tristate_foundry_horizontal_input_array #(.WIDTH(15)) pad_digital_from_tristate_foundry_horizontal_input_array_io_b (
.in(pad_digital_from_tristate_foundry_horizontal_input_array_io_b_in),
.out(pad_digital_from_tristate_foundry_horizontal_input_array_io_b_out)
);
pad_digital_from_tristate_foundry_horizontal_input_array #(.WIDTH(14)) pad_digital_from_tristate_foundry_horizontal_input_array_io_c (
.in(pad_digital_from_tristate_foundry_horizontal_input_array_io_c_in),
.out(pad_digital_from_tristate_foundry_horizontal_input_array_io_c_out)
);
pad_digital_from_tristate_foundry_horizontal_output_array #(.WIDTH(16)) pad_digital_from_tristate_foundry_horizontal_output_array_io_x (
.in(pad_digital_from_tristate_foundry_horizontal_output_array_io_x_in),
.out(pad_digital_from_tristate_foundry_horizontal_output_array_io_x_out)
);
pad_digital_from_tristate_foundry_vertical_output_array #(.WIDTH(16)) pad_digital_from_tristate_foundry_vertical_output_array_io_z (
.in(pad_digital_from_tristate_foundry_vertical_output_array_io_z_in),
.out(pad_digital_from_tristate_foundry_vertical_output_array_io_z_out)
);
pad_analog_fast_custom_horizontal_array #(.WIDTH(3)) pad_analog_fast_custom_horizontal_array_io_analog1 (
.io(io_analog1_Ext)
);
pad_analog_slow_foundry_vertical_array #(.WIDTH(3)) pad_analog_slow_foundry_vertical_array_io_analog2 (
.io(io_analog2_Ext)
);
pad_digital_from_tristate_foundry_horizontal_output_array #(.WIDTH(5)) pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0 (
.in(pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0_in),
.out(pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0_out)
);
pad_digital_from_tristate_foundry_horizontal_output_array #(.WIDTH(5)) pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1 (
.in(pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1_in),
.out(pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1_out)
);
pad_digital_from_tristate_foundry_horizontal_output_array #(.WIDTH(5)) pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2 (
.in(pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2_in),
.out(pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2_out)
);
pad_supply_vdd_horizontal pad_supply_vdd_horizontal_left_0 (
);
pad_supply_vdd_horizontal pad_supply_vdd_horizontal_left_1 (
);
pad_supply_vdd_horizontal pad_supply_vdd_horizontal_left_2 (
);
pad_supply_vdd_vertical pad_supply_vdd_vertical_bottom_0 (
);
pad_supply_vdd_vertical pad_supply_vdd_vertical_bottom_1 (
);
pad_supply_vss_horizontal pad_supply_vss_horizontal_right_0 (
);
assign clock_Int = clock_Ext;
assign reset_Int = pad_digital_from_tristate_foundry_vertical_input_array_reset_out;
assign io_a_Int = pad_digital_from_tristate_foundry_horizontal_input_array_io_a_out;
assign io_b_Int = pad_digital_from_tristate_foundry_horizontal_input_array_io_b_out;
assign io_c_Int = $signed(pad_digital_from_tristate_foundry_horizontal_input_array_io_c_out);
assign io_x_Ext = pad_digital_from_tristate_foundry_horizontal_output_array_io_x_out;
assign io_y_Ext = io_y_Int;
assign io_z_Ext = $signed(pad_digital_from_tristate_foundry_vertical_output_array_io_z_out);
assign io_v_0_Ext = pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0_out;
assign io_v_1_Ext = pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1_out;
assign io_v_2_Ext = pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2_out;
assign pad_digital_from_tristate_foundry_vertical_input_array_reset_in = reset_Ext;
assign pad_digital_from_tristate_foundry_horizontal_input_array_io_a_in = io_a_Ext;
assign pad_digital_from_tristate_foundry_horizontal_input_array_io_b_in = io_b_Ext;
assign pad_digital_from_tristate_foundry_horizontal_input_array_io_c_in = $unsigned(io_c_Ext);
assign pad_digital_from_tristate_foundry_horizontal_output_array_io_x_in = io_x_Int;
assign pad_digital_from_tristate_foundry_vertical_output_array_io_z_in = $unsigned(io_z_Int);
assign pad_digital_from_tristate_foundry_horizontal_output_array_io_v_0_in = io_v_0_Int;
assign pad_digital_from_tristate_foundry_horizontal_output_array_io_v_1_in = io_v_1_Int;
assign pad_digital_from_tristate_foundry_horizontal_output_array_io_v_2_in = io_v_2_Int;
endmodule
module ExampleTopModuleWithBB(
input clock,
input reset,
input [14:0] io_a,
input [14:0] io_b,
input [13:0] io_c,
output [15:0] io_x,
output [15:0] io_y,
output [15:0] io_z,
inout [2:0] io_analog1,
inout [2:0] io_analog2,
output [4:0] io_v_0,
output [4:0] io_v_1,
output [4:0] io_v_2
);
wire ExampleTopModuleWithBB_PadFrame_clock_Int;
wire ExampleTopModuleWithBB_PadFrame_reset_Int;
wire [14:0] ExampleTopModuleWithBB_PadFrame_io_a_Int;
wire [14:0] ExampleTopModuleWithBB_PadFrame_io_b_Int;
wire [13:0] ExampleTopModuleWithBB_PadFrame_io_c_Int;
wire [15:0] ExampleTopModuleWithBB_PadFrame_io_x_Int;
wire [15:0] ExampleTopModuleWithBB_PadFrame_io_y_Int;
wire [15:0] ExampleTopModuleWithBB_PadFrame_io_z_Int;
wire [4:0] ExampleTopModuleWithBB_PadFrame_io_v_0_Int;
wire [4:0] ExampleTopModuleWithBB_PadFrame_io_v_1_Int;
wire [4:0] ExampleTopModuleWithBB_PadFrame_io_v_2_Int;
wire ExampleTopModuleWithBB_PadFrame_clock_Ext;
wire ExampleTopModuleWithBB_PadFrame_reset_Ext;
wire [14:0] ExampleTopModuleWithBB_PadFrame_io_a_Ext;
wire [14:0] ExampleTopModuleWithBB_PadFrame_io_b_Ext;
wire [13:0] ExampleTopModuleWithBB_PadFrame_io_c_Ext;
wire [15:0] ExampleTopModuleWithBB_PadFrame_io_x_Ext;
wire [15:0] ExampleTopModuleWithBB_PadFrame_io_y_Ext;
wire [15:0] ExampleTopModuleWithBB_PadFrame_io_z_Ext;
wire [4:0] ExampleTopModuleWithBB_PadFrame_io_v_0_Ext;
wire [4:0] ExampleTopModuleWithBB_PadFrame_io_v_1_Ext;
wire [4:0] ExampleTopModuleWithBB_PadFrame_io_v_2_Ext;
wire ExampleTopModuleWithBB_Internal_clock;
wire ExampleTopModuleWithBB_Internal_reset;
wire [14:0] ExampleTopModuleWithBB_Internal_io_a;
wire [14:0] ExampleTopModuleWithBB_Internal_io_b;
wire [13:0] ExampleTopModuleWithBB_Internal_io_c;
wire [15:0] ExampleTopModuleWithBB_Internal_io_x;
wire [15:0] ExampleTopModuleWithBB_Internal_io_y;
wire [15:0] ExampleTopModuleWithBB_Internal_io_z;
wire [4:0] ExampleTopModuleWithBB_Internal_io_v_0;
wire [4:0] ExampleTopModuleWithBB_Internal_io_v_1;
wire [4:0] ExampleTopModuleWithBB_Internal_io_v_2;
ExampleTopModuleWithBB_PadFrame ExampleTopModuleWithBB_PadFrame (
.clock_Int(ExampleTopModuleWithBB_PadFrame_clock_Int),
.reset_Int(ExampleTopModuleWithBB_PadFrame_reset_Int),
.io_a_Int(ExampleTopModuleWithBB_PadFrame_io_a_Int),
.io_b_Int(ExampleTopModuleWithBB_PadFrame_io_b_Int),
.io_c_Int(ExampleTopModuleWithBB_PadFrame_io_c_Int),
.io_x_Int(ExampleTopModuleWithBB_PadFrame_io_x_Int),
.io_y_Int(ExampleTopModuleWithBB_PadFrame_io_y_Int),
.io_z_Int(ExampleTopModuleWithBB_PadFrame_io_z_Int),
.io_v_0_Int(ExampleTopModuleWithBB_PadFrame_io_v_0_Int),
.io_v_1_Int(ExampleTopModuleWithBB_PadFrame_io_v_1_Int),
.io_v_2_Int(ExampleTopModuleWithBB_PadFrame_io_v_2_Int),
.clock_Ext(ExampleTopModuleWithBB_PadFrame_clock_Ext),
.reset_Ext(ExampleTopModuleWithBB_PadFrame_reset_Ext),
.io_a_Ext(ExampleTopModuleWithBB_PadFrame_io_a_Ext),
.io_b_Ext(ExampleTopModuleWithBB_PadFrame_io_b_Ext),
.io_c_Ext(ExampleTopModuleWithBB_PadFrame_io_c_Ext),
.io_x_Ext(ExampleTopModuleWithBB_PadFrame_io_x_Ext),
.io_y_Ext(ExampleTopModuleWithBB_PadFrame_io_y_Ext),
.io_z_Ext(ExampleTopModuleWithBB_PadFrame_io_z_Ext),
.io_analog1_Ext(io_analog1),
.io_analog2_Ext(io_analog2),
.io_v_0_Ext(ExampleTopModuleWithBB_PadFrame_io_v_0_Ext),
.io_v_1_Ext(ExampleTopModuleWithBB_PadFrame_io_v_1_Ext),
.io_v_2_Ext(ExampleTopModuleWithBB_PadFrame_io_v_2_Ext)
);
ExampleTopModuleWithBB_Internal ExampleTopModuleWithBB_Internal (
.clock(ExampleTopModuleWithBB_Internal_clock),
.reset(ExampleTopModuleWithBB_Internal_reset),
.io_a(ExampleTopModuleWithBB_Internal_io_a),
.io_b(ExampleTopModuleWithBB_Internal_io_b),
.io_c(ExampleTopModuleWithBB_Internal_io_c),
.io_x(ExampleTopModuleWithBB_Internal_io_x),
.io_y(ExampleTopModuleWithBB_Internal_io_y),
.io_z(ExampleTopModuleWithBB_Internal_io_z),
.io_analog1(io_analog1),
.io_analog2(io_analog2),
.io_v_0(ExampleTopModuleWithBB_Internal_io_v_0),
.io_v_1(ExampleTopModuleWithBB_Internal_io_v_1),
.io_v_2(ExampleTopModuleWithBB_Internal_io_v_2)
);
assign io_x = ExampleTopModuleWithBB_PadFrame_io_x_Ext;
assign io_y = ExampleTopModuleWithBB_PadFrame_io_y_Ext;
assign io_z = ExampleTopModuleWithBB_PadFrame_io_z_Ext;
assign io_v_0 = ExampleTopModuleWithBB_PadFrame_io_v_0_Ext;
assign io_v_1 = ExampleTopModuleWithBB_PadFrame_io_v_1_Ext;
assign io_v_2 = ExampleTopModuleWithBB_PadFrame_io_v_2_Ext;
assign ExampleTopModuleWithBB_PadFrame_io_x_Int = ExampleTopModuleWithBB_Internal_io_x;
assign ExampleTopModuleWithBB_PadFrame_io_y_Int = ExampleTopModuleWithBB_Internal_io_y;
assign ExampleTopModuleWithBB_PadFrame_io_z_Int = ExampleTopModuleWithBB_Internal_io_z;
assign ExampleTopModuleWithBB_PadFrame_io_v_0_Int = ExampleTopModuleWithBB_Internal_io_v_0;
assign ExampleTopModuleWithBB_PadFrame_io_v_1_Int = ExampleTopModuleWithBB_Internal_io_v_1;
assign ExampleTopModuleWithBB_PadFrame_io_v_2_Int = ExampleTopModuleWithBB_Internal_io_v_2;
assign ExampleTopModuleWithBB_PadFrame_clock_Ext = clock;
assign ExampleTopModuleWithBB_PadFrame_reset_Ext = reset;
assign ExampleTopModuleWithBB_PadFrame_io_a_Ext = io_a;
assign ExampleTopModuleWithBB_PadFrame_io_b_Ext = io_b;
assign ExampleTopModuleWithBB_PadFrame_io_c_Ext = io_c;
assign ExampleTopModuleWithBB_Internal_clock = ExampleTopModuleWithBB_PadFrame_clock_Int;
assign ExampleTopModuleWithBB_Internal_reset = ExampleTopModuleWithBB_PadFrame_reset_Int;
assign ExampleTopModuleWithBB_Internal_io_a = ExampleTopModuleWithBB_PadFrame_io_a_Int;
assign ExampleTopModuleWithBB_Internal_io_b = ExampleTopModuleWithBB_PadFrame_io_b_Int;
assign ExampleTopModuleWithBB_Internal_io_c = ExampleTopModuleWithBB_PadFrame_io_c_Int;
endmodule

View File

@@ -1,41 +0,0 @@
[
{
"name" : "example",
"type" : "flipchip",
"bump_dimensions" : [27,27],
"bump_locations" : [
["-", "GND", "VDDC0_SEL[0]", "VDDC0_SEL[1]", "VDDC1_SEL[0]", "VDDC1_SEL[1]", "VDDC2_SEL[0]", "VDDC2_SEL[1]", "VDDC3_SEL[0]", "VDDC3_SEL[1]", "VDDC0_EN", "VDDC1_EN", "VDDC2_EN", "VDDC3_EN", "CCLK0", "CCLK1", "CCLK2", "RESET", "BOOT", "I2C_SDA", "I2C_SCL", "SPI_SCLK", "SPI_MOSI", "SPI_MISO", "SPI_SS_L", "GND", "-"],
[ "GND", "", "", "", "GND", "GND","GPIO[1]", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8","UART_RX","UART_TX", "GND", "GND", "GND", "GND", "", "", "", "GND"],
["TXP0", "VDDA", "VDDA", "GND", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "GND", "VDDA", "VDDA", "TXP4"],
["TXN0", "VDDA", "VDDA", "GND", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "GND", "VDDA", "VDDA", "TXN4"],
[ "GND", "", "", "", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "", "", "", "GND"],
["RXP0", "VDDA", "VDDA", "GND", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "GND", "VDDA", "VDDA", "RXP4"],
["RXN0", "VDDA", "VDDA", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "VDDA", "VDDA", "RXN4"],
[ "GND", "", "", "", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "", "", "", "GND"],
["TXP1", "VDDA", "VDDA", "GND", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "GND", "VDDA", "VDDA", "TXP5"],
["TXN1", "VDDA", "VDDA", "GND", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "GND", "VDDA", "VDDA", "TXN5"],
[ "GND", "", "", "", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "", "", "", "GND"],
["RXP1", "VDDA", "VDDA", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "VDDA", "VDDA", "RXP5"],
["RXN1", "VDDA", "VDDA", "GND", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "GND", "GND", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "GND", "VDDA", "VDDA", "RXN5"],
[ "GND", "", "", "", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "VDDC1", "GND", "GND", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC0", "VDDC0", "VDDC0", "VDDC0", "", "", "", "GND"],
["TXP2", "VDDA", "VDDA", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "VDDA", "VDDA", "TXP6"],
["TXN2", "VDDA", "VDDA", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "VDDA", "VDDA", "TXN6"],
[ "GND", "", "", "", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "", "", "", "GND"],
["RXP2", "VDDA", "VDDA", "GND", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC2", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "VDDC3", "GND", "VDDA", "VDDA", "RXP6"],
["RXN2", "VDDA", "VDDA", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "VDDA", "VDDA", "RXN6"],
[ "GND", "", "", "", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "GND", "", "", "", "GND"],
["TXP3", "VDDA", "VDDA", "GND", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "GND", "VDDA", "VDDA", "TXP7"],
["TXN3", "VDDA", "VDDA", "GND", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "VDD0V8", "GND", "VDDA", "VDDA", "TXN7"],
[ "GND", "", "", "", "-", "SERIAL_IN_READY", "-", "-", "SERIAL_IN_VALID", "-", "-", "-", "-", "", "-", "SERIAL_OUT_VALID", "-", "-", "SERIAL_OUT_READY", "-", "-", "GPIO[0]", "-", "", "", "", "GND"],
["RXP3", "VDDA", "VDDA", "GND", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "GND", "VDDA", "VDDA", "RXP7"],
["RXN3", "VDDA", "VDDA", "GND", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "GND", "VDDA", "VDDA", "RXN7"],
[ "GND", "", "", "", "GND", "GND", "GND", "GND", "GND", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "VDD1V8", "GND", "GND", "GND", "GND", "GND", "", "", "", "GND"],
["-", "GND", "REFCLK0P", "REFCLK0N", "GND", "SERIAL_OUT[0]", "SERIAL_OUT[1]", "SERIAL_OUT[2]", "SERIAL_OUT[3]", "SERIAL_IN[0]", "SERIAL_IN[1]", "SERIAL_IN[2]", "SERIAL_IN[3]", "JTAG_TMS", "JTAG_TCK", "JTAG_TDO", "JTAG_TDI", "CLKSEL", "PLLCLK_OUT", "GND", "PLLREFCLKP", "PLLREFCLKN", "GND", "REFCLK1P", "REFCLK1N", "GND", "-"]
]
}
]

View File

@@ -1,663 +0,0 @@
[
{
"name": "My IOs",
"type": "io_properties",
"top": "EAGLE",
"ios": [
{
"name": "GND",
"type": "ground"
},
{
"name": "VDD0V8",
"type": "power"
},
{
"name": "VDD1V8",
"type": "power"
},
{
"name": "VDDC0",
"type": "power"
},
{
"name": "VDDC1",
"type": "power"
},
{
"name": "VDDC2",
"type": "power"
},
{
"name": "VDDC3",
"type": "power"
},
{
"name": "VDDA",
"type": "power"
},
{
"name": "VDDC0_SEL[1:0]",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDC1_SEL[1:0]",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDC2_SEL[1:0]",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDC3_SEL[1:0]",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDDC0_EN",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDDC1_EN",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDDC2_EN",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "VDDDC3_EN",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "CCLK0",
"type": "digital",
"direction": "input",
"termination": 50,
"termination_type": "single",
"termination_reference": "GND"
},
{
"name": "CCLK1",
"type": "digital",
"direction": "input",
"termination": 50,
"termination_type": "single",
"termination_reference": "GND"
},
{
"name": "CCLK2",
"type": "digital",
"direction": "input",
"termination": 50,
"termination_type": "single",
"termination_reference": "GND"
},
{
"name": "RESET",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "BOOT",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "I2C_SDA",
"type": "digital",
"direction": "inout",
"termination": "open-drain"
},
{
"name": "I2C_SCL",
"type": "digital",
"direction": "inout",
"termination": "open-drain"
},
{
"name": "SPI_SCLK",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "SPI_MOSI",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "SPI_MISO",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "SPI_SS_L",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "GPIO[1:0]",
"type": "digital",
"direction": "inout",
"termination": "CMOS"
},
{
"name": "UART_RX",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "UART_TX",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "SERIAL_IN_READY",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "SERIAL_IN_VALID",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "SERIAL_OUT_READY",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "SERIAL_OUT_VALID",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "SERIAL_OUT[3:0]",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "SERIAL_IN[3:0]",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "REFCLK0P",
"type": "analog",
"direction": "input",
"match": [
"REFCLK0N"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "REFCLK0N",
"type": "analog",
"direction": "input",
"match": [
"REFCLK0P"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "REFCLK1N",
"type": "analog",
"direction": "input",
"match": [
"REFCLK1P"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "REFCLK1P",
"type": "analog",
"direction": "input",
"match": [
"REFCLK1N"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "PLLREFCLKP",
"type": "analog",
"direction": "input",
"match": [
"PLLREFCLKP"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "PLLREFCLKN",
"type": "analog",
"direction": "input",
"match": [
"PLLREFCLKP"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "JTAG_TMS",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "JTAG_TCK",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "JTAG_TDI",
"type": "digital",
"direction": "input",
"termination": "CMOS"
},
{
"name": "JTAG_TDO",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "PLLCLK_OUT",
"type": "digital",
"direction": "output",
"termination": "CMOS"
},
{
"name": "TXP0",
"type": "analog",
"direction": "output",
"match": [
"TXN0"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN0",
"type": "analog",
"direction": "output",
"match": [
"TXP0"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP0",
"type": "analog",
"direction": "output",
"match": [
"RXN0"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN1",
"type": "analog",
"direction": "input",
"match": [
"RXP1"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP1",
"type": "analog",
"direction": "output",
"match": [
"TXN1"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN1",
"type": "analog",
"direction": "output",
"match": [
"TXP1"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP1",
"type": "analog",
"direction": "output",
"match": [
"RXN1"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN1",
"type": "analog",
"direction": "input",
"match": [
"RXP1"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP2",
"type": "analog",
"direction": "output",
"match": [
"TXN2"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN2",
"type": "analog",
"direction": "output",
"match": [
"TXP2"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP2",
"type": "analog",
"direction": "output",
"match": [
"RXN2"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN2",
"type": "analog",
"direction": "input",
"match": [
"RXP2"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP3",
"type": "analog",
"direction": "output",
"match": [
"TXN3"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN3",
"type": "analog",
"direction": "output",
"match": [
"TXP3"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP3",
"type": "analog",
"direction": "output",
"match": [
"RXN3"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN3",
"type": "analog",
"direction": "input",
"match": [
"RXP3"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP4",
"type": "analog",
"direction": "output",
"match": [
"TXN4"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN4",
"type": "analog",
"direction": "output",
"match": [
"TXP4"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP4",
"type": "analog",
"direction": "output",
"match": [
"RXN4"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN4",
"type": "analog",
"direction": "input",
"match": [
"RXP4"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP5",
"type": "analog",
"direction": "output",
"match": [
"TXN5"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN5",
"type": "analog",
"direction": "output",
"match": [
"TXP5"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP5",
"type": "analog",
"direction": "output",
"match": [
"RXN5"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN5",
"type": "analog",
"direction": "input",
"match": [
"RXP5"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP6",
"type": "analog",
"direction": "output",
"match": [
"TXN6"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN6",
"type": "analog",
"direction": "output",
"match": [
"TXP6"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP6",
"type": "analog",
"direction": "output",
"match": [
"RXN6"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN6",
"type": "analog",
"direction": "input",
"match": [
"RXP6"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXP7",
"type": "analog",
"direction": "output",
"match": [
"TXN7"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "TXN7",
"type": "analog",
"direction": "output",
"match": [
"TXP7"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXP7",
"type": "analog",
"direction": "output",
"match": [
"RXN7"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
},
{
"name": "RXN7",
"type": "analog",
"direction": "input",
"match": [
"RXP7"
],
"termination": 100,
"termination_type": "differential",
"termination_reference": "GND"
}
]
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
[
{
"type": "sram",
"name": "fake_mem",
"width": 64,
"depth": "512",
"mux": 4,
"family": "1rw",
"ports": [
{
"address port name": "addr",
"address port polarity": "active high",
"clock port name": "clk",
"clock port polarity": "positive edge",
"write enable port name": "wen",
"write enable port polarity": "active high",
"read enable port name": "ren",
"read enable port polarity": "active high",
"output port name": "dataout",
"output port polarity": "active high",
"input port name": "datain",
"input port polarity": "active high",
"mask port name": "mport",
"mask port polarity": "active low",
"mask granularity": 1
}
]
}
]

View File

@@ -1,26 +0,0 @@
[
{
"type": "sram",
"name": "fake_mem",
"width": 64,
"depth": "4096",
"mux": 4,
"family": "1rw",
"ports": [
{
"address port name": "addr",
"address port polarity": "active high",
"clock port name": "clk",
"clock port polarity": "positive edge",
"write enable port name": "wen",
"write enable port polarity": "active high",
"read enable port name": "ren",
"read enable port polarity": "active high",
"output port name": "dataout",
"output port polarity": "active high",
"input port name": "datain",
"input port polarity": "active high"
}
]
}
]

View File

@@ -1,114 +0,0 @@
package barstools.macros
import mdf.macrolib.SRAMMacro
/** Tests to check that the cost function mechanism is working properly. */
/** A test metric that simply favours memories with smaller widths, to test that
* the metric is chosen properly.
*/
object TestMinWidthMetric extends CostMetric with CostMetricCompanion {
// Smaller width = lower cost = favoured
override def cost(mem: Macro, lib: Macro): Option[Double] = Some(lib.src.width)
override def commandLineParams() = Map()
override def name() = "TestMinWidthMetric"
override def construct(m: Map[String, String]): CostMetric = TestMinWidthMetric
}
/** Test that cost metric selection is working. */
class SelectCostMetric extends MacroCompilerSpec with HasSRAMGenerator {
val mem = s"mem-SelectCostMetric.json"
val lib = s"lib-SelectCostMetric.json"
val v = s"SelectCostMetric.v"
// Cost metrics must be registered for them to work with the command line.
CostMetric.registerCostMetric(TestMinWidthMetric)
override val costMetric: Option[CostMetric] = Some(TestMinWidthMetric)
val libSRAMs = Seq(
SRAMMacro(
name = "SRAM_WIDTH_128",
depth = BigInt(1024),
width = 128,
family = "1rw",
ports = Seq(
generateReadWritePort("", 128, BigInt(1024))
)
),
SRAMMacro(
name = "SRAM_WIDTH_64",
depth = BigInt(1024),
width = 64,
family = "1rw",
ports = Seq(
generateReadWritePort("", 64, BigInt(1024))
)
),
SRAMMacro(
name = "SRAM_WIDTH_32",
depth = BigInt(1024),
width = 32,
family = "1rw",
ports = Seq(
generateReadWritePort("", 32, BigInt(1024))
)
)
)
val memSRAMs = Seq(generateSRAM("target_memory", "", 128, BigInt(1024)))
writeToLib(lib, libSRAMs)
writeToMem(mem, memSRAMs)
// Check that the min width SRAM was chosen, even though it is less efficient.
val output =
"""
circuit target_memory :
module target_memory :
input addr : UInt<10>
input clk : Clock
input din : UInt<128>
output dout : UInt<128>
input write_en : UInt<1>
inst mem_0_0 of SRAM_WIDTH_32
inst mem_0_1 of SRAM_WIDTH_32
inst mem_0_2 of SRAM_WIDTH_32
inst mem_0_3 of SRAM_WIDTH_32
mem_0_0.clk <= clk
mem_0_0.addr <= addr
node dout_0_0 = bits(mem_0_0.dout, 31, 0)
mem_0_0.din <= bits(din, 31, 0)
mem_0_0.write_en <= and(and(and(write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_1.clk <= clk
mem_0_1.addr <= addr
node dout_0_1 = bits(mem_0_1.dout, 31, 0)
mem_0_1.din <= bits(din, 63, 32)
mem_0_1.write_en <= and(and(and(write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_2.clk <= clk
mem_0_2.addr <= addr
node dout_0_2 = bits(mem_0_2.dout, 31, 0)
mem_0_2.din <= bits(din, 95, 64)
mem_0_2.write_en <= and(and(and(write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_3.clk <= clk
mem_0_3.addr <= addr
node dout_0_3 = bits(mem_0_3.dout, 31, 0)
mem_0_3.din <= bits(din, 127, 96)
mem_0_3.write_en <= and(and(and(write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
node dout_0 = cat(dout_0_3, cat(dout_0_2, cat(dout_0_1, dout_0_0)))
dout <= mux(UInt<1>("h1"), dout_0, UInt<128>("h0"))
extmodule SRAM_WIDTH_32 :
input addr : UInt<10>
input clk : Clock
input din : UInt<32>
output dout : UInt<32>
input write_en : UInt<1>
defname = SRAM_WIDTH_32
"""
compileExecuteAndTest(mem, lib, v, output)
}

View File

@@ -1,120 +0,0 @@
package barstools.macros
// import firrtl.ir.Circuit
// import firrtl_interpreter.InterpretiveTester
// // Functional tests on memory compiler outputs.
// // Synchronous write and read back.
// class SynchronousReadAndWrite extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
// override lazy val width = 12
// override lazy val memDepth = BigInt(2048)
// override lazy val libDepth = BigInt(1024)
// compile(mem, lib, v, synflops = true)
// val result: Circuit = execute(mem, lib, synflops = true)
// it should "run with InterpretedTester" in {
// pending // Enable this when https://github.com/freechipsproject/firrtl-interpreter/pull/88 is snapshot-published
// val addr1 = 0
// val addr1val = 0xff
// val addr2 = 42
// val addr2val = 0xf0
// val addr3 = 1 << 10
// val addr3val = 1 << 10
// val tester = new InterpretiveTester(result.serialize)
// //~ tester.setVerbose()
// tester.poke("outer_write_en", 0)
// tester.step()
// // Write addresses and read them.
// tester.poke("outer_addr", addr1)
// tester.poke("outer_din", addr1val)
// tester.poke("outer_write_en", 1)
// tester.step()
// tester.poke("outer_write_en", 0)
// tester.step()
// tester.poke("outer_addr", addr2)
// tester.poke("outer_din", addr2val)
// tester.poke("outer_write_en", 1)
// tester.step()
// tester.poke("outer_write_en", 0)
// tester.step()
// tester.poke("outer_addr", addr3)
// tester.poke("outer_din", addr3val)
// tester.poke("outer_write_en", 1)
// tester.step()
// tester.poke("outer_write_en", 0)
// tester.step()
// tester.poke("outer_addr", addr1)
// tester.step()
// tester.expect("outer_dout", addr1val)
// tester.poke("outer_addr", addr2)
// tester.step()
// tester.expect("outer_dout", addr2val)
// tester.poke("outer_addr", addr3)
// tester.step()
// tester.expect("outer_dout", addr3val)
// }
// }
// // Test to verify that the circuit doesn't read combinationally based on addr
// // between two submemories.
// class DontReadCombinationally extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
// override lazy val width = 8
// override lazy val memDepth = BigInt(2048)
// override lazy val libDepth = BigInt(1024)
// compile(mem, lib, v, synflops = true)
// val result: Circuit = execute(mem, lib, synflops = true)
// it should "run with InterpretedTester" in {
// pending // Enable this when https://github.com/freechipsproject/firrtl-interpreter/pull/88 is snapshot-published
// val addr1 = 0
// val addr1a = 1
// val addr2 = 1 << 10
// val tester = new InterpretiveTester(result.serialize)
// //~ tester.setVerbose()
// tester.poke("outer_write_en", 0)
// tester.step()
// // Write two addresses, one in the lower submemory and the other in the
// // higher submemory.
// tester.poke("outer_addr", addr1)
// tester.poke("outer_din", 0x11)
// tester.poke("outer_write_en", 1)
// tester.step()
// tester.poke("outer_addr", addr1a)
// tester.poke("outer_din", 0x1a)
// tester.poke("outer_write_en", 1)
// tester.step()
// tester.poke("outer_addr", addr2)
// tester.poke("outer_din", 0xaa)
// tester.poke("outer_write_en", 1)
// tester.step()
// tester.poke("outer_write_en", 0)
// tester.poke("outer_addr", addr1)
// tester.step()
// // Test that there is no combinational read.
// tester.poke("outer_addr", addr1)
// tester.expect("outer_dout", 0x11)
// tester.poke("outer_addr", addr1a)
// tester.expect("outer_dout", 0x11)
// tester.poke("outer_addr", addr2)
// tester.expect("outer_dout", 0x11)
// // And upon step it should work again.
// tester.step()
// tester.expect("outer_addr", 0xaa)
// }
// }

View File

@@ -1,546 +0,0 @@
// See LICENSE for license details.
package barstools.macros
import firrtl.Parser.parse
import firrtl.ir.{Circuit, NoInfo}
import firrtl.passes.RemoveEmpty
import mdf.macrolib.SRAMMacro
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import java.io.File
abstract class MacroCompilerSpec extends AnyFlatSpec with Matchers {
import scala.language.implicitConversions
implicit def String2SomeString(i: String): Option[String] = Some(i)
val testDir: String = "test_run_dir/macros"
new File(testDir).mkdirs // Make sure the testDir exists
// Override these to change the prefixing of macroDir and testDir
val memPrefix: String = testDir
val libPrefix: String = testDir
val vPrefix: String = testDir
// Override this to use a different cost metric.
// If this is None, the compile() call will not have any -c/-cp arguments, and
// execute() will use CostMetric.default.
val costMetric: Option[CostMetric] = None
private def getCostMetric: CostMetric = costMetric.getOrElse(CostMetric.default)
private def costMetricCmdLine = {
costMetric match {
case None => Nil
case Some(m) =>
val name = m.name()
val params = m.commandLineParams()
List("-c", name) ++ params.flatMap { case (key, value) => List("-cp", key, value) }
}
}
private def args(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean) =
List("-m", mem, "-v", v) ++
(lib match {
case None => Nil
case Some(l) => List("-l", l)
}) ++
costMetricCmdLine ++
(if (synflops) List("--mode", "synflops") else Nil) ++
(if (useCompiler) List("--use-compiler") else Nil)
// Run the full compiler as if from the command line interface.
// Generates the Verilog; useful in testing since an error will throw an
// exception.
def compile(mem: String, lib: String, v: String, synflops: Boolean): Unit = {
compile(mem, Some(lib), v, synflops)
}
def compile(mem: String, lib: Option[String], v: String, synflops: Boolean, useCompiler: Boolean = false): Unit = {
val mem_full = concat(memPrefix, mem)
val lib_full = concat(libPrefix, lib)
val v_full = concat(vPrefix, v)
MacroCompiler.run(args(mem_full, lib_full, v_full, synflops, useCompiler))
}
// Helper functions to write macro libraries to the given files.
def writeToLib(lib: String, libs: Seq[mdf.macrolib.Macro]): Boolean = {
mdf.macrolib.Utils.writeMDFToPath(Some(concat(libPrefix, lib)), libs)
}
def writeToMem(mem: String, mems: Seq[mdf.macrolib.Macro]): Boolean = {
mdf.macrolib.Utils.writeMDFToPath(Some(concat(memPrefix, mem)), mems)
}
// Convenience function for running both compile, execute, and test at once.
def compileExecuteAndTest(
mem: String,
lib: Option[String],
v: String,
output: String,
synflops: Boolean = false,
useCompiler: Boolean = false
): Unit = {
compile(mem, lib, v, synflops, useCompiler)
val result = execute(mem, lib, synflops, useCompiler)
test(result, output)
}
// Compare FIRRTL outputs after reparsing output with ScalaTest ("should be").
def test(result: Circuit, output: String): Unit = {
val gold = RemoveEmpty.run(parse(output))
result.serialize should be(gold.serialize)
}
// Execute the macro compiler and returns a Circuit containing the output of
// the memory compiler.
def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean): Circuit =
execute(memFile, libFile, synflops, useCompiler = false)
def execute(memFile: Option[String], libFile: Option[String], synflops: Boolean, useCompiler: Boolean): Circuit = {
val mem_full = concat(memPrefix, memFile)
val lib_full = concat(libPrefix, libFile)
require(memFile.isDefined)
val mems: Seq[Macro] = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(mem_full)).get.map(new Macro(_))
val libs: Option[Seq[Macro]] = if (useCompiler) {
Utils.findSRAMCompiler(mdf.macrolib.Utils.readMDFFromPath(lib_full)).map { x =>
Utils.buildSRAMMacros(x).map(new Macro(_))
}
} else {
Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(lib_full)) match {
case Some(x) => Some(x.map(new Macro(_)))
case None => None
}
}
val macros = mems.map(_.blackbox)
val circuit = Circuit(NoInfo, macros, macros.last.name)
val passes = Seq(
new MacroCompilerPass(
Some(mems),
libs,
None,
None,
getCostMetric,
if (synflops) MacroCompilerAnnotation.Synflops else MacroCompilerAnnotation.Default
),
new SynFlopsPass(synflops, libs.getOrElse(mems)),
RemoveEmpty
)
val result: Circuit = passes.foldLeft(circuit)((c, pass) => pass.run(c))
result
}
// Helper method to deal with String + Option[String]
private def concat(a: String, b: String): String = { a + "/" + b }
private def concat(a: String, b: Option[String]): Option[String] = {
b match {
case Some(b2: String) => Some(a + "/" + b2)
case _ => None
}
}
}
// A collection of standard SRAM generators.
trait HasSRAMGenerator {
import mdf.macrolib._
import scala.language.implicitConversions
implicit def Int2SomeInt(i: Int): Option[Int] = Some(i)
implicit def BigInt2SomeBigInt(i: BigInt): Option[BigInt] = Some(i)
// Generate a standard (read/write/combo) port for testing.
// Helper methods for optional width argument
def generateTestPort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
maskGran: Option[Int] = None,
read: Boolean,
readEnable: Boolean = false,
write: Boolean,
writeEnable: Boolean = false
): MacroPort = {
val realPrefix = if (prefix == "") "" else prefix + "_"
MacroPort(
address = PolarizedPort(name = realPrefix + "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = realPrefix + "clk", polarity = PositiveEdge)),
readEnable = if (readEnable) Some(PolarizedPort(name = realPrefix + "read_en", polarity = ActiveHigh)) else None,
writeEnable =
if (writeEnable) Some(PolarizedPort(name = realPrefix + "write_en", polarity = ActiveHigh)) else None,
output = if (read) Some(PolarizedPort(name = realPrefix + "dout", polarity = ActiveHigh)) else None,
input = if (write) Some(PolarizedPort(name = realPrefix + "din", polarity = ActiveHigh)) else None,
maskPort = maskGran match {
case Some(_: Int) => Some(PolarizedPort(name = realPrefix + "mask", polarity = ActiveHigh))
case _ => None
},
maskGran = maskGran,
width = width,
depth = depth // These numbers don't matter here.
)
}
// Generate a read port for testing.
def generateReadPort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
readEnable: Boolean = false
): MacroPort = {
generateTestPort(prefix, width, depth, write = false, read = true, readEnable = readEnable)
}
// Generate a write port for testing.
def generateWritePort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
maskGran: Option[Int] = None,
writeEnable: Boolean = true
): MacroPort = {
generateTestPort(prefix, width, depth, maskGran = maskGran, write = true, read = false, writeEnable = writeEnable)
}
// Generate a simple read-write port for testing.
def generateReadWritePort(
prefix: String,
width: Option[Int],
depth: Option[BigInt],
maskGran: Option[Int] = None
): MacroPort = {
generateTestPort(prefix, width, depth, maskGran = maskGran, write = true, writeEnable = true, read = true)
}
// Generate a "simple" SRAM (active high/positive edge, 1 read-write port).
def generateSRAM(
name: String,
prefix: String,
width: Int,
depth: BigInt,
maskGran: Option[Int] = None,
extraPorts: Seq[MacroExtraPort] = List()
): SRAMMacro = {
SRAMMacro(
name = name,
width = width,
depth = depth,
family = "1rw",
ports = Seq(generateReadWritePort(prefix, width, depth, maskGran)),
extraPorts = extraPorts
)
}
// Generate a "simple" SRAM group (active high/positive edge, 1 read-write port).
def generateSimpleSRAMGroup(
prefix: String,
mux: Int,
depth: Range,
width: Range,
maskGran: Option[Int] = None
): SRAMGroup = {
SRAMGroup(
Seq("mygroup_", "width", "x", "depth", "_", "VT"),
"1rw",
Seq("svt", "lvt", "ulvt"),
mux,
depth,
width,
Seq(generateReadWritePort(prefix, None, None, maskGran))
)
}
// 'vt': ('svt','lvt','ulvt'), 'mux': 2, 'depth': range(16,513,8), 'width': range(8,289,2), 'ports': 1
// 'vt': ('svt','lvt','ulvt'), 'mux': 4, 'depth': range(32,1025,16), 'width': range(4,145), 'ports': 1}
def generateSRAMCompiler(name: String, prefix: String): mdf.macrolib.SRAMCompiler = {
SRAMCompiler(
name,
Seq(
generateSimpleSRAMGroup(prefix, 2, Range(16, 512, 8), Range(8, 288, 2)),
generateSimpleSRAMGroup(prefix, 4, Range(32, 1024, 16), Range(4, 144, 1))
)
)
}
}
// Generic "simple" test generator.
// Set up scaffolding for generating memories, files, etc.
// Override this generator to specify the expected FIRRTL output.
trait HasSimpleTestGenerator {
this: MacroCompilerSpec with HasSRAMGenerator =>
// Override these with "override lazy val".
// Why lazy? These are used in the constructor here so overriding non-lazily
// would be too late.
def useCompiler: Boolean = false
def memWidth: Int
def libWidth: Int
def memDepth: BigInt
def libDepth: BigInt
def memMaskGran: Option[Int] = None
def libMaskGran: Option[Int] = None
def extraPorts: Seq[mdf.macrolib.MacroExtraPort] = List()
def extraTag: String = ""
// "Effective" libMaskGran by considering write_enable.
val effectiveLibMaskGran: Int = libMaskGran.getOrElse(libWidth)
// Override this in the sub-generator if you need a more specific name.
// Defaults to using reflection to pull the name of the test using this
// generator.
def generatorType: String = this.getClass.getSimpleName
//require (memDepth >= libDepth)
// Convenience variables to check if a mask exists.
val memHasMask: Boolean = memMaskGran.isDefined
val libHasMask: Boolean = libMaskGran.isDefined
// We need to figure out how many mask bits there are in the mem.
val memMaskBits: Int = if (memHasMask) memWidth / memMaskGran.get else 0
val libMaskBits: Int = if (libHasMask) libWidth / libMaskGran.get else 0
val extraTagPrefixed: String = if (extraTag == "") "" else "-" + extraTag
val mem = s"mem-$generatorType$extraTagPrefixed.json"
val lib = s"lib-$generatorType$extraTagPrefixed.json"
val v = s"$generatorType$extraTagPrefixed.v"
lazy val mem_name = "target_memory"
val mem_addr_width: Int = MacroCompilerMath.ceilLog2(memDepth)
lazy val lib_name = "awesome_lib_mem"
val lib_addr_width: Int = MacroCompilerMath.ceilLog2(libDepth)
// Override these to change the port prefixes if needed.
def libPortPrefix: String = "lib"
def memPortPrefix: String = "outer"
// These generate "simple" SRAMs (1 masked read-write port) by default,
// but can be overridden if need be.
def generateLibSRAM(): SRAMMacro = generateSRAM(lib_name, libPortPrefix, libWidth, libDepth, libMaskGran, extraPorts)
def generateMemSRAM(): SRAMMacro = generateSRAM(mem_name, memPortPrefix, memWidth, memDepth, memMaskGran)
def libSRAM: SRAMMacro = generateLibSRAM()
def memSRAM: SRAMMacro = generateMemSRAM()
def libSRAMs: Seq[SRAMMacro] = Seq(libSRAM)
def memSRAMs: Seq[SRAMMacro] = Seq(memSRAM)
writeToLib(lib, libSRAMs)
writeToMem(mem, memSRAMs)
// For masks, width it's a bit tricky since we have to consider cases like
// memMaskGran = 4 and libMaskGran = 8.
// Consider the actually usable libWidth in cases like the above.
val usableLibWidth: Int =
if (memMaskGran.getOrElse(Int.MaxValue) < effectiveLibMaskGran) memMaskGran.get else libWidth
// Number of lib instances needed to hold the mem, in both directions.
// Round up (e.g. 1.5 instances = effectively 2 instances)
val depthInstances: Int = math.ceil(memDepth.toFloat / libDepth.toFloat).toInt
val widthInstances: Int = math.ceil(memWidth.toFloat / usableLibWidth).toInt
// Number of width bits in the last width-direction memory.
// e.g. if memWidth = 16 and libWidth = 8, this would be 8 since the last memory 0_1 has 8 bits of input width.
// e.g. if memWidth = 9 and libWidth = 8, this would be 1 since the last memory 0_1 has 1 bit of input width.
lazy val lastWidthBits: Int = if (memWidth % usableLibWidth == 0) usableLibWidth else memWidth % usableLibWidth
lazy val selectBits: Int = mem_addr_width - lib_addr_width
/** Convenience function to generate a mask statement.
* @param widthInst Width instance (mem_0_x)
* @param depthInst Depth instance (mem_x_0)
*/
def generateMaskStatement(widthInst: Int, depthInst: Int): String = {
// Width of this submemory.
val myMemWidth = if (widthInst == widthInstances - 1) lastWidthBits else usableLibWidth
// Base bit of this submemory.
// e.g. if libWidth is 8 and this is submemory 2 (0-indexed), then this
// would be 16.
val myBaseBit = usableLibWidth * widthInst
if (libMaskGran.isDefined) {
if (memMaskGran.isEmpty) {
// If there is no memory mask, we should just turn all the lib mask
// bits high.
s"""mem_${depthInst}_$widthInst.lib_mask <= UInt<$libMaskBits>("h${((1 << libMaskBits) - 1).toHexString}")"""
} else {
// Calculate which bit of outer_mask contains the given bit.
// e.g. if memMaskGran = 2, libMaskGran = 1 and libWidth = 4, then
// calculateMaskBit({0, 1}) = 0 and calculateMaskBit({1, 2}) = 1
def calculateMaskBit(bit: Int): Int = bit / memMaskGran.getOrElse(memWidth)
val bitsArr = (libMaskBits - 1 to 0 by -1).map(x => {
if (x * libMaskGran.get > myMemWidth) {
// If we have extra mask bits leftover after the effective width,
// disable those bits.
"""UInt<1>("h0")"""
} else {
val outerMaskBit = calculateMaskBit(x * libMaskGran.get + myBaseBit)
s"bits(outer_mask, $outerMaskBit, $outerMaskBit)"
}
})
val maskVal = bitsArr.reduceRight((bit, rest) => s"cat($bit, $rest)")
s"mem_${depthInst}_$widthInst.lib_mask <= $maskVal"
}
} else ""
}
/** Helper function to generate a port.
*
* @param prefix Memory port prefix (e.g. "x" for ports like "x_clk")
* @param addrWidth Address port width
* @param width data width
* @param write Has a write port?
* @param writeEnable Has a write enable port?
* @param read Has a read port?
* @param readEnable Has a read enable port?
* @param mask Mask granularity (# bits) of the port or None.
* @param extraPorts Extra ports (name, # bits)
*/
def generatePort(
prefix: String,
addrWidth: Int,
width: Int,
write: Boolean,
writeEnable: Boolean,
read: Boolean,
readEnable: Boolean,
mask: Option[Int],
extraPorts: Seq[(String, Int)] = Seq()
): String = {
val realPrefix = if (prefix == "") "" else prefix + "_"
val readStr = if (read) s"output ${realPrefix}dout : UInt<$width>" else ""
val writeStr = if (write) s"input ${realPrefix}din : UInt<$width>" else ""
val readEnableStr = if (readEnable) s"input ${realPrefix}read_en : UInt<1>" else ""
val writeEnableStr = if (writeEnable) s"input ${realPrefix}write_en : UInt<1>" else ""
val maskStr = mask match {
case Some(maskBits: Int) => s"input ${realPrefix}mask : UInt<$maskBits>"
case _ => ""
}
val extraPortsStr = extraPorts.map { case (name, bits) => s" input $name : UInt<$bits>" }.mkString("\n")
s"""
input ${realPrefix}addr : UInt<$addrWidth>
input ${realPrefix}clk : Clock
$writeStr
$readStr
$readEnableStr
$writeEnableStr
$maskStr
$extraPortsStr
"""
}
/** Helper function to generate a RW footer port.
*
* @param prefix Memory port prefix (e.g. "x" for ports like "x_clk")
* @param readEnable Has a read enable port?
* @param mask Mask granularity (# bits) of the port or None.
* @param extraPorts Extra ports (name, # bits)
*/
def generateReadWriteFooterPort(
prefix: String,
readEnable: Boolean,
mask: Option[Int],
extraPorts: Seq[(String, Int)] = Seq()
): String = {
generatePort(
prefix,
lib_addr_width,
libWidth,
write = true,
writeEnable = true,
read = true,
readEnable = readEnable,
mask = mask,
extraPorts = extraPorts
)
}
/** Helper function to generate a RW header port.
* @param prefix Memory port prefix (e.g. "x" for ports like "x_clk")
* @param readEnable Has a read enable port?
* @param mask Mask granularity (# bits) of the port or None.
*/
def generateReadWriteHeaderPort(prefix: String, readEnable: Boolean, mask: Option[Int]): String = {
generatePort(
prefix,
mem_addr_width,
memWidth,
write = true,
writeEnable = true,
read = true,
readEnable = readEnable,
mask
)
}
// Generate the header memory ports.
def generateHeaderPorts(): String = {
require(memSRAM.ports.size == 1, "Header generator only supports single RW port mem")
generateReadWriteHeaderPort(
memPortPrefix,
memSRAM.ports.head.readEnable.isDefined,
if (memHasMask) Some(memMaskBits) else None
)
}
// Generate the header (contains the circuit statement and the target memory
// module.
def generateHeader(): String = {
s"""
circuit $mem_name :
module $mem_name :
${generateHeaderPorts()}
"""
}
// Generate the target memory ports.
def generateFooterPorts(): String = {
require(libSRAM.ports.size == 1, "Footer generator only supports single RW port mem")
generateReadWriteFooterPort(
libPortPrefix,
libSRAM.ports.head.readEnable.isDefined,
if (libHasMask) Some(libMaskBits) else None,
extraPorts.map(p => (p.name, p.width))
)
}
// Generate the footer (contains the target memory extmodule declaration by default).
def generateFooter(): String = {
s"""
extmodule $lib_name :
${generateFooterPorts()}
defname = $lib_name
"""
}
// Abstract method to generate body; to be overridden by specific generator type.
def generateBody(): String
// Generate the entire output from header, body, and footer.
def generateOutput(): String = {
s"""
${generateHeader()}
${generateBody()}
${generateFooter()}
"""
}
val output: String = generateOutput()
}
// Use this trait for tests that invoke the memory compiler without lib.
trait HasNoLibTestGenerator extends HasSimpleTestGenerator {
this: MacroCompilerSpec with HasSRAMGenerator =>
// If there isn't a lib, then the "lib" will become a FIRRTL "mem", which
// in turn becomes synthesized flops.
// Therefore, make "lib" width/depth equal to the mem.
override lazy val libDepth: BigInt = memDepth
override lazy val libWidth: Int = memWidth
override lazy val lib_name: String = mem_name
// Do the same for port names.
override lazy val libPortPrefix: String = memPortPrefix
// If there is no lib, don't generate a body.
override def generateBody() = ""
}

View File

@@ -1,383 +0,0 @@
package barstools.macros
// Test the ability of the compiler to deal with various mask combinations.
trait MasksTestSettings {
this: MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator =>
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
}
// Try all four different kinds of mask config:
/** Non-masked mem Masked mem
* ---------------------------------
* Non-masked lib | | |
* ---------------------------------
* Masked lib | | |
* ---------------------------------
*/
class Masks_FourTypes_NonMaskedMem_NonMaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val memMaskGran: Option[Int] = None
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = None
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_FourTypes_NonMaskedMem_MaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val memMaskGran: Option[Int] = None
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = Some(2)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_FourTypes_MaskedMem_NonMaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = None
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_FourTypes_MaskedMem_NonMaskedLib_SmallerMaskGran
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val memMaskGran: Option[Int] = Some(4)
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = None
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_FourTypes_MaskedMem_MaskedLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libWidth = 16
override lazy val libMaskGran: Option[Int] = Some(4)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_FourTypes_MaskedMem_MaskedLib_SameMaskGran
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libWidth = 16
override lazy val libMaskGran: Option[Int] = Some(8)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_FourTypes_MaskedMem_MaskedLib_SmallerMaskGran
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val memMaskGran: Option[Int] = Some(4)
override lazy val libWidth = 32
override lazy val libMaskGran: Option[Int] = Some(8)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
// Bit-mask memories to non-masked libs whose width is larger than 1.
class Masks_BitMaskedMem_NonMaskedLib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val memMaskGran: Option[Int] = Some(1)
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = None
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
// FPGA-style byte-masked memories.
class Masks_FPGAStyle_32_8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 32
override lazy val memMaskGran: Option[Int] = Some(32)
override lazy val libMaskGran: Option[Int] = Some(8)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
// Simple powers of two with bit-masked lib.
class Masks_PowersOfTwo_8_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_PowersOfTwo_16_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64
override lazy val memMaskGran: Option[Int] = Some(16)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_PowersOfTwo_32_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64
override lazy val memMaskGran: Option[Int] = Some(32)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_PowersOfTwo_64_1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 64
override lazy val memMaskGran: Option[Int] = Some(64)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
// Simple powers of two with non bit-masked lib.
class Masks_PowersOfTwo_32_4
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 128
override lazy val memMaskGran: Option[Int] = Some(32)
override lazy val libMaskGran: Option[Int] = Some(4)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_PowersOfTwo_32_8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 128
override lazy val memMaskGran: Option[Int] = Some(32)
override lazy val libMaskGran: Option[Int] = Some(8)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_PowersOfTwo_8_8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 128
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(8)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
// Width as a multiple of the mask, bit-masked lib
class Masks_IntegerMaskMultiple_20_10
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 20
override lazy val memMaskGran: Option[Int] = Some(10)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_IntegerMaskMultiple_21_7
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 21
override lazy val memMaskGran: Option[Int] = Some(21)
override lazy val libMaskGran: Option[Int] = Some(7)
(it should "be enabled when non-power of two masks are supported").is(pending)
//~ compileExecuteAndTest(mem, lib, v, output)
}
class Masks_IntegerMaskMultiple_21_21
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 21
override lazy val memMaskGran: Option[Int] = Some(21)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_IntegerMaskMultiple_84_21
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 84
override lazy val memMaskGran: Option[Int] = Some(21)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_IntegerMaskMultiple_92_23
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 92
override lazy val memMaskGran: Option[Int] = Some(23)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_IntegerMaskMultiple_117_13
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 117
override lazy val memMaskGran: Option[Int] = Some(13)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_IntegerMaskMultiple_160_20
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 160
override lazy val memMaskGran: Option[Int] = Some(20)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
class Masks_IntegerMaskMultiple_184_23
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 184
override lazy val memMaskGran: Option[Int] = Some(23)
override lazy val libMaskGran: Option[Int] = Some(1)
it should "compile, execute, and test" in {
compileExecuteAndTest(mem, lib, v, output)
}
}
// Width as an non-integer multiple of the mask, bit-masked lib
class Masks_NonIntegerMaskMultiple_32_3
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with MasksTestSettings {
override lazy val width = 32
override lazy val memMaskGran: Option[Int] = Some(3)
override lazy val libMaskGran: Option[Int] = Some(1)
(it should "be enabled when non-power of two masks are supported").is(pending)
//~ compileExecuteAndTest(mem, lib, v, output)
}

View File

@@ -1,500 +0,0 @@
package barstools.macros
// Test that the memory compiler works fine for compiling multi-port memories.
// TODO: extend test generator to also automatically generate multi-ported memories.
class SplitWidth_2rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
import mdf.macrolib._
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val memMaskGran: Option[Int] = Some(16)
override lazy val libWidth = 16
override def generateMemSRAM(): SRAMMacro = {
SRAMMacro(
name = mem_name,
width = memWidth,
depth = memDepth,
family = "2rw",
ports = Seq(
generateTestPort(
"portA",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
),
generateTestPort(
"portB",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateLibSRAM(): SRAMMacro = {
SRAMMacro(
name = lib_name,
width = libWidth,
depth = libDepth,
family = "2rw",
ports = Seq(
generateTestPort(
"portA",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = true,
readEnable = true
),
generateTestPort(
"portB",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateHeaderPorts(): String = {
generateReadWriteHeaderPort("portA", readEnable = true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort(
"portB",
readEnable = true,
Some(memMaskBits)
)
}
override def generateFooterPorts(): String = {
generateReadWriteFooterPort("portA", readEnable = true, None) + "\n" + generateReadWriteFooterPort(
"portB",
readEnable = true,
None
)
}
override def generateBody() =
"""
inst mem_0_0 of awesome_lib_mem
inst mem_0_1 of awesome_lib_mem
inst mem_0_2 of awesome_lib_mem
inst mem_0_3 of awesome_lib_mem
mem_0_0.portA_clk <= portA_clk
mem_0_0.portA_addr <= portA_addr
node portA_dout_0_0 = bits(mem_0_0.portA_dout, 15, 0)
mem_0_0.portA_din <= bits(portA_din, 15, 0)
mem_0_0.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_0.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 0, 0)), UInt<1>("h1"))
mem_0_1.portA_clk <= portA_clk
mem_0_1.portA_addr <= portA_addr
node portA_dout_0_1 = bits(mem_0_1.portA_dout, 15, 0)
mem_0_1.portA_din <= bits(portA_din, 31, 16)
mem_0_1.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_1.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 1, 1)), UInt<1>("h1"))
mem_0_2.portA_clk <= portA_clk
mem_0_2.portA_addr <= portA_addr
node portA_dout_0_2 = bits(mem_0_2.portA_dout, 15, 0)
mem_0_2.portA_din <= bits(portA_din, 47, 32)
mem_0_2.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_2.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 2, 2)), UInt<1>("h1"))
mem_0_3.portA_clk <= portA_clk
mem_0_3.portA_addr <= portA_addr
node portA_dout_0_3 = bits(mem_0_3.portA_dout, 15, 0)
mem_0_3.portA_din <= bits(portA_din, 63, 48)
mem_0_3.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_3.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 3, 3)), UInt<1>("h1"))
node portA_dout_0 = cat(portA_dout_0_3, cat(portA_dout_0_2, cat(portA_dout_0_1, portA_dout_0_0)))
mem_0_0.portB_clk <= portB_clk
mem_0_0.portB_addr <= portB_addr
node portB_dout_0_0 = bits(mem_0_0.portB_dout, 15, 0)
mem_0_0.portB_din <= bits(portB_din, 15, 0)
mem_0_0.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_0.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 0, 0)), UInt<1>("h1"))
mem_0_1.portB_clk <= portB_clk
mem_0_1.portB_addr <= portB_addr
node portB_dout_0_1 = bits(mem_0_1.portB_dout, 15, 0)
mem_0_1.portB_din <= bits(portB_din, 31, 16)
mem_0_1.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_1.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 1, 1)), UInt<1>("h1"))
mem_0_2.portB_clk <= portB_clk
mem_0_2.portB_addr <= portB_addr
node portB_dout_0_2 = bits(mem_0_2.portB_dout, 15, 0)
mem_0_2.portB_din <= bits(portB_din, 47, 32)
mem_0_2.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_2.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 2, 2)), UInt<1>("h1"))
mem_0_3.portB_clk <= portB_clk
mem_0_3.portB_addr <= portB_addr
node portB_dout_0_3 = bits(mem_0_3.portB_dout, 15, 0)
mem_0_3.portB_din <= bits(portB_din, 63, 48)
mem_0_3.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_3.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 3, 3)), UInt<1>("h1"))
node portB_dout_0 = cat(portB_dout_0_3, cat(portB_dout_0_2, cat(portB_dout_0_1, portB_dout_0_0)))
portA_dout <= mux(UInt<1>("h1"), portA_dout_0, UInt<64>("h0"))
portB_dout <= mux(UInt<1>("h1"), portB_dout_0, UInt<64>("h0"))
"""
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth_1r_1w extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
import mdf.macrolib._
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val memMaskGran: Option[Int] = Some(16)
override lazy val libWidth = 16
override def generateMemSRAM(): SRAMMacro = {
SRAMMacro(
name = mem_name,
width = memWidth,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateTestPort(
"portA",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = false,
read = true,
readEnable = true
),
generateTestPort(
"portB",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = false
)
)
)
}
override def generateLibSRAM(): SRAMMacro = {
SRAMMacro(
name = lib_name,
width = libWidth,
depth = libDepth,
family = "1r1w",
ports = Seq(
generateTestPort(
"portA",
libWidth,
libDepth,
write = false,
read = true,
readEnable = true
),
generateTestPort("portB", libWidth, libDepth, write = true, writeEnable = true, read = false)
)
)
}
override def generateHeaderPorts(): String = {
generatePort(
"portA",
mem_addr_width,
memWidth,
write = false,
writeEnable = false,
read = true,
readEnable = true,
Some(memMaskBits)
) + "\n" +
generatePort(
"portB",
mem_addr_width,
memWidth,
write = true,
writeEnable = true,
read = false,
readEnable = false,
Some(memMaskBits)
)
}
override def generateFooterPorts(): String = {
generatePort(
"portA",
lib_addr_width,
libWidth,
write = false,
writeEnable = false,
read = true,
readEnable = true,
None
) + "\n" +
generatePort(
"portB",
lib_addr_width,
libWidth,
write = true,
writeEnable = true,
read = false,
readEnable = false,
None
)
}
override def generateBody() =
"""
inst mem_0_0 of awesome_lib_mem
inst mem_0_1 of awesome_lib_mem
inst mem_0_2 of awesome_lib_mem
inst mem_0_3 of awesome_lib_mem
mem_0_0.portB_clk <= portB_clk
mem_0_0.portB_addr <= portB_addr
mem_0_0.portB_din <= bits(portB_din, 15, 0)
mem_0_0.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 0, 0)), UInt<1>("h1"))
mem_0_1.portB_clk <= portB_clk
mem_0_1.portB_addr <= portB_addr
mem_0_1.portB_din <= bits(portB_din, 31, 16)
mem_0_1.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 1, 1)), UInt<1>("h1"))
mem_0_2.portB_clk <= portB_clk
mem_0_2.portB_addr <= portB_addr
mem_0_2.portB_din <= bits(portB_din, 47, 32)
mem_0_2.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 2, 2)), UInt<1>("h1"))
mem_0_3.portB_clk <= portB_clk
mem_0_3.portB_addr <= portB_addr
mem_0_3.portB_din <= bits(portB_din, 63, 48)
mem_0_3.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 3, 3)), UInt<1>("h1"))
mem_0_0.portA_clk <= portA_clk
mem_0_0.portA_addr <= portA_addr
node portA_dout_0_0 = bits(mem_0_0.portA_dout, 15, 0)
mem_0_0.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_1.portA_clk <= portA_clk
mem_0_1.portA_addr <= portA_addr
node portA_dout_0_1 = bits(mem_0_1.portA_dout, 15, 0)
mem_0_1.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_2.portA_clk <= portA_clk
mem_0_2.portA_addr <= portA_addr
node portA_dout_0_2 = bits(mem_0_2.portA_dout, 15, 0)
mem_0_2.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_3.portA_clk <= portA_clk
mem_0_3.portA_addr <= portA_addr
node portA_dout_0_3 = bits(mem_0_3.portA_dout, 15, 0)
mem_0_3.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
node portA_dout_0 = cat(portA_dout_0_3, cat(portA_dout_0_2, cat(portA_dout_0_1, portA_dout_0_0)))
portA_dout <= mux(UInt<1>("h1"), portA_dout_0, UInt<64>("h0"))
"""
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth_2rw_differentMasks extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
import mdf.macrolib._
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val memMaskGran: Option[Int] = Some(16)
override lazy val libWidth = 16
lazy val memMaskGranB = 8 // these generators are run at constructor time
override def generateMemSRAM(): SRAMMacro = {
SRAMMacro(
name = mem_name,
width = memWidth,
depth = memDepth,
family = "2rw",
ports = Seq(
generateTestPort(
"portA",
memWidth,
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
),
generateTestPort(
"portB",
memWidth,
Some(memDepth),
maskGran = Some(memMaskGranB),
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateLibSRAM(): SRAMMacro = {
SRAMMacro(
name = lib_name,
width = libWidth,
depth = libDepth,
family = "2rw",
ports = Seq(
generateTestPort(
"portA",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = true,
readEnable = true
),
generateTestPort(
"portB",
libWidth,
libDepth,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateHeaderPorts(): String = {
generateReadWriteHeaderPort("portA", readEnable = true, Some(memMaskBits)) + "\n" + generateReadWriteHeaderPort(
"portB",
readEnable = true,
Some(memWidth / memMaskGranB)
)
}
override def generateFooterPorts(): String = {
generateReadWriteFooterPort("portA", readEnable = true, None) + "\n" + generateReadWriteFooterPort(
"portB",
readEnable = true,
None
)
}
override def generateBody() =
"""
inst mem_0_0 of awesome_lib_mem
inst mem_0_1 of awesome_lib_mem
inst mem_0_2 of awesome_lib_mem
inst mem_0_3 of awesome_lib_mem
inst mem_0_4 of awesome_lib_mem
inst mem_0_5 of awesome_lib_mem
inst mem_0_6 of awesome_lib_mem
inst mem_0_7 of awesome_lib_mem
mem_0_0.portA_clk <= portA_clk
mem_0_0.portA_addr <= portA_addr
node portA_dout_0_0 = bits(mem_0_0.portA_dout, 7, 0)
mem_0_0.portA_din <= bits(portA_din, 7, 0)
mem_0_0.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_0.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 0, 0)), UInt<1>("h1"))
mem_0_1.portA_clk <= portA_clk
mem_0_1.portA_addr <= portA_addr
node portA_dout_0_1 = bits(mem_0_1.portA_dout, 7, 0)
mem_0_1.portA_din <= bits(portA_din, 15, 8)
mem_0_1.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_1.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 0, 0)), UInt<1>("h1"))
mem_0_2.portA_clk <= portA_clk
mem_0_2.portA_addr <= portA_addr
node portA_dout_0_2 = bits(mem_0_2.portA_dout, 7, 0)
mem_0_2.portA_din <= bits(portA_din, 23, 16)
mem_0_2.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_2.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 1, 1)), UInt<1>("h1"))
mem_0_3.portA_clk <= portA_clk
mem_0_3.portA_addr <= portA_addr
node portA_dout_0_3 = bits(mem_0_3.portA_dout, 7, 0)
mem_0_3.portA_din <= bits(portA_din, 31, 24)
mem_0_3.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_3.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 1, 1)), UInt<1>("h1"))
mem_0_4.portA_clk <= portA_clk
mem_0_4.portA_addr <= portA_addr
node portA_dout_0_4 = bits(mem_0_4.portA_dout, 7, 0)
mem_0_4.portA_din <= bits(portA_din, 39, 32)
mem_0_4.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_4.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 2, 2)), UInt<1>("h1"))
mem_0_5.portA_clk <= portA_clk
mem_0_5.portA_addr <= portA_addr
node portA_dout_0_5 = bits(mem_0_5.portA_dout, 7, 0)
mem_0_5.portA_din <= bits(portA_din, 47, 40)
mem_0_5.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_5.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 2, 2)), UInt<1>("h1"))
mem_0_6.portA_clk <= portA_clk
mem_0_6.portA_addr <= portA_addr
node portA_dout_0_6 = bits(mem_0_6.portA_dout, 7, 0)
mem_0_6.portA_din <= bits(portA_din, 55, 48)
mem_0_6.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_6.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 3, 3)), UInt<1>("h1"))
mem_0_7.portA_clk <= portA_clk
mem_0_7.portA_addr <= portA_addr
node portA_dout_0_7 = bits(mem_0_7.portA_dout, 7, 0)
mem_0_7.portA_din <= bits(portA_din, 63, 56)
mem_0_7.portA_read_en <= and(portA_read_en, UInt<1>("h1"))
mem_0_7.portA_write_en <= and(and(and(portA_write_en, UInt<1>("h1")), bits(portA_mask, 3, 3)), UInt<1>("h1"))
node portA_dout_0 = cat(portA_dout_0_7, cat(portA_dout_0_6, cat(portA_dout_0_5, cat(portA_dout_0_4, cat(portA_dout_0_3, cat(portA_dout_0_2, cat(portA_dout_0_1, portA_dout_0_0)))))))
mem_0_0.portB_clk <= portB_clk
mem_0_0.portB_addr <= portB_addr
node portB_dout_0_0 = bits(mem_0_0.portB_dout, 7, 0)
mem_0_0.portB_din <= bits(portB_din, 7, 0)
mem_0_0.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_0.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 0, 0)), UInt<1>("h1"))
mem_0_1.portB_clk <= portB_clk
mem_0_1.portB_addr <= portB_addr
node portB_dout_0_1 = bits(mem_0_1.portB_dout, 7, 0)
mem_0_1.portB_din <= bits(portB_din, 15, 8)
mem_0_1.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_1.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 1, 1)), UInt<1>("h1"))
mem_0_2.portB_clk <= portB_clk
mem_0_2.portB_addr <= portB_addr
node portB_dout_0_2 = bits(mem_0_2.portB_dout, 7, 0)
mem_0_2.portB_din <= bits(portB_din, 23, 16)
mem_0_2.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_2.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 2, 2)), UInt<1>("h1"))
mem_0_3.portB_clk <= portB_clk
mem_0_3.portB_addr <= portB_addr
node portB_dout_0_3 = bits(mem_0_3.portB_dout, 7, 0)
mem_0_3.portB_din <= bits(portB_din, 31, 24)
mem_0_3.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_3.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 3, 3)), UInt<1>("h1"))
mem_0_4.portB_clk <= portB_clk
mem_0_4.portB_addr <= portB_addr
node portB_dout_0_4 = bits(mem_0_4.portB_dout, 7, 0)
mem_0_4.portB_din <= bits(portB_din, 39, 32)
mem_0_4.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_4.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 4, 4)), UInt<1>("h1"))
mem_0_5.portB_clk <= portB_clk
mem_0_5.portB_addr <= portB_addr
node portB_dout_0_5 = bits(mem_0_5.portB_dout, 7, 0)
mem_0_5.portB_din <= bits(portB_din, 47, 40)
mem_0_5.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_5.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 5, 5)), UInt<1>("h1"))
mem_0_6.portB_clk <= portB_clk
mem_0_6.portB_addr <= portB_addr
node portB_dout_0_6 = bits(mem_0_6.portB_dout, 7, 0)
mem_0_6.portB_din <= bits(portB_din, 55, 48)
mem_0_6.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_6.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 6, 6)), UInt<1>("h1"))
mem_0_7.portB_clk <= portB_clk
mem_0_7.portB_addr <= portB_addr
node portB_dout_0_7 = bits(mem_0_7.portB_dout, 7, 0)
mem_0_7.portB_din <= bits(portB_din, 63, 56)
mem_0_7.portB_read_en <= and(portB_read_en, UInt<1>("h1"))
mem_0_7.portB_write_en <= and(and(and(portB_write_en, UInt<1>("h1")), bits(portB_mask, 7, 7)), UInt<1>("h1"))
node portB_dout_0 = cat(portB_dout_0_7, cat(portB_dout_0_6, cat(portB_dout_0_5, cat(portB_dout_0_4, cat(portB_dout_0_3, cat(portB_dout_0_2, cat(portB_dout_0_1, portB_dout_0_0)))))))
portA_dout <= mux(UInt<1>("h1"), portA_dout_0, UInt<64>("h0"))
portB_dout <= mux(UInt<1>("h1"), portB_dout_0, UInt<64>("h0"))
"""
compileExecuteAndTest(mem, lib, v, output)
}

View File

@@ -1,21 +0,0 @@
package barstools.macros
import mdf.macrolib
class SRAMCompiler extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
val compiler: macrolib.SRAMCompiler = generateSRAMCompiler("awesome", "A")
val verilog = s"v-SRAMCompiler.v"
override lazy val depth = BigInt(16)
override lazy val memWidth = 8
override lazy val libWidth = 8
override lazy val mem_name = "mymem"
override lazy val memPortPrefix = "X"
override lazy val lib_name = "mygroup_8x16_SVT"
override lazy val libPortPrefix = "A"
writeToLib(lib, Seq(compiler))
writeToMem(mem, Seq(generateSRAM("mymem", "X", 8, 16)))
compileExecuteAndTest(mem, Some(lib), verilog, output = output, useCompiler = true)
}

View File

@@ -1,638 +0,0 @@
package barstools.macros
// Test the depth splitting aspect of the memory compiler.
// This file is for simple tests: one read-write port, powers of two sizes, etc.
// For example, implementing a 4096x32 memory using four 1024x32 memories.
trait HasSimpleDepthTestGenerator extends HasSimpleTestGenerator {
this: MacroCompilerSpec with HasSRAMGenerator =>
def width: Int
override lazy val memWidth: Int = width
override lazy val libWidth: Int = width
// Generate a depth-splitting body.
override def generateBody(): String = {
val output = new StringBuilder
if (selectBits > 0) {
output.append(
s"""
node ${memPortPrefix}_addr_sel = bits(${memPortPrefix}_addr, ${mem_addr_width - 1}, $lib_addr_width)
reg ${memPortPrefix}_addr_sel_reg : UInt<$selectBits>, ${memPortPrefix}_clk with :
reset => (UInt<1>("h0"), ${memPortPrefix}_addr_sel_reg)
${memPortPrefix}_addr_sel_reg <= mux(UInt<1>("h1"), ${memPortPrefix}_addr_sel, ${memPortPrefix}_addr_sel_reg)
"""
)
}
for (i <- 0 until depthInstances) {
val maskStatement = generateMaskStatement(0, i)
val enableIdentifier =
if (selectBits > 0) s"""eq(${memPortPrefix}_addr_sel, UInt<$selectBits>("h${i.toHexString}"))"""
else "UInt<1>(\"h1\")"
val chipEnable = s"""UInt<1>("h1")"""
val writeEnable =
if (memMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, $chipEnable)" else s"${memPortPrefix}_write_en"
output.append(
s"""
inst mem_${i}_0 of $lib_name
mem_${i}_0.${libPortPrefix}_clk <= ${memPortPrefix}_clk
mem_${i}_0.${libPortPrefix}_addr <= ${memPortPrefix}_addr
node ${memPortPrefix}_dout_${i}_0 = bits(mem_${i}_0.${libPortPrefix}_dout, ${width - 1}, 0)
mem_${i}_0.${libPortPrefix}_din <= bits(${memPortPrefix}_din, ${width - 1}, 0)
$maskStatement
mem_${i}_0.${libPortPrefix}_write_en <= and(and($writeEnable, UInt<1>("h1")), $enableIdentifier)
node ${memPortPrefix}_dout_$i = ${memPortPrefix}_dout_${i}_0
"""
)
}
def generate_outer_dout_tree(i: Int, depthInstances: Int): String = {
if (i > depthInstances - 1) {
s"""UInt<$libWidth>("h0")"""
} else {
s"""mux(eq(${memPortPrefix}_addr_sel_reg, UInt<%d>("h%s")), ${memPortPrefix}_dout_%d, %s)""".format(
selectBits,
i.toHexString,
i,
generate_outer_dout_tree(i + 1, depthInstances)
)
}
}
output.append(s" ${memPortPrefix}_dout <= ")
if (selectBits > 0) {
output.append(generate_outer_dout_tree(0, depthInstances))
} else {
output.append(s"""mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<$libWidth>("h0"))""")
}
output.toString
}
}
// Try different widths
class SplitDepth4096x32_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(4096)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth4096x16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 16
override lazy val memDepth = BigInt(4096)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth32768x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(32768)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth4096x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(4096)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth1024x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(1024)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
// Non power of two
class SplitDepth2000x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(2000)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2049x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(2049)
override lazy val libDepth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output)
}
// Masked RAMs
// Test for mem mask == lib mask (i.e. mask is a write enable bit)
class SplitDepth2048x32_mrw_lib32 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(32)
override lazy val libMaskGran: Option[Int] = Some(32)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x8_mrw_lib8 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 8
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(8)
compileExecuteAndTest(mem, lib, v, output)
}
// Non-bit level mask
class SplitDepth2048x64_mrw_mem32_lib8
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator {
override lazy val width = 64
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(32)
override lazy val libMaskGran: Option[Int] = Some(8)
compileExecuteAndTest(mem, lib, v, output)
}
// Bit level mask
class SplitDepth2048x32_mrw_mem16_lib1
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(16)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x32_mrw_mem8_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x32_mrw_mem4_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(4)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x32_mrw_mem2_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(2)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
// Non-powers of 2 mask sizes
class SplitDepth2048x32_mrw_mem3_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(3)
override lazy val libMaskGran: Option[Int] = Some(1)
(it should "be enabled when non-power of two masks are supported").is(pending)
//compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x32_mrw_mem7_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(7)
override lazy val libMaskGran: Option[Int] = Some(1)
(it should "be enabled when non-power of two masks are supported").is(pending)
//compileExecuteAndTest(mem, lib, v, output)
}
class SplitDepth2048x32_mrw_mem9_lib1 extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
override lazy val width = 32
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val memMaskGran: Option[Int] = Some(9)
override lazy val libMaskGran: Option[Int] = Some(1)
(it should "be enabled when non-power of two masks are supported").is(pending)
//compileExecuteAndTest(mem, lib, v, output)
}
// Try an extra port
class SplitDepth2048x8_extraPort extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator {
import mdf.macrolib._
override lazy val width = 8
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val extraPorts = List(
MacroExtraPort(name = "extra_port", width = 8, portType = Constant, value = 0xff)
)
override lazy val extraTag = "extraPort"
override def generateOutput(): String =
"""
circuit target_memory :
module target_memory :
input outer_addr : UInt<11>
input outer_clk : Clock
input outer_din : UInt<8>
output outer_dout : UInt<8>
input outer_write_en : UInt<1>
node outer_addr_sel = bits(outer_addr, 10, 10)
reg outer_addr_sel_reg : UInt<1>, outer_clk with :
reset => (UInt<1>("h0"), outer_addr_sel_reg)
outer_addr_sel_reg <= mux(UInt<1>("h1"), outer_addr_sel, outer_addr_sel_reg)
inst mem_0_0 of awesome_lib_mem
mem_0_0.extra_port <= UInt<8>("hff")
mem_0_0.lib_clk <= outer_clk
mem_0_0.lib_addr <= outer_addr
node outer_dout_0_0 = bits(mem_0_0.lib_dout, 7, 0)
mem_0_0.lib_din <= bits(outer_din, 7, 0)
mem_0_0.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), eq(outer_addr_sel, UInt<1>("h0")))
node outer_dout_0 = outer_dout_0_0
inst mem_1_0 of awesome_lib_mem
mem_1_0.extra_port <= UInt<8>("hff")
mem_1_0.lib_clk <= outer_clk
mem_1_0.lib_addr <= outer_addr
node outer_dout_1_0 = bits(mem_1_0.lib_dout, 7, 0)
mem_1_0.lib_din <= bits(outer_din, 7, 0)
mem_1_0.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), eq(outer_addr_sel, UInt<1>("h1")))
node outer_dout_1 = outer_dout_1_0
outer_dout <= mux(eq(outer_addr_sel_reg, UInt<1>("h0")), outer_dout_0, mux(eq(outer_addr_sel_reg, UInt<1>("h1")), outer_dout_1, UInt<8>("h0")))
extmodule awesome_lib_mem :
input lib_addr : UInt<10>
input lib_clk : Clock
input lib_din : UInt<8>
output lib_dout : UInt<8>
input lib_write_en : UInt<1>
input extra_port : UInt<8>
defname = awesome_lib_mem
"""
compileExecuteAndTest(mem, lib, v, output)
}
// Split read and (non-masked) write ports (r+w).
class SplitDepth_SplitPortsNonMasked extends MacroCompilerSpec with HasSRAMGenerator {
lazy val width = 8
lazy val memDepth = BigInt(2048)
lazy val libDepth = BigInt(1024)
override val memPrefix: String = testDir
override val libPrefix: String = testDir
import mdf.macrolib._
"Non-masked split lib; split mem" should "split fine" in {
val lib = "lib-split_depth-r-w-split-lib-split-mem.json"
val mem = "mem-split_depth-r-w-split-lib-split-mem.json"
val v = "split_depth-r-w-split-lib-split-mem.v"
val libMacro = SRAMMacro(
name = "awesome_lib_mem",
width = width,
depth = libDepth,
family = "1r1w",
ports = Seq(
generateReadPort("innerA", width, libDepth),
generateWritePort("innerB", width, libDepth)
)
)
val memMacro = SRAMMacro(
name = "target_memory",
width = width,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateReadPort("outerB", width, memDepth),
generateWritePort("outerA", width, memDepth)
)
)
writeToLib(mem, Seq(memMacro))
writeToLib(lib, Seq(libMacro))
val output =
"""
circuit target_memory :
module target_memory :
input outerB_addr : UInt<11>
input outerB_clk : Clock
output outerB_dout : UInt<8>
input outerA_addr : UInt<11>
input outerA_clk : Clock
input outerA_din : UInt<8>
input outerA_write_en : UInt<1>
node outerB_addr_sel = bits(outerB_addr, 10, 10)
reg outerB_addr_sel_reg : UInt<1>, outerB_clk with :
reset => (UInt<1>("h0"), outerB_addr_sel_reg)
outerB_addr_sel_reg <= mux(UInt<1>("h1"), outerB_addr_sel, outerB_addr_sel_reg)
node outerA_addr_sel = bits(outerA_addr, 10, 10)
inst mem_0_0 of awesome_lib_mem
mem_0_0.innerB_clk <= outerA_clk
mem_0_0.innerB_addr <= outerA_addr
mem_0_0.innerB_din <= bits(outerA_din, 7, 0)
mem_0_0.innerB_write_en <= and(and(and(outerA_write_en, UInt<1>("h1")), UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h0")))
mem_0_0.innerA_clk <= outerB_clk
mem_0_0.innerA_addr <= outerB_addr
node outerB_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
node outerB_dout_0 = outerB_dout_0_0
inst mem_1_0 of awesome_lib_mem
mem_1_0.innerB_clk <= outerA_clk
mem_1_0.innerB_addr <= outerA_addr
mem_1_0.innerB_din <= bits(outerA_din, 7, 0)
mem_1_0.innerB_write_en <= and(and(and(outerA_write_en, UInt<1>("h1")), UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h1")))
mem_1_0.innerA_clk <= outerB_clk
mem_1_0.innerA_addr <= outerB_addr
node outerB_dout_1_0 = bits(mem_1_0.innerA_dout, 7, 0)
node outerB_dout_1 = outerB_dout_1_0
outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<8>("h0")))
extmodule awesome_lib_mem :
input innerA_addr : UInt<10>
input innerA_clk : Clock
output innerA_dout : UInt<8>
input innerB_addr : UInt<10>
input innerB_clk : Clock
input innerB_din : UInt<8>
input innerB_write_en : UInt<1>
defname = awesome_lib_mem
"""
compileExecuteAndTest(mem, lib, v, output)
}
"Non-masked regular lib; split mem" should "split fine" in {
// Enable this test when the memory compiler can compile non-matched
// memories (e.g. mrw mem and r+mw lib).
// Right now all we can get is a "port count must match" error.
pending
val lib = "lib-split_depth-r-w-regular-lib-split-mem.json"
val mem = "mem-split_depth-r-w-regular-lib-split-mem.json"
val v = "split_depth-r-w-regular-lib-split-mem.v"
val memMacro = SRAMMacro(
name = "target_memory",
width = width,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateReadPort("outerB", width, memDepth),
generateWritePort("outerA", width, memDepth)
)
)
writeToLib(mem, Seq(memMacro))
writeToLib(lib, Seq(generateSRAM("awesome_lib_mem", "lib", width, libDepth)))
val output =
"""
TODO
"""
compileExecuteAndTest(mem, lib, v, output)
}
"Non-masked split lib; regular mem" should "split fine" in {
// Enable this test when the memory compiler can compile non-matched
// memories (e.g. mrw mem and r+mw lib).
// Right now all we can get is a "port count must match" error.
// [edwardw]: does this even make sense? Can we compile a 2-ported memory using 1-ported memories?
pending
val lib = "lib-split_depth-r-w-split-lib-regular-mem.json"
val mem = "mem-split_depth-r-w-split-lib-regular-mem.json"
val v = "split_depth-r-w-split-lib-regular-mem.v"
val libMacro = SRAMMacro(
name = "awesome_lib_mem",
width = width,
depth = libDepth,
family = "1rw",
ports = Seq(
generateReadPort("innerA", width, libDepth),
generateWritePort("innerB", width, libDepth)
)
)
writeToLib(mem, Seq(generateSRAM("target_memory", "outer", width, memDepth)))
writeToLib(lib, Seq(libMacro))
val output =
"""
TODO
"""
compileExecuteAndTest(mem, lib, v, output)
}
}
// Split read and (masked) write ports (r+mw).
class SplitDepth_SplitPortsMasked extends MacroCompilerSpec with HasSRAMGenerator {
lazy val width = 8
lazy val memDepth = BigInt(2048)
lazy val libDepth = BigInt(1024)
lazy val memMaskGran: Option[Int] = Some(8)
lazy val libMaskGran: Option[Int] = Some(1)
override val memPrefix: String = testDir
override val libPrefix: String = testDir
import mdf.macrolib._
"Masked split lib; split mem" should "split fine" in {
val lib = "lib-split_depth-r-mw-split-lib-split-mem.json"
val mem = "mem-split_depth-r-mw-split-lib-split-mem.json"
val v = "split_depth-r-mw-split-lib-split-mem.v"
val libMacro = SRAMMacro(
name = "awesome_lib_mem",
width = width,
depth = libDepth,
family = "1r1w",
ports = Seq(
generateReadPort("innerA", width, libDepth),
generateWritePort("innerB", width, libDepth, libMaskGran)
)
)
val memMacro = SRAMMacro(
name = "target_memory",
width = width,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateReadPort("outerB", width, memDepth),
generateWritePort("outerA", width, memDepth, memMaskGran)
)
)
writeToLib(mem, Seq(memMacro))
writeToLib(lib, Seq(libMacro))
val output =
"""
circuit target_memory :
module target_memory :
input outerB_addr : UInt<11>
input outerB_clk : Clock
output outerB_dout : UInt<8>
input outerA_addr : UInt<11>
input outerA_clk : Clock
input outerA_din : UInt<8>
input outerA_write_en : UInt<1>
input outerA_mask : UInt<1>
node outerB_addr_sel = bits(outerB_addr, 10, 10)
reg outerB_addr_sel_reg : UInt<1>, outerB_clk with :
reset => (UInt<1>("h0"), outerB_addr_sel_reg)
outerB_addr_sel_reg <= mux(UInt<1>("h1"), outerB_addr_sel, outerB_addr_sel_reg)
node outerA_addr_sel = bits(outerA_addr, 10, 10)
inst mem_0_0 of awesome_lib_mem
mem_0_0.innerB_clk <= outerA_clk
mem_0_0.innerB_addr <= outerA_addr
mem_0_0.innerB_din <= bits(outerA_din, 7, 0)
mem_0_0.innerB_mask <= cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), bits(outerA_mask, 0, 0))))))))
mem_0_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h0")))
mem_0_0.innerA_clk <= outerB_clk
mem_0_0.innerA_addr <= outerB_addr
node outerB_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
node outerB_dout_0 = outerB_dout_0_0
inst mem_1_0 of awesome_lib_mem
mem_1_0.innerB_clk <= outerA_clk
mem_1_0.innerB_addr <= outerA_addr
mem_1_0.innerB_din <= bits(outerA_din, 7, 0)
mem_1_0.innerB_mask <= cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), bits(outerA_mask, 0, 0))))))))
mem_1_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h1")))
mem_1_0.innerA_clk <= outerB_clk
mem_1_0.innerA_addr <= outerB_addr
node outerB_dout_1_0 = bits(mem_1_0.innerA_dout, 7, 0)
node outerB_dout_1 = outerB_dout_1_0
outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<8>("h0")))
extmodule awesome_lib_mem :
input innerA_addr : UInt<10>
input innerA_clk : Clock
output innerA_dout : UInt<8>
input innerB_addr : UInt<10>
input innerB_clk : Clock
input innerB_din : UInt<8>
input innerB_write_en : UInt<1>
input innerB_mask : UInt<8>
defname = awesome_lib_mem
"""
compileExecuteAndTest(mem, lib, v, output)
}
"Non-masked regular lib; split mem" should "split fine" in {
// Enable this test when the memory compiler can compile non-matched
// memories (e.g. mrw mem and r+mw lib).
// Right now all we can get is a "port count must match" error.
pending
val lib = "lib-split_depth-r-mw-regular-lib-split-mem.json"
val mem = "mem-split_depth-r-mw-regular-lib-split-mem.json"
val v = "split_depth-r-mw-regular-lib-split-mem.v"
val memMacro = SRAMMacro(
name = "target_memory",
width = width,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateReadPort("outerB", width, memDepth),
generateWritePort("outerA", width, memDepth, memMaskGran)
)
)
writeToLib(mem, Seq(memMacro))
writeToLib(lib, Seq(generateSRAM("awesome_lib_mem", "lib", width, libDepth, libMaskGran)))
val output =
"""
TODO
"""
compileExecuteAndTest(mem, lib, v, output)
}
"Non-masked split lib; regular mem" should "split fine" in {
// Enable this test when the memory compiler can compile non-matched
// memories (e.g. mrw mem and r+mw lib).
// Right now all we can get is a "port count must match" error.
// [edwardw]: does this even make sense? Can we compile a 2-ported memory using 1-ported memories?
pending
val lib = "lib-split_depth-r-mw-split-lib-regular-mem.json"
val mem = "mem-split_depth-r-mw-split-lib-regular-mem.json"
val v = "split_depth-r-mw-split-lib-regular-mem.v"
val libMacro = SRAMMacro(
name = "awesome_lib_mem",
width = width,
depth = libDepth,
family = "1rw",
ports = Seq(
generateReadPort("innerA", width, libDepth),
generateWritePort("innerB", width, libDepth, libMaskGran)
)
)
writeToLib(mem, Seq(generateSRAM("target_memory", "outer", width, memDepth, memMaskGran)))
writeToLib(lib, Seq(libMacro))
val output =
"""
TODO
"""
compileExecuteAndTest(mem, lib, v, output)
}
}

View File

@@ -1,608 +0,0 @@
package barstools.macros
// Test the width splitting aspect of the memory compiler.
// For example, implementing a 1024x32 memory using four 1024x8 memories.
trait HasSimpleWidthTestGenerator extends HasSimpleTestGenerator {
this: MacroCompilerSpec with HasSRAMGenerator =>
def depth: BigInt
override lazy val memDepth: BigInt = depth
override lazy val libDepth: BigInt = depth
override def generateBody(): String = {
val output = new StringBuilder
// Generate mem_0_<i> lines for number of width instances.
output.append(
(0 until widthInstances).map { i: Int =>
s"""
inst mem_0_$i of $lib_name
"""
}.reduceLeft(_ + _)
)
// Generate submemory connection blocks.
output.append((for (i <- 0 until widthInstances) yield {
// Width of this submemory.
val myMemWidth = if (i == widthInstances - 1) lastWidthBits else usableLibWidth
// Base bit of this submemory.
// e.g. if libWidth is 8 and this is submemory 2 (0-indexed), then this
// would be 16.
val myBaseBit = usableLibWidth * i
val maskStatement = generateMaskStatement(i, 0)
// We need to use writeEnable as a crude "mask" if mem has a mask but
// lib does not.
val writeEnableBit = if (libMaskGran.isEmpty && memMaskGran.isDefined) {
val outerMaskBit = myBaseBit / memMaskGran.get
s"bits(outer_mask, $outerMaskBit, $outerMaskBit)"
} else """UInt<1>("h1")"""
val chipEnable = s"""UInt<1>("h1")"""
val writeEnableExpr =
if (libMaskGran.isEmpty) s"and(${memPortPrefix}_write_en, $chipEnable)" else s"${memPortPrefix}_write_en"
s"""
mem_0_$i.${libPortPrefix}_clk <= ${memPortPrefix}_clk
mem_0_$i.${libPortPrefix}_addr <= ${memPortPrefix}_addr
node ${memPortPrefix}_dout_0_$i = bits(mem_0_$i.${libPortPrefix}_dout, ${myMemWidth - 1}, 0)
mem_0_$i.${libPortPrefix}_din <= bits(${memPortPrefix}_din, ${myBaseBit + myMemWidth - 1}, $myBaseBit)
$maskStatement
mem_0_$i.${libPortPrefix}_write_en <= and(and($writeEnableExpr, $writeEnableBit), UInt<1>("h1"))
"""
}).reduceLeft(_ + _))
// Generate final output that concats together the sub-memories.
// e.g. cat(outer_dout_0_2, cat(outer_dout_0_1, outer_dout_0_0))
output.append {
val doutStatements = (widthInstances - 1 to 0 by -1).map(i => s"${memPortPrefix}_dout_0_$i")
val catStmt = doutStatements.init.foldRight(doutStatements.last)((l: String, r: String) => s"cat($l, $r)")
s"""
node ${memPortPrefix}_dout_0 = $catStmt
"""
}
output.append(s"""
${memPortPrefix}_dout <= mux(UInt<1>("h1"), ${memPortPrefix}_dout_0, UInt<$memWidth>("h0"))
""")
output.toString
}
}
// Try different widths against a base memory width of 8.
class SplitWidth1024x128_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 128
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x64_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x32_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 8
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
// Try different widths against a base memory width of 16.
class SplitWidth1024x128_lib16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 128
override lazy val libWidth = 16
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x64_lib16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val libWidth = 16
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x32_lib16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val libWidth = 16
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_lib16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 16
compileExecuteAndTest(mem, lib, v, output)
}
// Try different widths against a base memory width of 8 but depth 512 instead of 1024.
class SplitWidth512x128_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(512)
override lazy val memWidth = 128
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth512x64_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(512)
override lazy val memWidth = 64
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth512x32_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(512)
override lazy val memWidth = 32
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth512x16_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(512)
override lazy val memWidth = 16
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth512x8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(512)
override lazy val memWidth = 8
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
// Try non-power of two widths against a base memory width of 8.
class SplitWidth1024x67_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 67
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x60_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 60
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x42_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 42
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x20_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 20
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x17_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 17
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x15_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 15
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x9_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 9
override lazy val libWidth = 8
compileExecuteAndTest(mem, lib, v, output)
}
// Try against a non-power of two base memory width.
class SplitWidth1024x64_mem11_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 64
override lazy val libWidth = 11
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x33_mem11_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 33
override lazy val libWidth = 11
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_mem11_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 11
compileExecuteAndTest(mem, lib, v, output)
}
// Masked RAM
class SplitWidth1024x8_memGran_8_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 8
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_memGran_8_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_memGran_8_libGran_8_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(8)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x128_memGran_8_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 128
override lazy val libWidth = 32
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_memGran_4_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(4)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_memGran_2_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(2)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_memGran_16_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(16)
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
// Non-masked mem, masked lib
class SplitWidth1024x16_libGran_8_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = Some(8)
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x16_libGran_1_rw extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val libMaskGran: Option[Int] = Some(1)
compileExecuteAndTest(mem, lib, v, output)
}
// Non-memMask and non-1 libMask
class SplitWidth1024x16_memGran_8_libGran_2_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(2)
compileExecuteAndTest(mem, lib, v, output)
}
// Non-power of two memGran
class SplitWidth1024x16_memGran_9_libGran_1_rw
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
override lazy val depth = BigInt(1024)
override lazy val memWidth = 16
override lazy val libWidth = 8
override lazy val memMaskGran: Option[Int] = Some(9)
override lazy val libMaskGran: Option[Int] = Some(1)
(it should "be enabled when non-power of two masks are supported").is(pending)
//~ compile(mem, lib, v, false)
//~ execute(mem, lib, false, output)
}
// Read enable
class SplitWidth1024x32_readEnable_Lib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
import mdf.macrolib._
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val libWidth = 8
override def generateLibSRAM(): SRAMMacro = {
SRAMMacro(
name = lib_name,
width = libWidth,
depth = libDepth,
family = "1rw",
ports = Seq(
generateTestPort(
"lib",
Some(libWidth),
Some(libDepth),
maskGran = libMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateBody() =
"""
inst mem_0_0 of awesome_lib_mem
inst mem_0_1 of awesome_lib_mem
inst mem_0_2 of awesome_lib_mem
inst mem_0_3 of awesome_lib_mem
mem_0_0.lib_clk <= outer_clk
mem_0_0.lib_addr <= outer_addr
node outer_dout_0_0 = bits(mem_0_0.lib_dout, 7, 0)
mem_0_0.lib_din <= bits(outer_din, 7, 0)
mem_0_0.lib_read_en <= and(and(not(outer_write_en), UInt<1>("h1")), UInt<1>("h1"))
mem_0_0.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_1.lib_clk <= outer_clk
mem_0_1.lib_addr <= outer_addr
node outer_dout_0_1 = bits(mem_0_1.lib_dout, 7, 0)
mem_0_1.lib_din <= bits(outer_din, 15, 8)
mem_0_1.lib_read_en <= and(and(not(outer_write_en), UInt<1>("h1")), UInt<1>("h1"))
mem_0_1.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_2.lib_clk <= outer_clk
mem_0_2.lib_addr <= outer_addr
node outer_dout_0_2 = bits(mem_0_2.lib_dout, 7, 0)
mem_0_2.lib_din <= bits(outer_din, 23, 16)
mem_0_2.lib_read_en <= and(and(not(outer_write_en), UInt<1>("h1")), UInt<1>("h1"))
mem_0_2.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_3.lib_clk <= outer_clk
mem_0_3.lib_addr <= outer_addr
node outer_dout_0_3 = bits(mem_0_3.lib_dout, 7, 0)
mem_0_3.lib_din <= bits(outer_din, 31, 24)
mem_0_3.lib_read_en <= and(and(not(outer_write_en), UInt<1>("h1")), UInt<1>("h1"))
mem_0_3.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
node outer_dout_0 = cat(outer_dout_0_3, cat(outer_dout_0_2, cat(outer_dout_0_1, outer_dout_0_0)))
outer_dout <= mux(UInt<1>("h1"), outer_dout_0, UInt<32>("h0"))
"""
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x32_readEnable_Mem
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
import mdf.macrolib._
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val libWidth = 8
override def generateMemSRAM(): SRAMMacro = {
SRAMMacro(
name = mem_name,
width = memWidth,
depth = memDepth,
family = "1rw",
ports = Seq(
generateTestPort(
"outer",
Some(memWidth),
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
// No need to override body here due to the lack of a readEnable in the lib.
compileExecuteAndTest(mem, lib, v, output)
}
class SplitWidth1024x32_readEnable_LibMem
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator {
import mdf.macrolib._
override lazy val depth = BigInt(1024)
override lazy val memWidth = 32
override lazy val libWidth = 8
override def generateLibSRAM(): SRAMMacro = {
SRAMMacro(
name = lib_name,
width = libWidth,
depth = libDepth,
family = "1rw",
ports = Seq(
generateTestPort(
"lib",
Some(libWidth),
Some(libDepth),
maskGran = libMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateMemSRAM(): SRAMMacro = {
SRAMMacro(
name = mem_name,
width = memWidth,
depth = memDepth,
family = "1rw",
ports = Seq(
generateTestPort(
"outer",
Some(memWidth),
Some(memDepth),
maskGran = memMaskGran,
write = true,
writeEnable = true,
read = true,
readEnable = true
)
)
)
}
override def generateBody() =
"""
inst mem_0_0 of awesome_lib_mem
inst mem_0_1 of awesome_lib_mem
inst mem_0_2 of awesome_lib_mem
inst mem_0_3 of awesome_lib_mem
mem_0_0.lib_clk <= outer_clk
mem_0_0.lib_addr <= outer_addr
node outer_dout_0_0 = bits(mem_0_0.lib_dout, 7, 0)
mem_0_0.lib_din <= bits(outer_din, 7, 0)
mem_0_0.lib_read_en <= and(outer_read_en, UInt<1>("h1"))
mem_0_0.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_1.lib_clk <= outer_clk
mem_0_1.lib_addr <= outer_addr
node outer_dout_0_1 = bits(mem_0_1.lib_dout, 7, 0)
mem_0_1.lib_din <= bits(outer_din, 15, 8)
mem_0_1.lib_read_en <= and(outer_read_en, UInt<1>("h1"))
mem_0_1.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_2.lib_clk <= outer_clk
mem_0_2.lib_addr <= outer_addr
node outer_dout_0_2 = bits(mem_0_2.lib_dout, 7, 0)
mem_0_2.lib_din <= bits(outer_din, 23, 16)
mem_0_2.lib_read_en <= and(outer_read_en, UInt<1>("h1"))
mem_0_2.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_3.lib_clk <= outer_clk
mem_0_3.lib_addr <= outer_addr
node outer_dout_0_3 = bits(mem_0_3.lib_dout, 7, 0)
mem_0_3.lib_din <= bits(outer_din, 31, 24)
mem_0_3.lib_read_en <= and(outer_read_en, UInt<1>("h1"))
mem_0_3.lib_write_en <= and(and(and(outer_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
node outer_dout_0 = cat(outer_dout_0_3, cat(outer_dout_0_2, cat(outer_dout_0_1, outer_dout_0_0)))
outer_dout <= mux(UInt<1>("h1"), outer_dout_0, UInt<32>("h0"))
"""
compileExecuteAndTest(mem, lib, v, output)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,455 +0,0 @@
package barstools.macros
// Test flop synthesis of the memory compiler.
trait HasSynFlopsTestGenerator extends HasSimpleTestGenerator {
this: MacroCompilerSpec with HasSRAMGenerator =>
def generateFlops(): String = {
s"""
inst mem_0_0 of split_$lib_name
mem_0_0.${libPortPrefix}_clk <= ${libPortPrefix}_clk
mem_0_0.${libPortPrefix}_addr <= ${libPortPrefix}_addr
node ${libPortPrefix}_dout_0_0 = bits(mem_0_0.${libPortPrefix}_dout, ${libWidth - 1}, 0)
mem_0_0.${libPortPrefix}_din <= bits(${libPortPrefix}_din, ${libWidth - 1}, 0)
mem_0_0.${libPortPrefix}_write_en <= and(and(and(${libPortPrefix}_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
node ${libPortPrefix}_dout_0 = ${libPortPrefix}_dout_0_0
${libPortPrefix}_dout <= mux(UInt<1>("h1"), ${libPortPrefix}_dout_0, UInt<$libWidth>("h0"))
module split_$lib_name :
input ${libPortPrefix}_addr : UInt<$lib_addr_width>
input ${libPortPrefix}_clk : Clock
input ${libPortPrefix}_din : UInt<$libWidth>
output ${libPortPrefix}_dout : UInt<$libWidth>
input ${libPortPrefix}_write_en : UInt<1>
mem ram :
data-type => UInt<$libWidth>
depth => $libDepth
read-latency => 1
write-latency => 1
readwriter => RW_0
read-under-write => undefined
ram.RW_0.clk <= ${libPortPrefix}_clk
ram.RW_0.addr <= ${libPortPrefix}_addr
ram.RW_0.en <= UInt<1>("h1")
ram.RW_0.wmode <= ${libPortPrefix}_write_en
ram.RW_0.wmask <= UInt<1>("h1")
${libPortPrefix}_dout <= ram.RW_0.rdata
ram.RW_0.wdata <= ${libPortPrefix}_din
"""
}
// If there is no lib, put the flops definition into the body.
abstract override def generateBody(): String = {
if (this.isInstanceOf[HasNoLibTestGenerator]) {
generateFlops()
} else {
super.generateBody()
}
}
// If there is no lib, don't generate a footer, since the flops definition
// will be in the body.
override def generateFooter(): String = {
if (this.isInstanceOf[HasNoLibTestGenerator]) ""
else
s"""
module $lib_name :
${generateFooterPorts()}
${generateFlops()}
"""
}
}
class Synflops2048x8_noLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasNoLibTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(2048)
override lazy val memWidth = 8
compileExecuteAndTest(mem, None, v, output, synflops = true)
}
class Synflops2048x16_noLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasNoLibTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(2048)
override lazy val memWidth = 16
compileExecuteAndTest(mem, None, v, output, synflops = true)
}
class Synflops8192x16_noLib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasNoLibTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(8192)
override lazy val memWidth = 16
compileExecuteAndTest(mem, None, v, output, synflops = true)
}
class Synflops2048x16_depth_Lib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val width = 16
compileExecuteAndTest(mem, lib, v, output, synflops = true)
}
class Synflops2048x64_width_Lib
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleWidthTestGenerator
with HasSynFlopsTestGenerator {
override lazy val memWidth = 64
override lazy val libWidth = 8
override lazy val depth = BigInt(1024)
compileExecuteAndTest(mem, lib, v, output, synflops = true)
}
class Synflops_SplitPorts_Read_Write
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with HasSynFlopsTestGenerator {
import mdf.macrolib._
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val width = 8
override def generateLibSRAM(): SRAMMacro = SRAMMacro(
name = lib_name,
width = width,
depth = libDepth,
family = "1r1w",
ports = Seq(
generateReadPort("innerA", width, libDepth),
generateWritePort("innerB", width, libDepth)
)
)
override def generateMemSRAM(): SRAMMacro = SRAMMacro(
name = mem_name,
width = width,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateReadPort("outerB", width, memDepth),
generateWritePort("outerA", width, memDepth)
)
)
override def generateHeader() =
"""
circuit target_memory :
module target_memory :
input outerB_addr : UInt<11>
input outerB_clk : Clock
output outerB_dout : UInt<8>
input outerA_addr : UInt<11>
input outerA_clk : Clock
input outerA_din : UInt<8>
input outerA_write_en : UInt<1>
"""
override def generateBody() =
"""
node outerB_addr_sel = bits(outerB_addr, 10, 10)
reg outerB_addr_sel_reg : UInt<1>, outerB_clk with :
reset => (UInt<1>("h0"), outerB_addr_sel_reg)
outerB_addr_sel_reg <= mux(UInt<1>("h1"), outerB_addr_sel, outerB_addr_sel_reg)
node outerA_addr_sel = bits(outerA_addr, 10, 10)
inst mem_0_0 of awesome_lib_mem
mem_0_0.innerB_clk <= outerA_clk
mem_0_0.innerB_addr <= outerA_addr
mem_0_0.innerB_din <= bits(outerA_din, 7, 0)
mem_0_0.innerB_write_en <= and(and(and(outerA_write_en, UInt<1>("h1")), UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h0")))
mem_0_0.innerA_clk <= outerB_clk
mem_0_0.innerA_addr <= outerB_addr
node outerB_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
node outerB_dout_0 = outerB_dout_0_0
inst mem_1_0 of awesome_lib_mem
mem_1_0.innerB_clk <= outerA_clk
mem_1_0.innerB_addr <= outerA_addr
mem_1_0.innerB_din <= bits(outerA_din, 7, 0)
mem_1_0.innerB_write_en <= and(and(and(outerA_write_en, UInt<1>("h1")), UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h1")))
mem_1_0.innerA_clk <= outerB_clk
mem_1_0.innerA_addr <= outerB_addr
node outerB_dout_1_0 = bits(mem_1_0.innerA_dout, 7, 0)
node outerB_dout_1 = outerB_dout_1_0
outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<8>("h0")))
"""
override def generateFooterPorts() =
"""
input innerA_addr : UInt<10>
input innerA_clk : Clock
output innerA_dout : UInt<8>
input innerB_addr : UInt<10>
input innerB_clk : Clock
input innerB_din : UInt<8>
input innerB_write_en : UInt<1>
"""
override def generateFlops() =
"""
inst mem_0_0 of split_awesome_lib_mem
mem_0_0.innerB_clk <= innerB_clk
mem_0_0.innerB_addr <= innerB_addr
mem_0_0.innerB_din <= bits(innerB_din, 7, 0)
mem_0_0.innerB_write_en <= and(and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1")), UInt<1>("h1"))
mem_0_0.innerA_clk <= innerA_clk
mem_0_0.innerA_addr <= innerA_addr
node innerA_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
node innerA_dout_0 = innerA_dout_0_0
innerA_dout <= mux(UInt<1>("h1"), innerA_dout_0, UInt<8>("h0"))
module split_awesome_lib_mem :
input innerA_addr : UInt<10>
input innerA_clk : Clock
output innerA_dout : UInt<8>
input innerB_addr : UInt<10>
input innerB_clk : Clock
input innerB_din : UInt<8>
input innerB_write_en : UInt<1>
mem ram :
data-type => UInt<8>
depth => 1024
read-latency => 1
write-latency => 1
reader => R_0
writer => W_0
read-under-write => undefined
ram.R_0.clk <= innerA_clk
ram.R_0.addr <= innerA_addr
ram.R_0.en <= UInt<1>("h1")
innerA_dout <= ram.R_0.data
ram.W_0.clk <= innerB_clk
ram.W_0.addr <= innerB_addr
ram.W_0.en <= innerB_write_en
ram.W_0.mask <= UInt<1>("h1")
ram.W_0.data <= innerB_din
"""
"Non-masked split lib; split mem" should "syn flops fine" in {
compileExecuteAndTest(mem, lib, v, output, synflops = true)
}
}
class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite
extends MacroCompilerSpec
with HasSRAMGenerator
with HasSimpleDepthTestGenerator
with HasSynFlopsTestGenerator {
import mdf.macrolib._
override lazy val memDepth = BigInt(2048)
override lazy val libDepth = BigInt(1024)
override lazy val width = 8
override lazy val memMaskGran: Option[Int] = Some(8)
override lazy val libMaskGran: Option[Int] = Some(1)
override def generateLibSRAM(): SRAMMacro = SRAMMacro(
name = lib_name,
width = width,
depth = libDepth,
family = "1r1w",
ports = Seq(
generateReadPort("innerA", width, libDepth),
generateWritePort("innerB", width, libDepth, libMaskGran)
)
)
override def generateMemSRAM(): SRAMMacro = SRAMMacro(
name = mem_name,
width = width,
depth = memDepth,
family = "1r1w",
ports = Seq(
generateReadPort("outerB", width, memDepth),
generateWritePort("outerA", width, memDepth, memMaskGran)
)
)
override def generateHeader() =
"""
circuit target_memory :
module target_memory :
input outerB_addr : UInt<11>
input outerB_clk : Clock
output outerB_dout : UInt<8>
input outerA_addr : UInt<11>
input outerA_clk : Clock
input outerA_din : UInt<8>
input outerA_write_en : UInt<1>
input outerA_mask : UInt<1>
"""
override def generateBody() =
"""
node outerB_addr_sel = bits(outerB_addr, 10, 10)
reg outerB_addr_sel_reg : UInt<1>, outerB_clk with :
reset => (UInt<1>("h0"), outerB_addr_sel_reg)
outerB_addr_sel_reg <= mux(UInt<1>("h1"), outerB_addr_sel, outerB_addr_sel_reg)
node outerA_addr_sel = bits(outerA_addr, 10, 10)
inst mem_0_0 of awesome_lib_mem
mem_0_0.innerB_clk <= outerA_clk
mem_0_0.innerB_addr <= outerA_addr
mem_0_0.innerB_din <= bits(outerA_din, 7, 0)
mem_0_0.innerB_mask <= cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), bits(outerA_mask, 0, 0))))))))
mem_0_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h0")))
mem_0_0.innerA_clk <= outerB_clk
mem_0_0.innerA_addr <= outerB_addr
node outerB_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
node outerB_dout_0 = outerB_dout_0_0
inst mem_1_0 of awesome_lib_mem
mem_1_0.innerB_clk <= outerA_clk
mem_1_0.innerB_addr <= outerA_addr
mem_1_0.innerB_din <= bits(outerA_din, 7, 0)
mem_1_0.innerB_mask <= cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), bits(outerA_mask, 0, 0))))))))
mem_1_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h1")))
mem_1_0.innerA_clk <= outerB_clk
mem_1_0.innerA_addr <= outerB_addr
node outerB_dout_1_0 = bits(mem_1_0.innerA_dout, 7, 0)
node outerB_dout_1 = outerB_dout_1_0
outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<8>("h0")))
"""
override def generateFooterPorts() =
"""
input innerA_addr : UInt<10>
input innerA_clk : Clock
output innerA_dout : UInt<8>
input innerB_addr : UInt<10>
input innerB_clk : Clock
input innerB_din : UInt<8>
input innerB_write_en : UInt<1>
input innerB_mask : UInt<8>
"""
override def generateFlops() =
"""
inst mem_0_0 of split_awesome_lib_mem
inst mem_0_1 of split_awesome_lib_mem
inst mem_0_2 of split_awesome_lib_mem
inst mem_0_3 of split_awesome_lib_mem
inst mem_0_4 of split_awesome_lib_mem
inst mem_0_5 of split_awesome_lib_mem
inst mem_0_6 of split_awesome_lib_mem
inst mem_0_7 of split_awesome_lib_mem
mem_0_0.innerB_clk <= innerB_clk
mem_0_0.innerB_addr <= innerB_addr
mem_0_0.innerB_din <= bits(innerB_din, 0, 0)
mem_0_0.innerB_mask <= bits(innerB_mask, 0, 0)
mem_0_0.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_1.innerB_clk <= innerB_clk
mem_0_1.innerB_addr <= innerB_addr
mem_0_1.innerB_din <= bits(innerB_din, 1, 1)
mem_0_1.innerB_mask <= bits(innerB_mask, 1, 1)
mem_0_1.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_2.innerB_clk <= innerB_clk
mem_0_2.innerB_addr <= innerB_addr
mem_0_2.innerB_din <= bits(innerB_din, 2, 2)
mem_0_2.innerB_mask <= bits(innerB_mask, 2, 2)
mem_0_2.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_3.innerB_clk <= innerB_clk
mem_0_3.innerB_addr <= innerB_addr
mem_0_3.innerB_din <= bits(innerB_din, 3, 3)
mem_0_3.innerB_mask <= bits(innerB_mask, 3, 3)
mem_0_3.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_4.innerB_clk <= innerB_clk
mem_0_4.innerB_addr <= innerB_addr
mem_0_4.innerB_din <= bits(innerB_din, 4, 4)
mem_0_4.innerB_mask <= bits(innerB_mask, 4, 4)
mem_0_4.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_5.innerB_clk <= innerB_clk
mem_0_5.innerB_addr <= innerB_addr
mem_0_5.innerB_din <= bits(innerB_din, 5, 5)
mem_0_5.innerB_mask <= bits(innerB_mask, 5, 5)
mem_0_5.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_6.innerB_clk <= innerB_clk
mem_0_6.innerB_addr <= innerB_addr
mem_0_6.innerB_din <= bits(innerB_din, 6, 6)
mem_0_6.innerB_mask <= bits(innerB_mask, 6, 6)
mem_0_6.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_7.innerB_clk <= innerB_clk
mem_0_7.innerB_addr <= innerB_addr
mem_0_7.innerB_din <= bits(innerB_din, 7, 7)
mem_0_7.innerB_mask <= bits(innerB_mask, 7, 7)
mem_0_7.innerB_write_en <= and(and(innerB_write_en, UInt<1>("h1")), UInt<1>("h1"))
mem_0_0.innerA_clk <= innerA_clk
mem_0_0.innerA_addr <= innerA_addr
node innerA_dout_0_0 = bits(mem_0_0.innerA_dout, 0, 0)
mem_0_1.innerA_clk <= innerA_clk
mem_0_1.innerA_addr <= innerA_addr
node innerA_dout_0_1 = bits(mem_0_1.innerA_dout, 0, 0)
mem_0_2.innerA_clk <= innerA_clk
mem_0_2.innerA_addr <= innerA_addr
node innerA_dout_0_2 = bits(mem_0_2.innerA_dout, 0, 0)
mem_0_3.innerA_clk <= innerA_clk
mem_0_3.innerA_addr <= innerA_addr
node innerA_dout_0_3 = bits(mem_0_3.innerA_dout, 0, 0)
mem_0_4.innerA_clk <= innerA_clk
mem_0_4.innerA_addr <= innerA_addr
node innerA_dout_0_4 = bits(mem_0_4.innerA_dout, 0, 0)
mem_0_5.innerA_clk <= innerA_clk
mem_0_5.innerA_addr <= innerA_addr
node innerA_dout_0_5 = bits(mem_0_5.innerA_dout, 0, 0)
mem_0_6.innerA_clk <= innerA_clk
mem_0_6.innerA_addr <= innerA_addr
node innerA_dout_0_6 = bits(mem_0_6.innerA_dout, 0, 0)
mem_0_7.innerA_clk <= innerA_clk
mem_0_7.innerA_addr <= innerA_addr
node innerA_dout_0_7 = bits(mem_0_7.innerA_dout, 0, 0)
node innerA_dout_0 = cat(innerA_dout_0_7, cat(innerA_dout_0_6, cat(innerA_dout_0_5, cat(innerA_dout_0_4, cat(innerA_dout_0_3, cat(innerA_dout_0_2, cat(innerA_dout_0_1, innerA_dout_0_0)))))))
innerA_dout <= mux(UInt<1>("h1"), innerA_dout_0, UInt<8>("h0"))
module split_awesome_lib_mem :
input innerA_addr : UInt<10>
input innerA_clk : Clock
output innerA_dout : UInt<1>
input innerB_addr : UInt<10>
input innerB_clk : Clock
input innerB_din : UInt<1>
input innerB_write_en : UInt<1>
input innerB_mask : UInt<1>
mem ram :
data-type => UInt<1>
depth => 1024
read-latency => 1
write-latency => 1
reader => R_0
writer => W_0
read-under-write => undefined
ram.R_0.clk <= innerA_clk
ram.R_0.addr <= innerA_addr
ram.R_0.en <= UInt<1>("h1")
innerA_dout <= ram.R_0.data
ram.W_0.clk <= innerB_clk
ram.W_0.addr <= innerB_addr
ram.W_0.en <= innerB_write_en
ram.W_0.mask <= innerB_mask
ram.W_0.data <= innerB_din
"""
"masked split lib; masked split mem" should "syn flops fine" in {
compileExecuteAndTest(mem, lib, v, output, synflops = true)
}
}

View File

@@ -1,104 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
package barstools.tapeout.transforms
import chisel3._
import chisel3.experimental.ExtModule
import chisel3.stage.ChiselStage
import firrtl.FileUtils
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.must.Matchers.be
import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
import java.io.{File, PrintWriter}
class BlackBoxInverter extends ExtModule {
val in = IO(Input(Bool()))
val out = IO(Output(Bool()))
}
class GenerateExampleModule extends Module {
val in = IO(Input(Bool()))
val out = IO(Output(Bool()))
val inverter = Module(new BlackBoxInverter)
inverter.in := in
val inverted = inverter.out
val reg = RegInit(0.U(8.W))
reg := reg + inverted.asUInt
out := reg
}
class ToBeMadeExternal extends Module {
val in = IO(Input(Bool()))
val out = IO(Output(Bool()))
val reg = RegInit(0.U(8.W))
reg := reg + in.asUInt + 2.U
out := reg
}
class GenerateExampleTester extends Module {
val success = IO(Output(Bool()))
val mod = Module(new GenerateExampleModule)
mod.in := 1.U
val mod2 = Module(new ToBeMadeExternal)
mod2.in := 1.U
val reg = RegInit(0.U(8.W))
reg := reg + mod.out + mod2.out
success := reg === 100.U
when(reg === 100.U) {
stop()
}
}
class GenerateSpec extends AnyFreeSpec {
def generateTestData(targetDir: String): Unit = {
FileUtils.makeDirectory(targetDir)
new ChiselStage().emitFirrtl(new GenerateExampleTester, Array("--target-dir", targetDir))
val blackBoxInverterText =
"""
|module BlackBoxInverter(
| input [0:0] in,
| output [0:0] out
|);
| assign out = !in;
|endmodule
|""".stripMargin
val printWriter2 = new PrintWriter(new File(s"$targetDir/BlackBoxInverter.v"))
printWriter2.write(blackBoxInverterText)
printWriter2.close()
}
"generate test data" in {
val targetDir = "test_run_dir/generate_spec_source"
generateTestData(targetDir)
new File(s"$targetDir/GenerateExampleTester.fir").exists() should be(true)
}
"generate top test" in {
val targetDir = "test_run_dir/generate_spec"
generateTestData(targetDir)
GenerateModelStageMain.main(
Array(
"-i",
s"$targetDir/GenerateExampleTester.fir",
"-o",
s"$targetDir/GenerateExampleTester.v"
)
)
new File(s"$targetDir/GenerateExampleTester.v").exists() should be(true)
}
}

View File

@@ -1,119 +0,0 @@
// See LICENSE for license details.
package barstools.tapeout.transforms.retime
import chisel3._
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import firrtl.{EmittedFirrtlCircuitAnnotation, EmittedFirrtlModuleAnnotation, FileUtils}
import logger.Logger
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class RetimeSpec extends AnyFlatSpec with Matchers {
def normalized(s: String): String = {
require(!s.contains("\n"))
s.replaceAll("\\s+", " ").trim
}
def uniqueDirName[T](gen: => T, name: String): String = {
val genClassName = gen.getClass.getName
name + genClassName.hashCode.abs
}
def getLowFirrtl[T <: RawModule](gen: () => T, extraArgs: Array[String] = Array.empty): String = {
// generate low firrtl
(new ChiselStage)
.execute(
Array("-X", "low") ++ extraArgs,
Seq(ChiselGeneratorAnnotation(gen))
)
.collect {
case EmittedFirrtlCircuitAnnotation(a) => a
case EmittedFirrtlModuleAnnotation(a) => a
}
.map(_.value)
.mkString("")
}
behavior.of("retime library")
it should "pass simple retime module annotation" in {
val gen = () => new RetimeModule
val dir = uniqueDirName(gen, "RetimeModule")
Logger.makeScope(Seq.empty) {
val captor = new Logger.OutputCaptor
Logger.setOutput(captor.printStream)
// generate low firrtl
val firrtl = getLowFirrtl(
gen,
Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final", "--log-level", "info")
)
firrtl.nonEmpty should be(true)
//Make sure we got the RetimeTransform scheduled
captor.getOutputAsString should include("barstools.tapeout.transforms.retime.RetimeTransform")
}
val lines = FileUtils
.getLines(s"test_run_dir/$dir/test_run_dir/$dir/final.anno.json")
.map(normalized)
.mkString("\n")
lines should include("barstools.tapeout.transforms.retime.RetimeAnnotation")
lines should include(""""target":"RetimeModule.RetimeModule"""")
}
it should "pass simple retime instance annotation" in {
val gen = () => new RetimeInstance
val dir = uniqueDirName(gen, "RetimeInstance")
Logger.makeScope(Seq.empty) {
val captor = new Logger.OutputCaptor
Logger.setOutput(captor.printStream)
// generate low firrtl
val firrtl = getLowFirrtl(
gen,
Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final", "--log-level", "info")
)
firrtl.nonEmpty should be(true)
//Make sure we got the RetimeTransform scheduled
captor.getOutputAsString should include("barstools.tapeout.transforms.retime.RetimeTransform")
}
val lines = FileUtils
.getLines(s"test_run_dir/$dir/test_run_dir/$dir/final.anno.json")
.map(normalized)
.mkString("\n")
lines should include("barstools.tapeout.transforms.retime.RetimeAnnotation")
lines should include(""""target":"RetimeInstance.MyModule"""")
}
}
class RetimeModule extends Module with RetimeLib {
val io = IO(new Bundle {
val in = Input(UInt(15.W))
val out = Output(UInt(15.W))
})
io.out := io.in
retime(this)
}
class MyModule extends Module with RetimeLib {
val io = IO(new Bundle {
val in = Input(UInt(15.W))
val out = Output(UInt(15.W))
})
io.out := io.in
}
class RetimeInstance extends Module with RetimeLib {
val io = IO(new Bundle {
val in = Input(UInt(15.W))
val out = Output(UInt(15.W))
})
val instance = Module(new MyModule)
retime(instance)
instance.io.in := io.in
io.out := instance.io.out
}

View File

@@ -1,101 +0,0 @@
package mdf.macrolib
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class ConfReaderSpec extends AnyFlatSpec with Matchers {
/** Generate a read port in accordance with RenameAnnotatedMemoryPorts. */
def generateReadPort(num: Int, width: Int, depth: Int): MacroPort = {
MacroPort(
address = PolarizedPort(s"R${num}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"R${num}_clk", PositiveEdge)),
output = Some(PolarizedPort(s"R${num}_data", ActiveHigh)),
width = Some(width),
depth = Some(depth)
)
}
/** Generate a write port in accordance with RenameAnnotatedMemoryPorts. */
def generateWritePort(num: Int, width: Int, depth: Int, maskGran: Option[Int] = None): MacroPort = {
MacroPort(
address = PolarizedPort(s"W${num}_addr", ActiveHigh),
clock = Some(PolarizedPort(s"W${num}_clk", PositiveEdge)),
input = Some(PolarizedPort(s"W${num}_data", ActiveHigh)),
maskPort = if (maskGran.isDefined) Some(PolarizedPort(s"W${num}_mask", ActiveHigh)) else None,
maskGran = maskGran,
width = Some(184),
depth = Some(128)
)
}
"ConfReader" should "read a 1rw conf line" in {
val confStr = "name Foo_Bar_mem123_ext depth 128 width 184 ports mrw mask_gran 23"
ConfReader.readSingleLine(confStr) shouldBe SRAMMacro(
name = "Foo_Bar_mem123_ext",
width = 184,
depth = 128,
family = "1rw",
ports = List(
MacroPort(
address = PolarizedPort("RW0_addr", ActiveHigh),
clock = Some(PolarizedPort("RW0_clk", PositiveEdge)),
writeEnable = Some(PolarizedPort("RW0_wmode", ActiveHigh)),
output = Some(PolarizedPort("RW0_wdata", ActiveHigh)),
input = Some(PolarizedPort("RW0_rdata", ActiveHigh)),
maskPort = Some(PolarizedPort("RW0_wmask", ActiveHigh)),
maskGran = Some(23),
width = Some(184),
depth = Some(128)
)
),
extraPorts = List()
)
}
"ConfReader" should "read a 1r1w conf line" in {
val confStr = "name Foo_Bar_mem321_ext depth 128 width 184 ports read,mwrite mask_gran 23"
ConfReader.readSingleLine(confStr) shouldBe SRAMMacro(
name = "Foo_Bar_mem321_ext",
width = 184,
depth = 128,
family = "1r1w",
ports = List(
generateReadPort(0, 184, 128),
generateWritePort(0, 184, 128, Some(23))
),
extraPorts = List()
)
}
"ConfReader" should "read a mixed 1r2w conf line" in {
val confStr = "name Foo_Bar_mem321_ext depth 128 width 184 ports read,mwrite,write mask_gran 23"
ConfReader.readSingleLine(confStr) shouldBe SRAMMacro(
name = "Foo_Bar_mem321_ext",
width = 184,
depth = 128,
family = "1r2w",
ports = List(
generateReadPort(0, 184, 128),
generateWritePort(0, 184, 128, Some(23)),
generateWritePort(1, 184, 128)
),
extraPorts = List()
)
}
"ConfReader" should "read a 42r29w conf line" in {
val confStr =
"name Foo_Bar_mem321_ext depth 128 width 184 ports " + (Seq.fill(42)("read") ++ Seq.fill(29)("mwrite"))
.mkString(",") + " mask_gran 23"
ConfReader.readSingleLine(confStr) shouldBe SRAMMacro(
name = "Foo_Bar_mem321_ext",
width = 184,
depth = 128,
family = "42r29w",
ports = ((0 to 41).map((num: Int) => generateReadPort(num, 184, 128))) ++
((0 to 28).map((num: Int) => generateWritePort(num, 184, 128, Some(23)))),
extraPorts = List()
)
}
}

View File

@@ -1,15 +0,0 @@
package mdf.macrolib
import firrtl.FileUtils
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class FlipChipMacroSpec extends AnyFlatSpec with Matchers {
"Parsing flipchipmacros" should "work" in {
val stream = FileUtils.getLinesResource("/bumps.json")
val mdf = Utils.readMDFFromString(stream.mkString("\n"))
mdf match {
case Some(Seq(fcp: FlipChipMacro)) => println(fcp.visualize)
}
}
}

View File

@@ -1,67 +0,0 @@
package mdf.macrolib
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class IOMacroSpec extends AnyFlatSpec with Matchers {
"Ground IOs" should "be detected" in {
val json =
"""{
| "name" : "GND",
| "type" : "ground"
|}""".stripMargin
val m = JSONUtils.readStringValueMap(json).get
IOMacro.parseJSON(m) shouldBe Some(IOMacro("GND", Ground))
}
"Power IOs" should "be detected" in {
val json =
"""{
| "name" : "VDD0V8",
| "type" : "power"
|}""".stripMargin
val m = JSONUtils.readStringValueMap(json).get
IOMacro.parseJSON(m) shouldBe Some(IOMacro("VDD0V8", Power))
}
"Digital IOs" should "be detected" in {
val json =
"""{
| "name" : "VDDC0_SEL[1:0]",
| "type" : "digital",
| "direction" : "output",
| "termination" : "CMOS"
|}""".stripMargin
val m = JSONUtils.readStringValueMap(json).get
IOMacro.parseJSON(m) shouldBe Some(IOMacro("VDDC0_SEL[1:0]", Digital, Some(Output), Some(CMOS)))
}
"Digital IOs with termination" should "be detected" in {
val json =
"""{
| "name" : "CCLK1",
| "type" : "digital",
| "direction" : "input",
| "termination" : 50,
| "terminationType" : "single",
| "terminationReference" : "GND"
|}""".stripMargin
val m = JSONUtils.readStringValueMap(json).get
IOMacro.parseJSON(m) shouldBe Some(
IOMacro("CCLK1", Digital, Some(Input), Some(Resistive(50)), Some(Single), Some("GND"))
)
}
"Digital IOs with matching and termination" should "be detected" in {
val json =
"""{
| "name" : "REFCLK0P",
| "type" : "analog",
| "direction" : "input",
| "match" : ["REFCLK0N"],
| "termination" : 100,
| "terminationType" : "differential",
| "terminationReference" : "GND"
|}""".stripMargin
val m = JSONUtils.readStringValueMap(json).get
IOMacro.parseJSON(m) shouldBe Some(
IOMacro("REFCLK0P", Analog, Some(Input), Some(Resistive(100)), Some(Differential), Some("GND"), List("REFCLK0N"))
)
}
}

View File

@@ -1,15 +0,0 @@
package mdf.macrolib
import firrtl.FileUtils
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class IOPropertiesSpec extends AnyFlatSpec with Matchers {
"Parsing io_properties" should "work" in {
val stream = FileUtils.getLinesResource("/io_properties.json")
val mdf = Utils.readMDFFromString(stream.mkString("\n"))
mdf match {
case Some(Seq(fcp: IOProperties)) =>
}
}
}

View File

@@ -1,270 +0,0 @@
package mdf.macrolib
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import play.api.libs.json._
import java.io.File
// Output tests (Scala -> JSON).
// TODO: unify these tests with the input tests?
trait HasAwesomeMemData {
def getAwesomeMem() = {
SRAMMacro(
name = "awesome_mem",
width = 32,
depth = 1024,
family = "1rw",
ports = Seq(
MacroPort(
address = PolarizedPort(name = "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = "clk", polarity = PositiveEdge)),
writeEnable = Some(PolarizedPort(name = "write_enable", polarity = ActiveHigh)),
readEnable = Some(PolarizedPort(name = "read_enable", polarity = ActiveHigh)),
chipEnable = Some(PolarizedPort(name = "chip_enable", polarity = ActiveHigh)),
output = Some(PolarizedPort(name = "data_out", polarity = ActiveHigh)),
input = Some(PolarizedPort(name = "data_in", polarity = ActiveHigh)),
maskPort = Some(PolarizedPort(name = "mask", polarity = ActiveHigh)),
maskGran = Some(8),
width = Some(32),
depth = Some(1024) // These numbers don't matter.
)
),
extraPorts = List()
)
}
def getAwesomeMemJSON(): String = {
"""
| {
| "type": "sram",
| "name": "awesome_mem",
| "width": 32,
| "depth": "1024",
| "mux": 1,
| "mask":true,
| "family": "1rw",
| "ports": [
| {
| "address port name": "addr",
| "address port polarity": "active high",
| "clock port name": "clk",
| "clock port polarity": "positive edge",
| "write enable port name": "write_enable",
| "write enable port polarity": "active high",
| "read enable port name": "read_enable",
| "read enable port polarity": "active high",
| "chip enable port name": "chip_enable",
| "chip enable port polarity": "active high",
| "output port name": "data_out",
| "output port polarity": "active high",
| "input port name": "data_in",
| "input port polarity": "active high",
| "mask port name": "mask",
| "mask port polarity": "active high",
| "mask granularity": 8
| }
| ]
| }
|""".stripMargin
}
}
// Tests for filler macros.
class FillerMacroOutput extends AnyFlatSpec with Matchers {
"Valid lvt macro" should "be generated" in {
val expected = """
| {
| "type": "filler cell",
| "name": "MY_FILLER_CELL",
| "vt": "lvt"
| }
|""".stripMargin
FillerMacro("MY_FILLER_CELL", "lvt").toJSON shouldBe Json.parse(expected)
}
"Valid metal macro" should "be generated" in {
val expected = """
| {
| "type": "metal filler cell",
| "name": "METAL_FILLER_CELL",
| "vt": "lvt"
| }
|""".stripMargin
MetalFillerMacro("METAL_FILLER_CELL", "lvt").toJSON shouldBe Json.parse(expected)
}
"Valid hvt macro" should "be generated" in {
val expected = """
| {
| "type": "filler cell",
| "name": "HVT_CELL_PROP",
| "vt": "hvt"
| }
|""".stripMargin
FillerMacro("HVT_CELL_PROP", "hvt").toJSON shouldBe Json.parse(expected)
}
}
class SRAMPortOutput extends AnyFlatSpec with Matchers {
"Extra port" should "be generated" in {
val m = MacroExtraPort(
name = "TIE_HIGH",
width = 8,
portType = Constant,
value = ((1 << 8) - 1)
)
val expected = """
| {
| "type": "constant",
| "name": "TIE_HIGH",
| "width": 8,
| "value": 255
| }
|""".stripMargin
m.toJSON shouldBe Json.parse(expected)
}
"Minimal write port" should "be generated" in {
val m = MacroPort(
address = PolarizedPort(name = "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = "clk", polarity = PositiveEdge)),
writeEnable = Some(PolarizedPort(name = "write_enable", polarity = ActiveHigh)),
input = Some(PolarizedPort(name = "data_in", polarity = ActiveHigh)),
width = Some(32),
depth = Some(1024) // These numbers don't matter.
)
val expected = """
| {
| "address port name": "addr",
| "address port polarity": "active high",
| "clock port name": "clk",
| "clock port polarity": "positive edge",
| "write enable port name": "write_enable",
| "write enable port polarity": "active high",
| "input port name": "data_in",
| "input port polarity": "active high"
| }
|""".stripMargin
m.toJSON shouldBe Json.parse(expected)
}
"Minimal read port" should "be generated" in {
val m = MacroPort(
address = PolarizedPort(name = "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = "clk", polarity = PositiveEdge)),
output = Some(PolarizedPort(name = "data_out", polarity = ActiveHigh)),
width = Some(32),
depth = Some(1024) // These numbers don't matter.
)
val expected = """
| {
| "address port name": "addr",
| "address port polarity": "active high",
| "clock port name": "clk",
| "clock port polarity": "positive edge",
| "output port name": "data_out",
| "output port polarity": "active high"
| }
|""".stripMargin
m.toJSON shouldBe Json.parse(expected)
}
"Masked read port" should "be generated" in {
val m = MacroPort(
address = PolarizedPort(name = "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = "clk", polarity = PositiveEdge)),
output = Some(PolarizedPort(name = "data_out", polarity = ActiveHigh)),
maskPort = Some(PolarizedPort(name = "mask", polarity = ActiveHigh)),
maskGran = Some(8),
width = Some(32),
depth = Some(1024) // These numbers don't matter.
)
val expected = """
| {
| "address port name": "addr",
| "address port polarity": "active high",
| "clock port name": "clk",
| "clock port polarity": "positive edge",
| "output port name": "data_out",
| "output port polarity": "active high",
| "mask port name": "mask",
| "mask port polarity": "active high",
| "mask granularity": 8
| }
|""".stripMargin
m.toJSON shouldBe Json.parse(expected)
}
"Everything port" should "be generated" in {
val m = MacroPort(
address = PolarizedPort(name = "addr", polarity = ActiveHigh),
clock = Some(PolarizedPort(name = "clk", polarity = PositiveEdge)),
writeEnable = Some(PolarizedPort(name = "write_enable", polarity = ActiveHigh)),
readEnable = Some(PolarizedPort(name = "read_enable", polarity = ActiveHigh)),
chipEnable = Some(PolarizedPort(name = "chip_enable", polarity = ActiveHigh)),
output = Some(PolarizedPort(name = "data_out", polarity = ActiveHigh)),
input = Some(PolarizedPort(name = "data_in", polarity = ActiveHigh)),
maskPort = Some(PolarizedPort(name = "mask", polarity = ActiveHigh)),
maskGran = Some(8),
width = Some(32),
depth = Some(1024) // These numbers don't matter.
)
val expected = """
| {
| "address port name": "addr",
| "address port polarity": "active high",
| "clock port name": "clk",
| "clock port polarity": "positive edge",
| "write enable port name": "write_enable",
| "write enable port polarity": "active high",
| "read enable port name": "read_enable",
| "read enable port polarity": "active high",
| "chip enable port name": "chip_enable",
| "chip enable port polarity": "active high",
| "output port name": "data_out",
| "output port polarity": "active high",
| "input port name": "data_in",
| "input port polarity": "active high",
| "mask port name": "mask",
| "mask port polarity": "active high",
| "mask granularity": 8
| }
|""".stripMargin
m.toJSON shouldBe Json.parse(expected)
}
}
class SRAMMacroOutput extends AnyFlatSpec with Matchers with HasAwesomeMemData {
"SRAM macro" should "be generated" in {
val m = getAwesomeMem
val expected = getAwesomeMemJSON
m.toJSON shouldBe Json.parse(expected)
}
}
class InputOutput extends AnyFlatSpec with Matchers with HasAwesomeMemData {
"Read-write string" should "preserve data" in {
val mdf = List(
FillerMacro("MY_FILLER_CELL", "lvt"),
MetalFillerMacro("METAL_GEAR_FILLER", "hvt"),
getAwesomeMem
)
Utils.readMDFFromString(Utils.writeMDFToString(mdf)) shouldBe Some(mdf)
}
val testDir: String = "test_run_dir"
new File(testDir).mkdirs // Make sure the testDir exists
"Read-write file" should "preserve data" in {
val mdf = List(
FillerMacro("MY_FILLER_CELL", "lvt"),
MetalFillerMacro("METAL_GEAR_FILLER", "hvt"),
getAwesomeMem
)
val filename = testDir + "/" + "mdf_read_write_test.json"
Utils.writeMDFToPath(Some(filename), mdf) shouldBe true
Utils.readMDFFromPath(Some(filename)) shouldBe Some(mdf)
}
}

View File

@@ -1,406 +0,0 @@
package mdf.macrolib
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import play.api.libs.json._
object JSONUtils {
def readStringValueMap(str: String): Option[Map[String, JsValue]] = {
Json.parse(str) match {
case x: JsObject => Some(x.as[Map[String, JsValue]])
case _ => None
}
}
}
// Tests for filler macros
class FillerMacroSpec extends AnyFlatSpec with Matchers {
"Valid lvt macros" should "be detected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "filler cell",
| "name": "MY_FILLER_CELL",
| "vt": "lvt"
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe Some(FillerMacro("MY_FILLER_CELL", "lvt"))
}
"Valid metal macro" should "be detected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "metal filler cell",
| "name": "METAL_FILLER_CELL",
| "vt": "lvt"
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe Some(MetalFillerMacro("METAL_FILLER_CELL", "lvt"))
}
"Valid hvt macros" should "be detected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "filler cell",
| "name": "HVT_CELL_PROP",
| "vt": "hvt"
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe Some(FillerMacro("HVT_CELL_PROP", "hvt"))
}
"Empty name macros" should "be rejected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "filler cell",
| "name": "",
| "vt": "hvt"
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe None
}
"Empty vt macros" should "be rejected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "metal filler cell",
| "name": "DEAD_CELL",
| "vt": ""
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe None
}
"Missing vt macros" should "be rejected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "metal filler cell",
| "name": "DEAD_CELL"
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe None
}
"Missing name macros" should "be rejected" in {
val m = JSONUtils
.readStringValueMap("""
| {
| "type": "filler cell",
| "vt": ""
| }
|""".stripMargin)
.get
FillerMacroBase.parseJSON(m) shouldBe None
}
}
// Tests for SRAM type and associates.
class SRAMMacroSpec extends AnyFlatSpec with Matchers {
// Simple port which can be reused in tests
// Note: assume width=depth=simplePortConstant.
val simplePortConstant = 1024
def simplePort(
postfix: String = "",
width: Int = simplePortConstant,
depth: Int = simplePortConstant
): (String, MacroPort) = {
val json = s"""
{
"address port name": "A_${postfix}",
"address port polarity": "active high",
"clock port name": "CLK_${postfix}",
"clock port polarity": "positive edge",
"write enable port name": "WEN_${postfix}",
"write enable port polarity": "active high",
"read enable port name": "REN_${postfix}",
"read enable port polarity": "active high",
"chip enable port name": "CEN_${postfix}",
"chip enable port polarity": "active high",
"output port name": "OUT_${postfix}",
"output port polarity": "active high",
"input port name": "IN_${postfix}",
"input port polarity": "active high",
"mask granularity": 1,
"mask port name": "MASK_${postfix}",
"mask port polarity": "active high"
}
"""
val port = MacroPort(
address = PolarizedPort(s"A_${postfix}", ActiveHigh),
clock = Some(PolarizedPort(s"CLK_${postfix}", PositiveEdge)),
writeEnable = Some(PolarizedPort(s"WEN_${postfix}", ActiveHigh)),
readEnable = Some(PolarizedPort(s"REN_${postfix}", ActiveHigh)),
chipEnable = Some(PolarizedPort(s"CEN_${postfix}", ActiveHigh)),
output = Some(PolarizedPort(s"OUT_${postfix}", ActiveHigh)),
input = Some(PolarizedPort(s"IN_${postfix}", ActiveHigh)),
maskPort = Some(PolarizedPort(s"MASK_${postfix}", ActiveHigh)),
maskGran = Some(1),
width = Some(width),
depth = Some(depth)
)
(json, port)
}
"Simple port" should "be valid" in {
{
val (json, port) = simplePort("Simple1")
MacroPort.parseJSON(JSONUtils.readStringValueMap(json).get, simplePortConstant, simplePortConstant) shouldBe Some(
port
)
}
{
val (json, port) = simplePort("Simple2")
MacroPort.parseJSON(JSONUtils.readStringValueMap(json).get, simplePortConstant, simplePortConstant) shouldBe Some(
port
)
}
{
val (json, port) = simplePort("bar")
MacroPort.parseJSON(JSONUtils.readStringValueMap(json).get, simplePortConstant, simplePortConstant) shouldBe Some(
port
)
}
{
val (json, port) = simplePort("")
MacroPort.parseJSON(JSONUtils.readStringValueMap(json).get, simplePortConstant, simplePortConstant) shouldBe Some(
port
)
}
}
"Simple SRAM macro" should "be detected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "SRAMS_R_US",
"width": 2048,
"depth": "4096",
"family": "1rw",
"ports": [
${json}
]
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe Some(
SRAMMacro("SRAMS_R_US", width = 2048, depth = 4096, family = "1rw", ports = List(port), extraPorts = List())
)
}
"Non-power-of-two width & depth SRAM macro" should "be detected" in {
val (json, port) = simplePort("", 1234, 8888)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "SRAMS_R_US",
"width": 1234,
"depth": "8888",
"family": "1rw",
"ports": [
${json}
]
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe Some(
SRAMMacro("SRAMS_R_US", width = 1234, depth = 8888, family = "1rw", ports = List(port), extraPorts = List())
)
}
"Minimal memory port" should "be detected" in {
val (json, port) = simplePort("_A", 64, 1024)
val port2 = MacroPort(
address = PolarizedPort("A_B", ActiveHigh),
clock = Some(PolarizedPort("CLK_B", PositiveEdge)),
writeEnable = Some(PolarizedPort("WEN_B", ActiveHigh)),
readEnable = None,
chipEnable = None,
output = Some(PolarizedPort("OUT_B", ActiveHigh)),
input = Some(PolarizedPort("IN_B", ActiveHigh)),
maskPort = None,
maskGran = None,
width = Some(64),
depth = Some(1024)
)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "SRAMS_R_US",
"width": 64,
"depth": "1024",
"family": "2rw",
"ports": [
${json},
{
"address port name": "A_B",
"address port polarity": "active high",
"clock port name": "CLK_B",
"clock port polarity": "positive edge",
"write enable port name": "WEN_B",
"write enable port polarity": "active high",
"output port name": "OUT_B",
"output port polarity": "active high",
"input port name": "IN_B",
"input port polarity": "active high"
}
]
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe Some(
SRAMMacro("SRAMS_R_US", width = 64, depth = 1024, family = "2rw", ports = List(port, port2), extraPorts = List())
)
}
"Extra ports" should "be detected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "GOT_EXTRA",
"width": 2048,
"depth": "4096",
"family": "1rw",
"ports": [
${json}
],
"extra ports": [
{
"name": "TIE_DIE",
"width": 1,
"type": "constant",
"value": 1
},
{
"name": "TIE_MOO",
"width": 4,
"type": "constant",
"value": 0
}
]
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe Some(
SRAMMacro(
"GOT_EXTRA",
width = 2048,
depth = 4096,
family = "1rw",
ports = List(port),
extraPorts = List(
MacroExtraPort(
name = "TIE_DIE",
width = 1,
portType = Constant,
value = 1
),
MacroExtraPort(
name = "TIE_MOO",
width = 4,
portType = Constant,
value = 0
)
)
)
)
}
"Invalid port" should "be rejected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "SRAMS_R_US",
"width": 2048,
"depth": "4096",
"family": "1rw",
"ports": [
{
"address port name": "missing_polarity",
"output port name": "missing_clock"
}
]
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe None
}
"No ports" should "be rejected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "SRAMS_R_US",
"width": 2048,
"depth": "4096",
"family": "1rw"
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe None
}
"No family and ports" should "be rejected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "SRAMS_R_US",
"width": 2048,
"depth": "4096"
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe None
}
"String width" should "be rejected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "BAD_BAD_SRAM",
"width": "wide",
"depth": "4096"
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe None
}
"String depth" should "be rejected" in {
val (json, port) = simplePort("", 2048, 4096)
val m = JSONUtils
.readStringValueMap(s"""
{
"type": "sram",
"name": "BAD_BAD_SRAM",
"width": 512,
"depth": "octopus_under_the_sea"
}
""")
.get
SRAMMacro.parseJSON(m) shouldBe None
}
}