Remove barstools tests
This commit is contained in:
@@ -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
|
||||
@@ -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", "-"]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
// }
|
||||
// }
|
||||
@@ -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() = ""
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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)) =>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user